2 * Copyright (c) 2002, 2003 Niels Provos <provos@citi.umich.edu>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 /* If we have vasprintf, we need to define this before we include stdio.h. */
37 #include <sys/types.h>
39 #ifdef HAVE_SYS_TIME_H
43 #ifdef HAVE_SYS_IOCTL_H
44 #include <sys/ioctl.h>
64 struct evbuffer
*buffer
;
66 buffer
= calloc(1, sizeof(struct evbuffer
));
72 evbuffer_free(struct evbuffer
*buffer
)
74 if (buffer
->orig_buffer
!= NULL
)
75 free(buffer
->orig_buffer
);
80 * This is a destructive add. The data from one buffer moves into
84 #define SWAP(x,y) do { \
85 (x)->buffer = (y)->buffer; \
86 (x)->orig_buffer = (y)->orig_buffer; \
87 (x)->misalign = (y)->misalign; \
88 (x)->totallen = (y)->totallen; \
89 (x)->off = (y)->off; \
93 evbuffer_add_buffer(struct evbuffer
*outbuf
, struct evbuffer
*inbuf
)
97 /* Short cut for better performance */
98 if (outbuf
->off
== 0) {
100 size_t oldoff
= inbuf
->off
;
102 /* Swap them directly */
108 * Optimization comes with a price; we need to notify the
109 * buffer if necessary of the changes. oldoff is the amount
110 * of data that we transfered from inbuf to outbuf
112 if (inbuf
->off
!= oldoff
&& inbuf
->cb
!= NULL
)
113 (*inbuf
->cb
)(inbuf
, oldoff
, inbuf
->off
, inbuf
->cbarg
);
114 if (oldoff
&& outbuf
->cb
!= NULL
)
115 (*outbuf
->cb
)(outbuf
, 0, oldoff
, outbuf
->cbarg
);
120 res
= evbuffer_add(outbuf
, inbuf
->buffer
, inbuf
->off
);
122 /* We drain the input buffer on success */
123 evbuffer_drain(inbuf
, inbuf
->off
);
130 evbuffer_add_vprintf(struct evbuffer
*buf
, const char *fmt
, va_list ap
)
134 size_t oldoff
= buf
->off
;
138 /* make sure that at least some space is available */
139 evbuffer_expand(buf
, 64);
141 size_t used
= buf
->misalign
+ buf
->off
;
142 buffer
= (char *)buf
->buffer
+ buf
->off
;
143 assert(buf
->totallen
>= used
);
144 space
= buf
->totallen
- used
;
147 #define va_copy(dst, src) memcpy(&(dst), &(src), sizeof(va_list))
152 sz
= vsnprintf(buffer
, space
- 1, fmt
, aq
);
153 buffer
[space
- 1] = '\0';
155 sz
= vsnprintf(buffer
, space
, fmt
, aq
);
165 (*buf
->cb
)(buf
, oldoff
, buf
->off
, buf
->cbarg
);
168 if (evbuffer_expand(buf
, sz
+ 1) == -1)
176 evbuffer_add_printf(struct evbuffer
*buf
, const char *fmt
, ...)
182 res
= evbuffer_add_vprintf(buf
, fmt
, ap
);
188 /* Reads data from an event buffer and drains the bytes read */
191 evbuffer_remove(struct evbuffer
*buf
, void *data
, size_t datlen
)
193 size_t nread
= datlen
;
194 if (nread
>= buf
->off
)
197 memcpy(data
, buf
->buffer
, nread
);
198 evbuffer_drain(buf
, nread
);
204 * Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'.
205 * The returned buffer needs to be freed by the called.
209 evbuffer_readline(struct evbuffer
*buffer
)
211 u_char
*data
= EVBUFFER_DATA(buffer
);
212 size_t len
= EVBUFFER_LENGTH(buffer
);
216 for (i
= 0; i
< len
; i
++) {
217 if (data
[i
] == '\r' || data
[i
] == '\n')
224 if ((line
= malloc(i
+ 1)) == NULL
) {
225 fprintf(stderr
, "%s: out of memory\n", __func__
);
226 evbuffer_drain(buffer
, i
);
230 memcpy(line
, data
, i
);
234 * Some protocols terminate a line with '\r\n', so check for
238 char fch
= data
[i
], sch
= data
[i
+1];
240 /* Drain one more character if needed */
241 if ( (sch
== '\r' || sch
== '\n') && sch
!= fch
)
245 evbuffer_drain(buffer
, i
+ 1);
250 /* Adds data to an event buffer */
253 evbuffer_align(struct evbuffer
*buf
)
255 memmove(buf
->orig_buffer
, buf
->buffer
, buf
->off
);
256 buf
->buffer
= buf
->orig_buffer
;
260 /* Expands the available space in the event buffer to at least datlen */
263 evbuffer_expand(struct evbuffer
*buf
, size_t datlen
)
265 size_t need
= buf
->misalign
+ buf
->off
+ datlen
;
267 /* If we can fit all the data, then we don't have to do anything */
268 if (buf
->totallen
>= need
)
272 * If the misalignment fulfills our data needs, we just force an
273 * alignment to happen. Afterwards, we have enough space.
275 if (buf
->misalign
>= datlen
) {
279 size_t length
= buf
->totallen
;
283 while (length
< need
)
286 if (buf
->orig_buffer
!= buf
->buffer
)
288 if ((newbuf
= realloc(buf
->buffer
, length
)) == NULL
)
291 buf
->orig_buffer
= buf
->buffer
= newbuf
;
292 buf
->totallen
= length
;
299 evbuffer_add(struct evbuffer
*buf
, const void *data
, size_t datlen
)
301 size_t need
= buf
->misalign
+ buf
->off
+ datlen
;
302 size_t oldoff
= buf
->off
;
304 if (buf
->totallen
< need
) {
305 if (evbuffer_expand(buf
, datlen
) == -1)
309 memcpy(buf
->buffer
+ buf
->off
, data
, datlen
);
312 if (datlen
&& buf
->cb
!= NULL
)
313 (*buf
->cb
)(buf
, oldoff
, buf
->off
, buf
->cbarg
);
319 evbuffer_drain(struct evbuffer
*buf
, size_t len
)
321 size_t oldoff
= buf
->off
;
323 if (len
>= buf
->off
) {
325 buf
->buffer
= buf
->orig_buffer
;
331 buf
->misalign
+= len
;
336 /* Tell someone about changes in this buffer */
337 if (buf
->off
!= oldoff
&& buf
->cb
!= NULL
)
338 (*buf
->cb
)(buf
, oldoff
, buf
->off
, buf
->cbarg
);
343 * Reads data from a file descriptor into a buffer.
346 #define EVBUFFER_MAX_READ 4096
349 evbuffer_read(struct evbuffer
*buf
, int fd
, int howmuch
)
352 size_t oldoff
= buf
->off
;
353 int n
= EVBUFFER_MAX_READ
;
359 if (ioctl(fd
, FIONREAD
, &n
) == -1 || n
== 0) {
360 n
= EVBUFFER_MAX_READ
;
361 } else if (n
> EVBUFFER_MAX_READ
&& n
> howmuch
) {
363 * It's possible that a lot of data is available for
364 * reading. We do not want to exhaust resources
365 * before the reader has a chance to do something
366 * about it. If the reader does not tell us how much
367 * data we should read, we artifically limit it.
369 if (n
> buf
->totallen
<< 2)
370 n
= buf
->totallen
<< 2;
371 if (n
< EVBUFFER_MAX_READ
)
372 n
= EVBUFFER_MAX_READ
;
375 if (howmuch
< 0 || howmuch
> n
)
378 /* If we don't have FIONREAD, we might waste some space here */
379 if (evbuffer_expand(buf
, howmuch
) == -1)
382 /* We can append new data at this point */
383 p
= buf
->buffer
+ buf
->off
;
386 n
= read(fd
, p
, howmuch
);
392 n
= ReadFile((HANDLE
)fd
, p
, howmuch
, &dwBytesRead
, NULL
);
395 if (dwBytesRead
== 0)
402 /* Tell someone about changes in this buffer */
403 if (buf
->off
!= oldoff
&& buf
->cb
!= NULL
)
404 (*buf
->cb
)(buf
, oldoff
, buf
->off
, buf
->cbarg
);
410 evbuffer_write(struct evbuffer
*buffer
, int fd
)
414 DWORD dwBytesWritten
;
418 n
= write(fd
, buffer
->buffer
, buffer
->off
);
424 n
= WriteFile((HANDLE
)fd
, buffer
->buffer
, buffer
->off
, &dwBytesWritten
, NULL
);
427 if (dwBytesWritten
== 0)
431 evbuffer_drain(buffer
, n
);
437 evbuffer_find(struct evbuffer
*buffer
, const u_char
*what
, size_t len
)
439 u_char
*search
= buffer
->buffer
, *end
= search
+ buffer
->off
;
442 while (search
< end
&&
443 (p
= memchr(search
, *what
, end
- search
)) != NULL
) {
446 if (memcmp(p
, what
, len
) == 0)
454 void evbuffer_setcb(struct evbuffer
*buffer
,
455 void (*cb
)(struct evbuffer
*, size_t, size_t, void *),
459 buffer
->cbarg
= cbarg
;