/* ==========================================================================
* libevnet/src/bufio-membuf.c - Network server library for libevent.
* --------------------------------------------------------------------------
* Copyright (c) 2006 Barracuda Networks, Inc.
* Copyright (c) 2006 William Ahern
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
* ==========================================================================
*/
#include <errno.h> /* ENOBUFS */
#include <string.h> /* memcpy(3) */
#include <sys/param.h> /* MIN */
#include <windows.h> /* GetLastError SetLastError */
#include <winsock2.h> /* INVALID_SOCKET */
#include <arena/proto.h> /* struct arena_prototype */
#include "bufio.h"
#include "pagebuf.h"
#include "membuf.h"
const struct bufio_membuf_options bufio_membuf_oneshot = {
#ifndef WIN32
.oneshot = 1,
#else
1,
#endif
}; /* bufio_membuf_oneshot */
const struct bufio_membuf_options bufio_membuf_defaults;
static size_t bufio_membuf_copyfrom(struct bufio_sink *snk, struct bufio_source *src, int flags, enum bufio_errno *e) {
struct bufio_membuf *m = BUFIO_CAST_FROM(snk, bufio_membuf, bufio_sink);
size_t n, nbytes = 0;
if (0 == bufio_page_nfree(&m->page)) {
*e = (m->opts.oneshot)? BUFIO_EPIPE : BUFIO_EAGAIN;
return 0;
}
*e = 0;
do {
n = src->copyout(src, m->page.cursor.put, bufio_page_nfree(&m->page), flags, e);
m->page.cursor.put += n;
nbytes += n;
} while (n > 0 && 0 < bufio_page_nfree(&m->page));
return nbytes;
} /* bufio_membuf_copyfrom() */
static size_t bufio_membuf_copyin(struct bufio_sink *snk, void *srcbuf, size_t bufsiz, int flags, enum bufio_errno *e) {
struct bufio_membuf *m = BUFIO_CAST_FROM(snk, bufio_membuf, bufio_sink);
size_t nbytes;
if (0 == bufio_page_nfree(&m->page))
goto wouldblock;
*e = 0;
nbytes = MIN(bufio_page_nfree(&m->page), bufsiz);
if ((flags & BUFIO_NOFRAG) && nbytes != bufsiz)
goto wouldblock;
(void)memcpy(m->page.cursor.put, srcbuf, nbytes);
m->page.cursor.put += nbytes;
return nbytes;
wouldblock:
*e = (m->opts.oneshot)? BUFIO_EPIPE : BUFIO_EAGAIN;
return 0;
} /* bufio_membuf_copyin() */
static size_t bufio_membuf_sink_buffered(struct bufio_sink *snk) {
return bufio_page_len(&BUFIO_CAST_FROM(snk, bufio_membuf, bufio_sink)->page);
} /* bufio_membuf_sink_buffered() */
static size_t bufio_membuf_copyto(struct bufio_source *src, struct bufio_sink *snk, int flags, enum bufio_errno *e) {
struct bufio_membuf *m = BUFIO_CAST_FROM(src, bufio_membuf, bufio_source);
size_t n, nbytes = 0;
*e = 0;
if (0 == bufio_page_len(&m->page)) {
*e = (m->opts.oneshot)? BUFIO_EEOF : BUFIO_EAGAIN;
return 0;
}
do {
n = snk->copyin(snk, m->page.cursor.get, bufio_page_len(&m->page), flags, e);
m->page.cursor.get += n;
nbytes += n;
} while (n > 0 && 0 < bufio_page_len(&m->page));
return nbytes;
} /* bufio_membuf_copyto() */
static size_t bufio_membuf_copyout(struct bufio_source *src, void *buf, size_t bufsiz, int flags, enum bufio_errno *e) {
struct bufio_membuf *m = BUFIO_CAST_FROM(src, bufio_membuf, bufio_source);
size_t nbytes;
*e = 0;
if (0 == bufio_page_len(&m->page))
goto wouldblock;
nbytes = MIN(bufio_page_len(&m->page), bufsiz);
if ((flags && BUFIO_NOFRAG) && nbytes != bufio_page_len(&m->page))
goto wouldblock;
(void)memcpy(buf, m->page.cursor.get, nbytes);
if (!(flags & BUFIO_PEEK))
m->page.cursor.get += nbytes;
return nbytes;
wouldblock:
*e = (m->opts.oneshot)? BUFIO_EEOF : BUFIO_EAGAIN;
return 0;
} /* bufio_membuf_copyout() */
static size_t bufio_membuf_source_buffered(struct bufio_source *src) {
return bufio_page_len(&BUFIO_CAST_FROM(src, bufio_membuf, bufio_source)->page);
} /* bufio_membuf_source_buffered() */
struct bufio_membuf *bufio_membuf_init(struct bufio_membuf *m, const struct bufio_membuf_options *opts) {
static const struct bufio_membuf bufio_membuf_initializer;
struct bufio_source *src;
struct bufio_sink *snk;
*m = bufio_membuf_initializer;
m->opts = *((opts)? opts : &bufio_membuf_defaults);
src = BUFIO_CAST_TO(m, bufio_membuf, bufio_source);
*src = BUFIO_SOURCE_INITIALIZER;
src->copyto = &bufio_membuf_copyto;
src->copyout = &bufio_membuf_copyout;
src->buffered = &bufio_membuf_source_buffered;
snk = BUFIO_CAST_TO(m, bufio_membuf, bufio_sink);
*snk = BUFIO_SINK_INITIALIZER;
snk->copyfrom = &bufio_membuf_copyfrom;
snk->copyin = &bufio_membuf_copyin;
snk->buffered = &bufio_membuf_sink_buffered;
return m;
} /* bufio_membuf_options() */
struct bufio_source *bufio_membuf_init_source(struct bufio_membuf *m, const struct bufio_membuf_options *opts, const void *buf, size_t bufsiz) {
bufio_membuf_init(m, opts);
m->page.base = m->page.cursor.get
= (unsigned char *)buf;
m->page.cursor.end = m->page.cursor.put
= m->page.cursor.get + bufsiz;
return bufio_membuf_to_source(m);
} /* bufio_membuf_init_source() */
struct bufio_sink *bufio_membuf_init_sink(struct bufio_membuf *m, const struct bufio_membuf_options *opts, void *buf, size_t bufsiz) {
bufio_membuf_init(m, opts);
m->page.base = m->page.cursor.get
= m->page.cursor.put
= (unsigned char *)buf;
m->page.cursor.end = m->page.cursor.get + bufsiz;
return bufio_membuf_to_sink(m);
} /* bufio_membuf_init_sink() */
struct bufio_source *bufio_membuf_to_source(struct bufio_membuf *m) {
return BUFIO_CAST_TO(m, bufio_membuf, bufio_source);
} /* bufio_membuf_to_source() */
struct bufio_sink *bufio_membuf_to_sink(struct bufio_membuf *m) {
return BUFIO_CAST_TO(m, bufio_membuf, bufio_sink);
} /* bufio_membuf_to_sink() */
syntax highlighted by Code2HTML, v. 0.9.1