summaryrefslogtreecommitdiff
path: root/lib/libevent/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libevent/buffer.c')
-rw-r--r--lib/libevent/buffer.c202
1 files changed, 179 insertions, 23 deletions
diff --git a/lib/libevent/buffer.c b/lib/libevent/buffer.c
index 7755e7f1b53..a072e7d51ee 100644
--- a/lib/libevent/buffer.c
+++ b/lib/libevent/buffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: buffer.c,v 1.3 2005/04/19 08:07:45 deraadt Exp $ */
+/* $OpenBSD: buffer.c,v 1.4 2005/04/22 00:56:25 brad Exp $ */
/*
* Copyright (c) 2002, 2003 Niels Provos <provos@citi.umich.edu>
@@ -27,17 +27,25 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/types.h>
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#ifdef HAVE_VASPRINTF
+/* If we have vasprintf, we need to define this before we include stdio.h. */
+#define _GNU_SOURCE
+#endif
+
+#include <sys/types.h>
+
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
-#include <err.h>
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -64,8 +72,8 @@ evbuffer_new(void)
void
evbuffer_free(struct evbuffer *buffer)
{
- if (buffer->buffer != NULL)
- free(buffer->buffer);
+ if (buffer->orig_buffer != NULL)
+ free(buffer->orig_buffer);
free(buffer);
}
@@ -74,10 +82,42 @@ evbuffer_free(struct evbuffer *buffer)
* the other buffer.
*/
+#define SWAP(x,y) do { \
+ (x)->buffer = (y)->buffer; \
+ (x)->orig_buffer = (y)->orig_buffer; \
+ (x)->misalign = (y)->misalign; \
+ (x)->totallen = (y)->totallen; \
+ (x)->off = (y)->off; \
+} while (0)
+
int
evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
{
int res;
+
+ /* Short cut for better performance */
+ if (outbuf->off == 0) {
+ struct evbuffer tmp;
+ size_t oldoff = inbuf->off;
+
+ /* Swap them directly */
+ SWAP(&tmp, outbuf);
+ SWAP(outbuf, inbuf);
+ SWAP(inbuf, &tmp);
+
+ /*
+ * Optimization comes with a price; we need to notify the
+ * buffer if necessary of the changes. oldoff is the amount
+ * of data that we tranfered from inbuf to outbuf
+ */
+ if (inbuf->off != oldoff && inbuf->cb != NULL)
+ (*inbuf->cb)(inbuf, oldoff, inbuf->off, inbuf->cbarg);
+ if (oldoff && outbuf->cb != NULL)
+ (*outbuf->cb)(outbuf, 0, oldoff, outbuf->cbarg);
+
+ return (0);
+ }
+
res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off);
if (res == 0)
evbuffer_drain(inbuf, inbuf->off);
@@ -90,46 +130,113 @@ evbuffer_add_printf(struct evbuffer *buf, char *fmt, ...)
{
int res = -1;
char *msg;
+#ifndef HAVE_VASPRINTF
+ static char buffer[4096];
+#endif
va_list ap;
va_start(ap, fmt);
+#ifdef HAVE_VASPRINTF
if (vasprintf(&msg, fmt, ap) == -1)
goto end;
+#else
+# ifdef WIN32
+ _vsnprintf(buffer, sizeof(buffer) - 1, fmt, ap);
+ buffer[sizeof(buffer)-1] = '\0';
+# else /* ! WIN32 */
+ vsnprintf(buffer, sizeof(buffer), fmt, ap);
+# endif
+ msg = buffer;
+#endif
res = strlen(msg);
if (evbuffer_add(buf, msg, res) == -1)
res = -1;
+#ifdef HAVE_VASPRINTF
free(msg);
- end:
+end:
+#endif
va_end(ap);
return (res);
}
+/* Reads data from an event buffer and drains the bytes read */
+
int
-evbuffer_add(struct evbuffer *buf, u_char *data, size_t datlen)
+evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen)
{
- size_t need = buf->off + datlen;
- size_t oldoff = buf->off;
+ int nread = datlen;
+ if (nread >= buf->off)
+ nread = buf->off;
- if (buf->totallen < need) {
+ memcpy(data, buf->buffer, nread);
+ evbuffer_drain(buf, nread);
+
+ return (nread);
+}
+
+/* Adds data to an event buffer */
+
+static inline void
+evbuffer_align(struct evbuffer *buf)
+{
+ memmove(buf->orig_buffer, buf->buffer, buf->off);
+ buf->buffer = buf->orig_buffer;
+ buf->misalign = 0;
+}
+
+/* Expands the available space in the event buffer to at least datlen */
+
+int
+evbuffer_expand(struct evbuffer *buf, size_t datlen)
+{
+ size_t need = buf->misalign + buf->off + datlen;
+
+ /* If we can fit all the data, then we don't have to do anything */
+ if (buf->totallen >= need)
+ return (0);
+
+ /*
+ * If the misalignment fulfills our data needs, we just force an
+ * alignment to happen. Afterwards, we have enough space.
+ */
+ if (buf->misalign >= datlen) {
+ evbuffer_align(buf);
+ } else {
void *newbuf;
- int length = buf->totallen;
+ size_t length = buf->totallen;
if (length < 256)
length = 256;
while (length < need)
length <<= 1;
+ if (buf->orig_buffer != buf->buffer)
+ evbuffer_align(buf);
if ((newbuf = realloc(buf->buffer, length)) == NULL)
return (-1);
- buf->buffer = newbuf;
+ buf->orig_buffer = buf->buffer = newbuf;
buf->totallen = length;
}
+ return (0);
+}
+
+int
+evbuffer_add(struct evbuffer *buf, void *data, size_t datlen)
+{
+ size_t need = buf->misalign + buf->off + datlen;
+ size_t oldoff = buf->off;
+
+ if (buf->totallen < need) {
+ if (evbuffer_expand(buf, datlen) == -1)
+ return (-1);
+ }
+
memcpy(buf->buffer + buf->off, data, datlen);
buf->off += datlen;
@@ -146,10 +253,14 @@ evbuffer_drain(struct evbuffer *buf, size_t len)
if (len >= buf->off) {
buf->off = 0;
+ buf->buffer = buf->orig_buffer;
+ buf->misalign = 0;
goto done;
}
- memmove(buf->buffer, buf->buffer + len, buf->off - len);
+ buf->buffer += len;
+ buf->misalign += len;
+
buf->off -= len;
done:
@@ -159,22 +270,56 @@ evbuffer_drain(struct evbuffer *buf, size_t len)
}
+/*
+ * Reads data from a file descriptor into a buffer.
+ */
+
+#define EVBUFFER_MAX_READ 4096
+
int
-evbuffer_read(struct evbuffer *buffer, int fd, int howmuch)
+evbuffer_read(struct evbuffer *buf, int fd, int howmuch)
{
- u_char inbuf[4096];
- int n;
-
- if (howmuch < 0 || howmuch > sizeof(inbuf))
- howmuch = sizeof(inbuf);
+ u_char *p;
+ size_t oldoff = buf->off;
+ int n = EVBUFFER_MAX_READ;
+#ifdef WIN32
+ DWORD dwBytesRead;
+#endif
+
+#ifdef FIONREAD
+ if (ioctl(fd, FIONREAD, &n) == -1)
+ n = EVBUFFER_MAX_READ;
+#endif
+ if (howmuch < 0 || howmuch > n)
+ howmuch = n;
- n = read(fd, inbuf, howmuch);
+ /* If we don't have FIONREAD, we might waste some space here */
+ if (evbuffer_expand(buf, howmuch) == -1)
+ return (-1);
+
+ /* We can append new data at this point */
+ p = buf->buffer + buf->off;
+
+#ifndef WIN32
+ n = read(fd, p, howmuch);
if (n == -1)
return (-1);
if (n == 0)
return (0);
+#else
+ n = ReadFile((HANDLE)fd, p, howmuch, &dwBytesRead, NULL);
+ if (n == 0)
+ return (-1);
+ if (dwBytesRead == 0)
+ return (0);
+ n = dwBytesRead;
+#endif
- evbuffer_add(buffer, inbuf, n);
+ buf->off += n;
+
+ /* Tell someone about changes in this buffer */
+ if (buf->off != oldoff && buf->cb != NULL)
+ (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
return (n);
}
@@ -183,13 +328,24 @@ int
evbuffer_write(struct evbuffer *buffer, int fd)
{
int n;
+#ifdef WIN32
+ DWORD dwBytesWritten;
+#endif
+#ifndef WIN32
n = write(fd, buffer->buffer, buffer->off);
if (n == -1)
return (-1);
if (n == 0)
return (0);
-
+#else
+ n = WriteFile((HANDLE)fd, buffer->buffer, buffer->off, &dwBytesWritten, NULL);
+ if (n == 0)
+ return (-1);
+ if (dwBytesWritten == 0)
+ return (0);
+ n = dwBytesWritten;
+#endif
evbuffer_drain(buffer, n);
return (n);