~ubuntu-branches/ubuntu/trusty/charybdis/trusty-proposed

« back to all changes in this revision

Viewing changes to doc/technical/linebuf.txt

  • Committer: Package Import Robot
  • Author(s): Antoine Beaupré
  • Date: 2011-11-10 23:07:37 UTC
  • Revision ID: package-import@ubuntu.com-20111110230737-kqo6qsglp5oh02hr
Tags: upstream-3.3.0
Import upstream version 3.3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
linebuf - a dbuf replacement for the New World Order(tm)
 
3
 
 
4
By Adrian Chadd <adrian@creative.net.au>
 
5
 
 
6
$Id: linebuf.txt 6 2005-09-10 01:02:21Z nenolod $
 
7
 
 
8
 
 
9
History
 
10
-------
 
11
 
 
12
I could probably learn the dbuf history, but basically its evil. The
 
13
general idea is that a dbuf holds incoming and outgoing data streams.
 
14
The trouble is that well.. it was evil. You can check it out by getting
 
15
the old src/dbuf.c and include/dbuf.h files if you really want.
 
16
 
 
17
 
 
18
Replacement
 
19
-----------
 
20
 
 
21
The linebuf system is a replacement for the dbuf code. The general idea here
 
22
is that the data should be buffered in "lines" rather than just linearly
 
23
like 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
 
25
reduce the copying required for one to many delivery.)
 
26
 
 
27
The linebuf system is broken into two structures, the buf_head and buf_line .
 
28
buf_head contains the buffer information (queue head/tail, length, allocated
 
29
length and the write offset for flushing), and buf_line contains the
 
30
line buffer information (buffer and various flags.)
 
31
 
 
32
linebuf->terminated is *only* set when a CR/LF combination is received.
 
33
 
 
34
linebuf->overflow is set if we get more data than we should, and we simply
 
35
  truncate the incoming data.
 
36
 
 
37
linebuf->flushing is set when we are currently writing the buffer. We should
 
38
  _NEVER_ be appending to a buffer which we're flushing!
 
39
 
 
40
When you get a buffer through linebuf_get() or write one through
 
41
linebuf_flush(), it will *always* be terminated with a CR/LF (and a NUL if
 
42
its a linebuf_get()).
 
43
 
 
44
 
 
45
Linebuf manipulation
 
46
--------------------
 
47
 
 
48
To use a linebuf, you simply stick a buf_head_t in your structure somewhere.
 
49
You then use the following routines:
 
50
 
 
51
int
 
52
linebuf_parse(buf_head_t *bufhead, char *buf, int len)
 
53
 
 
54
Parse 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
 
 
71
void
 
72
linebuf_put(buf_head_t *bufhead, char *buf, int len)
 
73
 
 
74
Parse the given buf, ASSUMING it is a single buffer line. This is useful
 
75
for server-generated messages where you know you have a single line, and
 
76
you don't want to go through the overhead of parsing the data just for
 
77
this.
 
78
 
 
79
 
 
80
int
 
81
linebuf_get(buf_head_t *bufhead, char *buf, int maxlen)
 
82
 
 
83
Get a single line from the buffer. This removes data from the head of the
 
84
buffer. If the first buffer is empty or is not terminated, 0 is returned
 
85
which indicates that there is no data to parse. Terminated buffers are
 
86
returned (CR/LF/NUL), and the length INCLUDING the CR/LF/NUL is returned.
 
87
The buffer is copied and the linebuf is then deallocated.
 
88
 
 
89
 
 
90
int
 
91
linebuf_flush(int fd, buf_head_t *bufhead)
 
92
 
 
93
Attempt to flush some data to the given socket. bufhead->writeofs tracks
 
94
where 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
 
 
98
linebuf_flush() returns whatever write() returns, and sets (ie doesn't touch
 
99
after write()) errno accordingly.
 
100
 
 
101
 
 
102
int
 
103
linebuf_len(buf_head_t *bufhead)
 
104
 
 
105
Return the length of the buffer, in bytes. This should be used when calculating
 
106
how big a buffer is for statistics.
 
107
 
 
108
 
 
109
int
 
110
linebuf_alloclen(buf_head_t *bufhead)
 
111
 
 
112
Return how big the *allocated* space is. This is much more suitable for
 
113
anti-flood checking, as someone might be sending a whole bunch of 1-byte
 
114
linebufs which might not trigger a recvq / sendq limit but might chew up
 
115
way too much memory.
 
116
 
 
117
 
 
118
 
 
119
Notes
 
120
-----
 
121
 
 
122
* Remember that the trailing NUL isn't covered in the string length.
 
123
 
 
124
 
 
125
Limitations
 
126
-----------
 
127
 
 
128
* all the buffers are a fixed size - here they are current 513 bytes
 
129
  (510 bytes + CR/LF/NUL)
 
130
 
 
131
 
 
132
TODO
 
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