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