]>
Commit | Line | Data |
---|---|---|
db137867 AC |
1 | /* |
2 | * ircd-ratbox: A slight useful ircd | |
3 | * rawbuf.c: raw buffer (non-line oriented buffering) | |
55abcbb2 | 4 | * |
db137867 AC |
5 | * Copyright (C) 2007 Aaron Sethman <androsyn@ratbox.org> |
6 | * Copyright (C) 2007 ircd-ratbox development team | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 | |
21 | * USA | |
22 | * | |
db137867 | 23 | */ |
fe037171 EM |
24 | #include <librb_config.h> |
25 | #include <rb_lib.h> | |
db137867 AC |
26 | #include <commio-int.h> |
27 | #define RAWBUF_SIZE 1024 | |
28 | ||
29 | struct _rawbuf | |
30 | { | |
31 | rb_dlink_node node; | |
a9fb3ed0 | 32 | uint8_t data[RAWBUF_SIZE]; |
db137867 | 33 | int len; |
a9fb3ed0 | 34 | uint8_t flushing; |
db137867 AC |
35 | }; |
36 | ||
37 | struct _rawbuf_head | |
38 | { | |
39 | rb_dlink_list list; | |
40 | int len; | |
41 | int written; | |
42 | }; | |
43 | ||
44 | static rb_bh *rawbuf_heap; | |
45 | ||
46 | ||
47 | static rawbuf_t * | |
48 | rb_rawbuf_alloc(void) | |
49 | { | |
50 | rawbuf_t *t; | |
51 | t = rb_bh_alloc(rawbuf_heap); | |
52 | return t; | |
53 | } | |
54 | ||
55 | static rawbuf_t * | |
56 | rb_rawbuf_newbuf(rawbuf_head_t * rb) | |
57 | { | |
58 | rawbuf_t *buf; | |
59 | buf = rb_rawbuf_alloc(); | |
60 | rb_dlinkAddTail(buf, &buf->node, &rb->list); | |
61 | return buf; | |
62 | } | |
63 | ||
64 | static void | |
65 | rb_rawbuf_done(rawbuf_head_t * rb, rawbuf_t * buf) | |
66 | { | |
67 | rawbuf_t *ptr = buf; | |
68 | rb_dlinkDelete(&buf->node, &rb->list); | |
69 | rb_bh_free(rawbuf_heap, ptr); | |
70 | } | |
71 | ||
72 | static int | |
73 | rb_rawbuf_flush_writev(rawbuf_head_t * rb, rb_fde_t *F) | |
74 | { | |
75 | rb_dlink_node *ptr, *next; | |
76 | rawbuf_t *buf; | |
77 | int x = 0, y = 0; | |
78 | int xret, retval; | |
79 | struct rb_iovec vec[RB_UIO_MAXIOV]; | |
80 | memset(vec, 0, sizeof(vec)); | |
81 | ||
82 | if(rb->list.head == NULL) | |
83 | { | |
84 | errno = EAGAIN; | |
85 | return -1; | |
86 | } | |
87 | ||
88 | RB_DLINK_FOREACH(ptr, rb->list.head) | |
89 | { | |
90 | if(x >= RB_UIO_MAXIOV) | |
91 | break; | |
92 | ||
93 | buf = ptr->data; | |
94 | if(buf->flushing) | |
95 | { | |
96 | vec[x].iov_base = buf->data + rb->written; | |
97 | vec[x++].iov_len = buf->len - rb->written; | |
98 | continue; | |
99 | } | |
100 | vec[x].iov_base = buf->data; | |
101 | vec[x++].iov_len = buf->len; | |
102 | ||
103 | } | |
104 | ||
105 | if(x == 0) | |
106 | { | |
107 | errno = EAGAIN; | |
108 | return -1; | |
109 | } | |
110 | xret = retval = rb_writev(F, vec, x); | |
111 | if(retval <= 0) | |
112 | return retval; | |
113 | ||
114 | RB_DLINK_FOREACH_SAFE(ptr, next, rb->list.head) | |
115 | { | |
116 | buf = ptr->data; | |
117 | if(y++ >= x) | |
118 | break; | |
119 | if(buf->flushing) | |
120 | { | |
121 | if(xret >= buf->len - rb->written) | |
122 | { | |
123 | xret -= buf->len - rb->written; | |
124 | rb->len -= buf->len - rb->written; | |
125 | rb_rawbuf_done(rb, buf); | |
126 | continue; | |
3202e249 | 127 | } |
db137867 | 128 | } |
3202e249 | 129 | |
db137867 AC |
130 | if(xret >= buf->len) |
131 | { | |
132 | xret -= buf->len; | |
133 | rb->len -= buf->len; | |
134 | rb_rawbuf_done(rb, buf); | |
135 | } | |
136 | else | |
137 | { | |
138 | buf->flushing = 1; | |
139 | rb->written = xret; | |
140 | rb->len -= xret; | |
141 | break; | |
142 | } | |
143 | ||
144 | } | |
145 | return retval; | |
146 | } | |
147 | ||
148 | int | |
149 | rb_rawbuf_flush(rawbuf_head_t * rb, rb_fde_t *F) | |
150 | { | |
151 | rawbuf_t *buf; | |
152 | int retval; | |
153 | if(rb->list.head == NULL) | |
154 | { | |
155 | errno = EAGAIN; | |
156 | return -1; | |
157 | } | |
158 | ||
159 | if(!rb_fd_ssl(F)) | |
160 | return rb_rawbuf_flush_writev(rb, F); | |
161 | ||
162 | buf = rb->list.head->data; | |
163 | if(!buf->flushing) | |
164 | { | |
165 | buf->flushing = 1; | |
166 | rb->written = 0; | |
167 | } | |
168 | ||
169 | retval = rb_write(F, buf->data + rb->written, buf->len - rb->written); | |
170 | if(retval <= 0) | |
171 | return retval; | |
172 | ||
173 | rb->written += retval; | |
174 | if(rb->written == buf->len) | |
175 | { | |
176 | rb->written = 0; | |
177 | rb_dlinkDelete(&buf->node, &rb->list); | |
178 | rb_bh_free(rawbuf_heap, buf); | |
179 | } | |
180 | rb->len -= retval; | |
3202e249 | 181 | lrb_assert(rb->len >= 0); |
db137867 AC |
182 | return retval; |
183 | } | |
184 | ||
185 | ||
186 | void | |
187 | rb_rawbuf_append(rawbuf_head_t * rb, void *data, int len) | |
188 | { | |
189 | rawbuf_t *buf = NULL; | |
190 | int clen; | |
191 | void *ptr; | |
192 | if(rb->list.tail != NULL) | |
193 | buf = rb->list.tail->data; | |
194 | ||
195 | if(buf != NULL && buf->len < RAWBUF_SIZE && !buf->flushing) | |
196 | { | |
197 | buf = (rawbuf_t *) rb->list.tail->data; | |
198 | clen = RAWBUF_SIZE - buf->len; | |
3202e249 | 199 | ptr = (void *)(buf->data + buf->len); |
db137867 AC |
200 | if(len < clen) |
201 | clen = len; | |
202 | ||
203 | memcpy(ptr, data, clen); | |
204 | buf->len += clen; | |
205 | rb->len += clen; | |
206 | len -= clen; | |
207 | if(len == 0) | |
208 | return; | |
c2ac22cc | 209 | data = (char *)data + clen; |
db137867 AC |
210 | |
211 | } | |
212 | ||
3202e249 | 213 | while(len > 0) |
db137867 AC |
214 | { |
215 | buf = rb_rawbuf_newbuf(rb); | |
216 | ||
217 | if(len >= RAWBUF_SIZE) | |
218 | clen = RAWBUF_SIZE; | |
219 | else | |
220 | clen = len; | |
221 | ||
222 | memcpy(buf->data, data, clen); | |
223 | buf->len += clen; | |
224 | len -= clen; | |
c2ac22cc | 225 | data = (char *)data + clen; |
db137867 AC |
226 | rb->len += clen; |
227 | } | |
228 | } | |
229 | ||
230 | ||
231 | int | |
232 | rb_rawbuf_get(rawbuf_head_t * rb, void *data, int len) | |
233 | { | |
234 | rawbuf_t *buf; | |
235 | int cpylen; | |
236 | void *ptr; | |
237 | if(rb->list.head == NULL) | |
238 | return 0; | |
239 | ||
240 | buf = rb->list.head->data; | |
241 | ||
242 | if(buf->flushing) | |
3202e249 | 243 | ptr = (void *)(buf->data + rb->written); |
db137867 AC |
244 | else |
245 | ptr = buf->data; | |
246 | ||
247 | if(len > buf->len) | |
248 | cpylen = buf->len; | |
249 | else | |
250 | cpylen = len; | |
251 | ||
252 | memcpy(data, ptr, cpylen); | |
253 | ||
254 | if(cpylen == buf->len) | |
255 | { | |
256 | rb->written = 0; | |
257 | rb_rawbuf_done(rb, buf); | |
258 | rb->len -= len; | |
259 | return cpylen; | |
260 | } | |
261 | ||
262 | buf->flushing = 1; | |
263 | buf->len -= cpylen; | |
264 | rb->len -= cpylen; | |
265 | rb->written += cpylen; | |
266 | return cpylen; | |
267 | } | |
268 | ||
269 | int | |
270 | rb_rawbuf_length(rawbuf_head_t * rb) | |
271 | { | |
272 | if(rb_dlink_list_length(&rb->list) == 0 && rb->len != 0) | |
273 | lrb_assert(1 == 0); | |
274 | return rb->len; | |
275 | } | |
276 | ||
277 | rawbuf_head_t * | |
278 | rb_new_rawbuffer(void) | |
279 | { | |
280 | return rb_malloc(sizeof(rawbuf_head_t)); | |
281 | ||
282 | } | |
283 | ||
284 | void | |
285 | rb_free_rawbuffer(rawbuf_head_t * rb) | |
286 | { | |
287 | rb_dlink_node *ptr, *next; | |
288 | RB_DLINK_FOREACH_SAFE(ptr, next, rb->list.head) | |
289 | { | |
290 | rb_rawbuf_done(rb, ptr->data); | |
291 | } | |
292 | rb_free(rb); | |
293 | } | |
294 | ||
295 | ||
296 | void | |
297 | rb_init_rawbuffers(int heap_size) | |
298 | { | |
299 | if(rawbuf_heap == NULL) | |
300 | rawbuf_heap = rb_bh_create(sizeof(rawbuf_t), heap_size, "librb_rawbuf_heap"); | |
301 | } |