]> jfr.im git - irc/rqf/shadowircd.git/blame - doc/technical/linebuf.txt
Fix another typo.
[irc/rqf/shadowircd.git] / doc / technical / linebuf.txt
CommitLineData
212380e3 1
2linebuf - a dbuf replacement for the New World Order(tm)
3
4By Adrian Chadd <adrian@creative.net.au>
5
6$Id: linebuf.txt 6 2005-09-10 01:02:21Z nenolod $
7
8
9History
10-------
11
12I could probably learn the dbuf history, but basically its evil. The
13general idea is that a dbuf holds incoming and outgoing data streams.
14The trouble is that well.. it was evil. You can check it out by getting
15the old src/dbuf.c and include/dbuf.h files if you really want.
16
17
18Replacement
19-----------
20
21The linebuf system is a replacement for the dbuf code. The general idea here
22is that the data should be buffered in "lines" rather than just linearly
23like in the dbuf code. This lends to easier manipulation at a later date
24(think flushing data lines to a socket, and even "sharing" linebufs to
25reduce the copying required for one to many delivery.)
26
27The linebuf system is broken into two structures, the buf_head and buf_line .
28buf_head contains the buffer information (queue head/tail, length, allocated
29length and the write offset for flushing), and buf_line contains the
30line buffer information (buffer and various flags.)
31
32linebuf->terminated is *only* set when a CR/LF combination is received.
33
34linebuf->overflow is set if we get more data than we should, and we simply
35 truncate the incoming data.
36
37linebuf->flushing is set when we are currently writing the buffer. We should
38 _NEVER_ be appending to a buffer which we're flushing!
39
40When you get a buffer through linebuf_get() or write one through
41linebuf_flush(), it will *always* be terminated with a CR/LF (and a NUL if
42its a linebuf_get()).
43
44
45Linebuf manipulation
46--------------------
47
48To use a linebuf, you simply stick a buf_head_t in your structure somewhere.
49You then use the following routines:
50
51int
52linebuf_parse(buf_head_t *bufhead, char *buf, int len)
53
54Parse the given buf. This routine does some complex manipulation:
55
56- if there is an incomplete buffer at the tail, buf is parsed to try and
57 fill that incomplete buffer
58- a buffer is completed by a CR/LF/CRLF/LFCR. It accepts everything purely
59 because I wanted to be "liberal in what you accept" ..
60- If a buffer is terminated, the linebuf is flagged terminated
61- If more data is trying to be squeezed into the buffer than space LEFT
62 in the buffer, we skip to the next "CRLF", and tag the buffer terminated
63 _and_ overflowed.
64- We treat multiple runs of CR/LF/CRLF/LFCR as a single CRLF. This is just
65 a little extra goody to stop people sending hundreds of "CRLF"s and creating
66 unnecessary buffers.
67- The number of lines parsed is returned (so you can implement per-line flood
68 protection ..)
69
70
71void
72linebuf_put(buf_head_t *bufhead, char *buf, int len)
73
74Parse the given buf, ASSUMING it is a single buffer line. This is useful
75for server-generated messages where you know you have a single line, and
76you don't want to go through the overhead of parsing the data just for
77this.
78
79
80int
81linebuf_get(buf_head_t *bufhead, char *buf, int maxlen)
82
83Get a single line from the buffer. This removes data from the head of the
84buffer. If the first buffer is empty or is not terminated, 0 is returned
85which indicates that there is no data to parse. Terminated buffers are
86returned (CR/LF/NUL), and the length INCLUDING the CR/LF/NUL is returned.
87The buffer is copied and the linebuf is then deallocated.
88
89
90int
91linebuf_flush(int fd, buf_head_t *bufhead)
92
93Attempt to flush some data to the given socket. bufhead->writeofs tracks
94where in the head buffer we currently are. If the buffer is not terminated,
95-1 is returned with errno == EWOULDBLOCK to simulate a "retry me" condition.
96(See TODO..)
97
98linebuf_flush() returns whatever write() returns, and sets (ie doesn't touch
99after write()) errno accordingly.
100
101
102int
103linebuf_len(buf_head_t *bufhead)
104
105Return the length of the buffer, in bytes. This should be used when calculating
106how big a buffer is for statistics.
107
108
109int
110linebuf_alloclen(buf_head_t *bufhead)
111
112Return how big the *allocated* space is. This is much more suitable for
113anti-flood checking, as someone might be sending a whole bunch of 1-byte
114linebufs which might not trigger a recvq / sendq limit but might chew up
115way too much memory.
116
117
118
119Notes
120-----
121
122* Remember that the trailing NUL isn't covered in the string length.
123
124
125Limitations
126-----------
127
128* all the buffers are a fixed size - here they are current 513 bytes
129 (510 bytes + CR/LF/NUL)
130
131
132TODO
133----
134
135* linebuf_flush() should be changed a little so if the buffer isn't
136 terminated, we *dont* retry flushing a buffer until we get more data.
137
138* Implement a reference-friendly linebuf to reduce copies ..
139