]> jfr.im git - solanum.git/blame - librb/src/rawbuf.c
check bans and quiets for cmode -n/nonmember PRIVMSG
[solanum.git] / librb / src / rawbuf.c
CommitLineData
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
29struct _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
37struct _rawbuf_head
38{
39 rb_dlink_list list;
40 int len;
41 int written;
42};
43
44static rb_bh *rawbuf_heap;
45
46
47static rawbuf_t *
48rb_rawbuf_alloc(void)
49{
50 rawbuf_t *t;
51 t = rb_bh_alloc(rawbuf_heap);
52 return t;
53}
54
55static rawbuf_t *
56rb_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
64static void
65rb_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
72static int
73rb_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
148int
149rb_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
186void
187rb_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
231int
232rb_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
269int
270rb_rawbuf_length(rawbuf_head_t * rb)
271{
2100c58d
SA
272 if (rb_dlink_list_length(&rb->list) == 0 && lrb_assert(rb->len == 0))
273 rb->len = 0;
db137867
AC
274 return rb->len;
275}
276
277rawbuf_head_t *
278rb_new_rawbuffer(void)
279{
280 return rb_malloc(sizeof(rawbuf_head_t));
281
282}
283
284void
285rb_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
296void
297rb_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}