size_t to_alloc;
size += EVBUFFER_CHAIN_SIZE;
-
+
/* get the next largest memory that can hold the buffer */
to_alloc = MIN_BUFFER_SIZE;
while (to_alloc < size)
{
struct evbuffer_chain *chain = buf->last;
- if (chain == NULL ||
+ if (chain == NULL ||
chain->buffer_len - chain->off - chain->misalign < size)
return (-1);
(dst)->previous_to_last = NULL; \
(dst)->total_len = 0; \
} while (0)
-
+
#define COPY_CHAIN(dst, src) do { \
(dst)->first = (src)->first; \
(dst)->previous_to_last = (src)->previous_to_last; \
if ((dst)->previous_to_last == NULL) \
(dst)->previous_to_last = (src)->last; \
} while (0)
-
+
int
evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
src->first = chain;
if (src->first == src->last)
src->previous_to_last = NULL;
-
+
dst->total_len += nread;
}
memcpy(buffer, chain->buffer + chain->misalign, chain->off);
size -= chain->off;
buffer += chain->off;
-
+
evbuffer_chain_free(chain);
}
chain->buffer + chain->misalign,
chain->off);
chain->misalign = 0;
-
+
memcpy(chain->buffer + chain->off, data, datlen);
chain->off += datlen;
buf->total_len += datlen;
tmp = evbuffer_chain_new(to_alloc);
if (tmp == NULL)
return (-1);
-
+
if (remain) {
memcpy(chain->buffer + chain->misalign + chain->off,
data, remain);
res = sendfile(fd, info->fd, &offset, chain->off);
if (res == -1 && EVUTIL_ERR_RW_RETRIABLE(errno)) {
/* if this is EGAIN or EINTR return 0; otherwise, -1 */
- return (0);
+ return (0);
}
return (res);
#endif
info = EVBUFFER_CHAIN_EXTRA(struct evbuffer_chain_fd, chain);
info->fd = fd;
-
+
evbuffer_chain_insert(outbuf, chain);
} else
#endif
-#if defined(HAVE_MMAP)
+#if defined(HAVE_MMAP)
if (use_mmap) {
void *mapped = mmap(NULL, length + offset, PROT_READ,
#ifdef MAP_NOCACHE
chain->buffer = mapped;
chain->buffer_len = length + offset;
chain->off = length + offset;
-
+
info = EVBUFFER_CHAIN_EXTRA(struct evbuffer_chain_fd, chain);
info->fd = fd;
-
+
evbuffer_chain_insert(outbuf, chain);
/* we need to subtract whatever we don't need */
length -= read;
}
-
+
close(fd);
}
return (event_add(ev, ptv));
}
-/*
+/*
* This callback is executed when the size of the input buffer changes.
* We use it to apply back pressure on the reading side.
*/
bufferevent_filter_free(filter);
}
-
+
while ((filter = TAILQ_FIRST(&bufev->output_filters)) != NULL) {
bufferevent_filter_remove(bufev, BEV_OUTPUT, filter);
if (evbuffer_add_buffer(output, buf) == -1)
return (-1);
-
+
return (bufferevent_write_closure(bufev, len > 0));
}
if (filter->free_context)
filter->free_context(filter->ctx);
-
+
}
static int
if (devpollop->nchanges >= devpollop->nevents) {
/*
- * Change buffer is full, must commit it to /dev/poll before
- * adding more
+ * Change buffer is full, must commit it to /dev/poll before
+ * adding more
*/
if (devpoll_commit(devpollop) != 0)
return(-1);
int res;
(void)p;
- /*
+ /*
* It's not necessary to OR the existing read/write events that we
* are currently interested in with the new event we are adding.
* The /dev/poll driver ORs any new events with the existing events
/*
* The only way to remove an fd from the /dev/poll monitored set is
- * to use POLLREMOVE by itself. This removes ALL events for the fd
- * provided so if we care about two events and are only removing one
+ * to use POLLREMOVE by itself. This removes ALL events for the fd
+ * provided so if we care about two events and are only removing one
* we must re-add the other event after POLLREMOVE.
*/
if (j < 0) {
return (int)j;
}
-
+
APPEND16(type);
APPEND16(class);
#ifndef WIN32
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
-#else
+#else
#include <sys/_time.h>
#endif
#endif
EVLIST_ACTIVE);
base->sig.ev_signal_added = 0;
}
-
+
if (base->evsel->dealloc != NULL)
base->evsel->dealloc(base);
base->evbase = evsel->init(base);
event_queue_remove(base, ev, EVLIST_ACTIVE);
else
event_del_internal(ev);
-
+
event_debug((
"event_process_active: event: %p, %s%scall %p",
- ev,
+ ev,
ev->ev_res & EV_READ ? "EV_READ " : " ",
ev->ev_res & EV_WRITE ? "EV_WRITE " : " ",
ev->ev_callback));
if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) {
timeout_next(base, &tv_p);
} else {
- /*
+ /*
* if we have active events, we just poll new events
* without waiting.
*/
evutil_timerclear(&tv);
}
-
+
/* If we have no events, we just exit */
if (!event_haveevents(base)) {
event_debug(("%s: no events registered.", __func__));
event_queue_insert(base, ev, EVLIST_INSERTED);
}
- /*
+ /*
* we should change the timout state only if the previous event
* addition succeeded.
*/
if (ev->ev_closure == event_persist_closure)
ev->ev_io_timeout = *tv;
- /*
+ /*
* we already reserved memory above for the case where we
* are not replacing an exisiting timeout.
*/
if (ev->ev_flags & EVLIST_TIMEOUT)
event_queue_remove(base, ev, EVLIST_TIMEOUT);
-
+
/* Check if it is active due to a timeout. Rescheduling
* this timeout before the callback can be executed
* removes it from the active list. */
*ev->ev_pncalls = 0;
}
}
-
+
event_queue_remove(base, ev, EVLIST_ACTIVE);
}
int res;
EVTHREAD_ACQUIRE_LOCK(ev->ev_base, EVTHREAD_WRITE, th_base_lock);
-
+
res = event_del_internal(ev);
EVTHREAD_RELEASE_LOCK(ev->ev_base, EVTHREAD_WRITE, th_base_lock);
return (VERSION);
}
-/*
+/*
* No thread-safe interface needed - the information should be the same
* for all threads.
*/
class StructCCode(Struct):
""" Knows how to generate C code for a struct """
-
+
def __init__(self, name):
Struct.__init__(self, name)
-
+
def PrintTags(self, file):
"""Prints the tag definitions for a structure."""
print >>file, '/* Tag definition for %s */' % self._name
void %(name)s_marshal(struct evbuffer *, const struct %(name)s *);
int %(name)s_unmarshal(struct %(name)s *, struct evbuffer *);
int %(name)s_complete(struct %(name)s *);
-void evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t,
+void evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t,
const struct %(name)s *);
int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
struct %(name)s *);""" % { 'name' : self._name }
if entry.Array():
self.PrintIndented(file, '', entry.CodeAdd())
print >>file, ''
-
+
# Assigning
for entry in self._entries:
self.PrintIndented(file, '', entry.CodeAssign())
for entry in self._entries:
self.PrintIndented(file, '', entry.CodeGet())
print >>file, ''
-
+
# Clearing
print >>file, ( 'void\n'
'%(name)s_clear(struct %(name)s *tmp)\n'
'%(name)s_free(struct %(name)s *tmp)\n'
'{'
) % { 'name' : self._name }
-
+
for entry in self._entries:
self.PrintIndented(file, ' ', entry.CodeFree('tmp'))
print >>file, ' }'
print >>file, '}\n'
-
+
# Unmarshaling
print >>file, ('int\n'
'%(name)s_unmarshal(struct %(name)s *tmp, '
code = TranslateList(code, entry.GetTranslation())
self.PrintIndented(
file, ' ', code)
-
+
self.PrintIndented(
file, ' ',
entry.CodeComplete('msg', entry.GetVarName('msg')))
def MakeArray(self, yes=1):
self._array = yes
-
+
def MakeOptional(self):
self._optional = 1
mapping[k] = v
return mapping
-
+
def GetVarName(self, var):
return '%(var)s->%(name)s_data' % self.GetTranslation({ 'var' : var })
def GetFuncName(self):
return '%s_%s_get' % (self._struct.Name(), self._name)
-
+
def GetDeclaration(self, funcname):
code = [ 'int %s(struct %s *, %s *);' % (
funcname, self._struct.Name(), self._ctype ) ]
code = '\n'.join(code)
code = code % self.GetTranslation()
return code.split('\n')
-
+
def AssignFuncName(self):
return '%s_%s_assign' % (self._struct.Name(), self._name)
-
+
def AddFuncName(self):
return '%s_%s_add' % (self._struct.Name(), self._name)
-
+
def AssignDeclaration(self, funcname):
code = [ 'int %s(struct %s *, const %s);' % (
funcname, self._struct.Name(), self._ctype ) ]
code = [ '%s->%s_set = 0;' % (structname, self.Name()) ]
return code
-
+
def CodeComplete(self, structname, var_name):
return []
code = [ 'int %s(struct %s *, %s **);' % (
funcname, self._struct.Name(), self._ctype ) ]
return code
-
+
def AssignDeclaration(self, funcname):
code = [ 'int %s(struct %s *, const %s *);' % (
funcname, self._struct.Name(), self._ctype ) ]
return code
-
+
def Declaration(self):
dcl = ['ev_uint8_t %s_data[%s];' % (self._name, self._length)]
-
+
return dcl
def CodeGet(self):
' return (0);',
'}' ]
return code
-
+
def CodeAssign(self):
name = self._name
code = [ 'int',
' return (0);',
'}' ]
return code
-
+
def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
code = [ 'if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, '
'%(var)s, %(varlen)s) == -1) {',
structname, self._name, structname, self._name)]
return code
-
+
def CodeInitialize(self, name):
code = ['memset(%s->%s_data, 0, sizeof(%s->%s_data));' % (
name, self._name, name, self._name)]
self._marshal_type = 'int64'
def GetInitializer(self):
- return "0"
+ return "0"
def CodeArrayFree(self, var):
return []
-
+
def CodeArrayAssign(self, varname, srcvar):
return [ '%(varname)s = %(srcvar)s;' % { 'varname' : varname,
'srcvar' : srcvar } ]
}""" % self.GetTranslation()
return code.split('\n')
-
+
def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
code = ['if (evtag_unmarshal_string(%(buf)s, %(tag)s, &%(var)s) == -1) {',
' event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
]
return code
-
+
def CodeInitialize(self, name):
code = ['%s->%s_data = NULL;' % (name, self._name)]
return code
def CodeFree(self, name):
code = ['if (%s->%s_data != NULL)' % (name, self._name),
- ' free (%s->%s_data); ' % (name, self._name)]
+ ' free (%s->%s_data);' % (name, self._name)]
return code
self._optaddarg = False
def GetInitializer(self):
- return "NULL"
+ return "NULL"
def GetVarLen(self, var):
return '-1'
' %(refname)s_clear(%(var)s);',
' return (-1);',
'}' ]
-
+
return TranslateList(code, self.GetTranslation({
'var' : var,
'srcvar' : srcvar}))
' return (0);',
'}' ]
return code
-
+
def CodeAssign(self):
name = self._name
code = """int
return (-1);
}""" % self.GetTranslation()
return code.split('\n')
-
+
def CodeComplete(self, structname, var_name):
code = [ 'if (%(structname)s->%(name)s_set && '
'%(refname)s_complete(%(var)s) == -1)',
return TranslateList(code, self.GetTranslation({
'structname' : structname,
'var' : var_name }))
-
+
def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
code = ['%(var)s = %(refname)s_new();',
'if (%(var)s == NULL)',
]
return code
-
+
def CodeInitialize(self, name):
code = ['%s->%s_data = NULL;' % (name, self._name)]
return code
self._ctype = 'ev_uint8_t *'
def GetInitializer(self):
- return "NULL"
+ return "NULL"
def GetVarLen(self, var):
return '%(var)s->%(name)s_length' % self.GetTranslation({ 'var' : var })
code = [ 'int %s(struct %s *, %s *, ev_uint32_t *);' % (
funcname, self._struct.Name(), self._ctype ) ]
return code
-
+
def AssignDeclaration(self, funcname):
code = [ 'int %s(struct %s *, const %s, ev_uint32_t);' % (
funcname, self._struct.Name(), self._ctype ) ]
return code
-
+
def CodeAssign(self):
name = self._name
code = [ 'int',
' return (0);',
'}' ]
return code
-
+
def CodeGet(self):
name = self._name
code = [ 'int',
]
return code
-
+
def CodeInitialize(self, name):
code = ['%s->%s_data = NULL;' % (name, self._name),
'%s->%s_length = 0;' % (name, self._name) ]
self._entry.GetVarName = GetVarName
def GetInitializer(self):
- return "NULL"
+ return "NULL"
def GetVarName(self, var_name):
return var_name
'int %(funcname)s(struct %(parent_name)s *, int, %(ctype)s *);' %
self.GetTranslation({ 'funcname' : funcname }) ]
return code
-
+
def AssignDeclaration(self, funcname):
code = [ 'int %s(struct %s *, int, const %s);' % (
funcname, self._struct.Name(), self._ctype ) ]
return code
-
+
def AddDeclaration(self, funcname):
code = [
'%(ctype)s %(optpointer)s '
'%(funcname)s(struct %(parent_name)s *msg%(optaddarg)s);' % \
self.GetTranslation({ 'funcname' : funcname }) ]
return code
-
+
def CodeGet(self):
code = """int
%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, int offset,
}""" % self.GetTranslation()
return code.split('\n')
-
+
def CodeAssign(self):
code = [
'int',
'}' ], self.GetTranslation())
return code
-
+
def CodeAdd(self):
codearrayadd = self._entry.CodeArrayAdd(
'msg->%(name)s_data[msg->%(name)s_length - 1]' % self.GetTranslation(),
' }' ]
code = TranslateList(code, self.GetTranslation())
-
+
code += map(lambda x: ' ' + x, codearrayadd)
code += TranslateList([
'}' ]
return code
-
+
def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
translate = self.GetTranslation({ 'var' : var_name,
'buf' : buf,
]
code = "\n".join(code) % self.GetTranslation({ 'var' : var_name })
-
+
return code.split('\n')
def CodeClear(self, structname):
code += map(lambda x: ' ' + x, codearrayfree)
code += [
' }' ]
-
- code += TranslateList([
+
+ code += TranslateList([
' free(%(structname)s->%(name)s_data);',
' %(structname)s->%(name)s_data = NULL;',
' %(structname)s->%(name)s_set = 0;',
], translate)
return code
-
+
def CodeInitialize(self, name):
code = ['%s->%s_data = NULL;' % (name, self._name),
'%s->%s_length = 0;' % (name, self._name),
def NormalizeLine(line):
global white
global cppcomment
-
+
line = cppcomment.sub('', line)
line = line.strip()
line = white.sub(' ', line)
sys.exit(1)
structs = []
-
+
if optional:
newentry.MakeOptional()
if array:
line = file.readline()
if not line:
break
-
+
line_count += 1
line = line[:-1]
if re.match(r'#include ["<].*[>"]', line):
cppdirect.append(line)
continue
-
+
if re.match(r'^#(if( |def)|endif)', line):
cppdirect.append(line)
continue
# Remove any comments, that might be in there
data = re.sub(r'/\*.*\*/', '', data)
-
+
return data
-
+
def Parse(factory, file):
"""
class CCodeGenerator:
def __init__(self):
pass
-
+
def GuardName(self, name):
name = '_'.join(name.split('.'))
name = '_'.join(name.split('/'))
guard = '_' + name.upper() + '_'
-
+
return guard
-
+
def HeaderPreamble(self, name):
guard = self.GuardName(name)
pre = (
'#ifndef %s\n'
'#define %s\n\n' ) % (
name, guard, guard)
-
+
# insert stdint.h - let's hope everyone has it
pre += (
'#include <event-config.h>\n'
'#ifdef _EVENT_HAVE_STDINT_H\n'
'#include <stdint.h>\n'
'#endif\n' )
-
+
for statement in headerdirect:
pre += '%s\n' % statement
if headerdirect:
pre += '\n'
-
+
pre += (
'#define EVTAG_HAS(msg, member) ((msg)->member##_set == 1)\n'
'#define EVTAG_ASSIGN(msg, member, args...) '
'(*(msg)->base->member##_add)(msg, ## args)\n'
'#define EVTAG_LEN(msg, member) ((msg)->member##_length)\n'
)
-
+
return pre
-
+
def HeaderPostamble(self, name):
guard = self.GuardName(name)
return '#endif /* %s */' % guard
-
+
def BodyPreamble(self, name):
global _NAME
global _VERSION
-
+
header_file = '.'.join(name.split('.')[:-1]) + '.gen.h'
-
+
pre = ( '/*\n'
' * Automatically generated from %s\n'
' * by %s/%s. DO NOT EDIT THIS FILE.\n'
'#include <event2/buffer.h>\n'
'#include <event2/tag.h>\n\n'
)
-
+
for statement in cppdirect:
pre += '%s\n' % statement
-
+
pre += '\n#include "%s"\n\n' % header_file
-
+
pre += 'void event_err(int eval, const char *fmt, ...);\n'
pre += 'void event_warn(const char *fmt, ...);\n'
pre += 'void event_errx(int eval, const char *fmt, ...);\n'
pre += 'void event_warnx(const char *fmt, ...);\n\n'
-
+
return pre
def HeaderFilename(self, filename):
- return '.'.join(filename.split('.')[:-1]) + '.gen.h'
+ return '.'.join(filename.split('.')[:-1]) + '.gen.h'
def CodeFilename(self, filename):
- return '.'.join(filename.split('.')[:-1]) + '.gen.c'
+ return '.'.join(filename.split('.')[:-1]) + '.gen.c'
def Struct(self, name):
return StructCCode(name)
for entry in entities:
entry.PrintCode(impl_fp)
impl_fp.close()
-
+
def main(argv):
if len(argv) < 2 or not argv[1]:
print >>sys.stderr, 'Need RPC description file as first argument.'
if (tag_len != len)
return (-1);
-
+
evbuffer_remove(src, data, len);
return (0);
}
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
*
* evport_add and evport_del update this data structure. evport_dispatch uses it
* to determine where to callback when an event occurs (which it gets from
- * port_getn).
+ * port_getn).
*
* Helper functions are used: grow() grows the file descriptor array as
* necessary when large fd's come in. reassociate() takes care of maintaining
if (NULL == tmp)
return -1;
epdp->ed_fds = tmp;
- memset((char*) (epdp->ed_fds + oldsize), 0,
+ memset((char*) (epdp->ed_fds + oldsize), 0,
(newsize - oldsize)*sizeof(struct fd_info));
epdp->ed_nevents = newsize;
}
}
- if ((res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN,
+ if ((res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN,
(unsigned int *) &nevents, ts_p)) == -1) {
if (errno == EINTR || errno == EAGAIN) {
evsig_process(base);
} else if (base->sig.evsig_caught) {
evsig_process(base);
}
-
+
event_debug(("%s: port_getn reports %d events", __func__, nevents));
for (i = 0; i < nevents; ++i) {
epdp->ed_pending[i] = fd;
/*
- * Figure out what kind of event it was
+ * Figure out what kind of event it was
* (because we have to pass this to the callback)
*/
res = 0;
hook = mm_calloc(1, sizeof(struct evrpc_hook));
assert(hook != NULL);
-
+
hook->process = cb;
hook->process_arg = cb_arg;
TAILQ_INSERT_TAIL(head, hook, next);
constructed_uri,
evrpc_request_cb,
rpc);
-
+
mm_free(constructed_uri);
return (0);
return (-1);
}
TAILQ_REMOVE(&base->registered_rpcs, rpc, next);
-
+
mm_free((char *)rpc->uri);
mm_free(rpc);
if (pool->base != NULL)
evhttp_connection_set_base(connection, pool->base);
- /*
+ /*
* unless a timeout was specifically set for a connection,
* the connection inherits the timeout from the pool.
*/
if (connection->timeout == -1)
connection->timeout = pool->timeout;
- /*
+ /*
* if we have any requests pending, schedule them with the new
* connections.
*/
if (TAILQ_FIRST(&pool->requests) != NULL) {
- struct evrpc_request_wrapper *request =
+ struct evrpc_request_wrapper *request =
TAILQ_FIRST(&pool->requests);
TAILQ_REMOVE(&pool->requests, request, next);
evrpc_schedule_request(connection, request);
/*
* Prototypes responsible for evrpc scheduling and hooking
- */
+ */
static void evrpc_schedule_request_closure(void *ctx, enum EVRPC_HOOK_RESULT);
goto error;
if (pool->timeout > 0) {
- /*
+ /*
* a timeout after which the whole rpc is going to be aborted.
*/
struct timeval tv;
/* we better have some available connections on the pool */
assert(TAILQ_FIRST(&pool->connections) != NULL);
- /*
+ /*
* if no connection is available, we queue the request on the pool,
* the next time a connection is empty, the rpc will be send on that.
*/
struct evrpc_request_wrapper *ctx = arg;
struct evrpc_pool *pool = ctx->pool;
int hook_res = EVRPC_CONTINUE;
-
+
/* cancel any timeout we might have scheduled */
event_del(&ctx->ev_timeout);
}
(*ctx->cb)(&status, ctx->request, ctx->reply, ctx->cb_arg);
-
+
evrpc_request_wrapper_free(ctx);
/* the http layer owned the orignal request structure, but if we
if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
event_warn("fcntl(O_NONBLOCK)");
return -1;
-}
+}
#endif
return 0;
}
#define NI_NUMERICSERV 2
static int
-fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
+fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
size_t hostlen, char *serv, size_t servlen, int flags)
{
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
-
+
if (serv != NULL) {
char tmpserv[16];
evutil_snprintf(tmpserv, sizeof(tmpserv),
return (0);
} else {
struct hostent *hp;
- hp = gethostbyaddr((char *)&sin->sin_addr,
+ hp = gethostbyaddr((char *)&sin->sin_addr,
sizeof(struct in_addr), AF_INET);
if (hp == NULL)
return (-2);
-
+
if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
return (-1);
else
/* Echo the character back */
buf[0] = ch;
buf[1] = '\0';
-
+
return buf;
}
{
if (timeout != 0) {
struct timeval tv;
-
+
evutil_timerclear(&tv);
tv.tv_sec = timeout != -1 ? timeout : default_timeout;
event_add(ev, &tv);
struct evhttp_request *req)
{
const char *method;
-
+
evhttp_remove_header(req->output_headers, "Proxy-Connection");
/* Generate request line */
evhttp_is_connection_keepalive(struct evkeyvalq* headers)
{
const char *connection = evhttp_find_header(headers, "Connection");
- return (connection != NULL
+ return (connection != NULL
&& strncasecmp(connection, "keep-alive", 10) == 0);
}
if ((req->minor == 1 || is_keepalive) &&
evhttp_response_needs_body(req)) {
- /*
+ /*
* we need to add the content length if the
* user did not give it, this is required for
* persistent connections to work.
{
struct evkeyval *header;
struct evbuffer *output = bufferevent_get_output(evcon->bufev);
-
+
/*
* Depending if this is a HTTP request or response, we might need to
* add some new headers or remove existing headers.
switch (error) {
case EVCON_HTTP_TIMEOUT:
case EVCON_HTTP_EOF:
- /*
+ /*
* these are cases in which we probably should just
* close the connection and not send a reply. this
* case may happen when a browser keeps a persistent
req->uri = NULL;
}
- /*
+ /*
* the callback needs to send a reply, once the reply has
* been send, the connection should get freed.
*/
(*req->cb)(req, req->cb_arg);
}
-
+
return (0);
}
void (*cb)(struct evhttp_request *, void *);
void *cb_arg;
assert(req != NULL);
-
+
bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
if (evcon->flags & EVHTTP_CON_INCOMING) {
- /*
+ /*
* for incoming requests, there are two different
* failure cases. it's either a network level error
* or an http layer error. for problems on the network
/* reset the connection */
evhttp_connection_reset(evcon);
-
+
/* We are trying the next request that was queued on us */
if (TAILQ_FIRST(&evcon->requests) != NULL)
evhttp_connection_connect(evcon);
evcon->state = EVCON_IDLE;
- need_close =
+ need_close =
evhttp_is_connection_close(req->flags, req->input_headers)||
evhttp_is_connection_close(req->flags, req->output_headers);
evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
{
struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
-
+
if (req->chunked) {
switch (evhttp_handle_chunked_read(req, buf)) {
case ALL_DATA_READ:
evhttp_request_dispatch(struct evhttp_connection* evcon)
{
struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
-
+
/* this should not usually happy but it's possible */
if (req == NULL)
return;
/* delete possible close detection events */
evhttp_connection_stop_detectclose(evcon);
-
+
/* we assume that the connection is connected already */
assert(evcon->state == EVCON_IDLE);
/* For connections from the client, we just
* reset the connection so that it becomes
* disconnected.
- */
+ */
assert(evcon->state == EVCON_IDLE);
evhttp_connection_reset(evcon);
return;
evcon);
if (evcon->timeout == -1)
- bufferevent_settimeout(evcon->bufev,
+ bufferevent_settimeout(evcon->bufev,
HTTP_READ_TIMEOUT, HTTP_WRITE_TIMEOUT);
else
- bufferevent_settimeout(evcon->bufev,
+ bufferevent_settimeout(evcon->bufev,
evcon->timeout, evcon->timeout);
/* try to start requests that have queued up on this connection */
content_length = evhttp_find_header(headers, "Content-Length");
connection = evhttp_find_header(headers, "Connection");
-
+
if (content_length == NULL && connection == NULL)
req->ntoread = -1;
else if (content_length == NULL &&
}
req->ntoread = ntoread;
}
-
+
event_debug(("%s: bytes to read: %d (in buffer %ld)\n",
__func__, req->ntoread,
EVBUFFER_LENGTH(bufferevent_get_input(req->evcon->bufev))));
evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
{
const char *xfer_enc;
-
+
/* If this is a request without a body, then we are done */
if (req->kind == EVHTTP_REQUEST &&
(req->type != EVHTTP_REQ_POST && req->type != EVHTTP_REQ_PUT)) {
const char *address, unsigned short port)
{
struct evhttp_connection *evcon = NULL;
-
+
event_debug(("Attempting connection to %s:%d\n", address, port));
if ((evcon = mm_calloc(1, sizeof(struct evhttp_connection))) == NULL) {
}
return (evcon);
-
+
error:
if (evcon != NULL)
evhttp_connection_free(evcon);
evcon->timeout = timeout_in_secs;
if (evcon->timeout == -1)
- bufferevent_settimeout(evcon->bufev,
+ bufferevent_settimeout(evcon->bufev,
HTTP_READ_TIMEOUT, HTTP_WRITE_TIMEOUT);
else
- bufferevent_settimeout(evcon->bufev,
+ bufferevent_settimeout(evcon->bufev,
evcon->timeout, evcon->timeout);
}
{
if (evcon->state == EVCON_CONNECTING)
return (0);
-
+
evhttp_connection_reset(evcon);
assert(!(evcon->flags & EVHTTP_CON_INCOMING));
evcon->flags |= EVHTTP_CON_OUTGOING;
-
+
evcon->fd = bind_socket(
evcon->bind_address, evcon->bind_port, 0 /*reuse*/);
if (evcon->fd == -1) {
/* Set up a callback for successful connection setup */
bufferevent_setfd(evcon->bufev, evcon->fd);
- bufferevent_setcb(evcon->bufev,
+ bufferevent_setcb(evcon->bufev,
NULL /* evhttp_read_cb */,
evhttp_connection_cb,
evhttp_error_cb, evcon);
bufferevent_enable(evcon->bufev, EV_WRITE);
evcon->state = EVCON_CONNECTING;
-
+
return (0);
}
req->major = 1;
req->minor = 1;
}
-
+
assert(req->evcon == NULL);
req->evcon = evcon;
assert(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
-
+
TAILQ_INSERT_TAIL(&evcon->requests, req, next);
/* If the connection object is not connected; make it so */
if (need_close) {
evhttp_connection_free(evcon);
return;
- }
+ }
/* we have a persistent connection; try to accept another request. */
if (evhttp_associate_new_request_with_connection(evcon) == -1) {
/* xxx: not sure if we really should expose the data buffer this way */
if (databuf != NULL)
evbuffer_add_buffer(req->output_buffer, databuf);
-
+
/* Adds headers to the response */
evhttp_make_header(evcon, req);
struct evbuffer *databuf)
{
evhttp_response_code(req, code, reason);
-
+
evhttp_send(req, databuf);
}
req->major = 1;
req->minor = 1;
}
-
+
if (req->kind != EVHTTP_RESPONSE)
evhttp_response_code(req, 200, "OK");
evbuffer_add(buf, "", 1);
p = mm_strdup((char *)EVBUFFER_DATA(buf));
evbuffer_free(buf);
-
+
return (p);
}
evhttp_decode_uri(const char *uri)
{
char *ret;
-
+
if ((ret = mm_malloc(strlen(uri) + 1)) == NULL)
event_err(1, "%s: malloc(%lu)", __func__,
(unsigned long)(strlen(uri) + 1));
evhttp_decode_uri_internal(uri, strlen(uri), ret);
-
+
return (ret);
}
-/*
+/*
* Helper function to parse out arguments in a query.
* The arguments are separated by key and value.
* URI should already be decoded.
prefix_suffix_match(const char *pattern, const char *name, int ignorecase)
{
char c;
-
+
while (1) {
switch (c = *pattern++) {
case '\0':
}
res = evhttp_accept_socket(http, fd);
-
+
if (res != -1)
event_debug(("Bound to port %d - Awaiting connections ... ",
port));
if (http->vhost_pattern != NULL)
mm_free(http->vhost_pattern);
-
+
mm_free(http);
}
evcon->flags |= EVHTTP_CON_INCOMING;
evcon->state = EVCON_READING_FIRSTLINE;
-
+
evcon->fd = fd;
bufferevent_setfd(evcon->bufev, fd);
req->evcon = evcon; /* the request ends up owning the connection */
req->flags |= EVHTTP_REQ_OWN_CONNECTION;
-
+
TAILQ_INSERT_TAIL(&evcon->requests, req, next);
-
+
req->kind = EVHTTP_REQUEST;
-
+
if ((req->remote_host = mm_strdup(evcon->address)) == NULL)
event_err(1, "%s: strdup", __func__);
req->remote_port = evcon->port;
evhttp_start_read(evcon);
-
+
return (0);
}
if (http->timeout != -1)
evhttp_connection_set_timeout(evcon, http->timeout);
- /*
+ /*
* if we want to accept more than one request on a connection,
* we need to know which http server it belongs to.
*/
evcon->http_server = http;
TAILQ_INSERT_TAIL(&http->connections, evcon, next);
-
+
if (evhttp_associate_new_request_with_connection(evcon) == -1)
evhttp_connection_free(evcon);
}
ni_result = getnameinfo(sa, salen,
ntop, sizeof(ntop), strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV);
-
+
if (ni_result != 0) {
if (ni_result == EAI_SYSTEM)
event_err(1, "getnameinfo failed");
/* just create an unbound socket */
if (address == NULL && port == 0)
return bind_socket_ai(NULL, 0);
-
+
aitop = make_addrinfo(address, port);
if (aitop == NULL)
/**
Get the kernel event notification mechanism used by libevent.
-
+
@param eb the event_base structure returned by event_base_new()
@return a string identifying the kernel event mechanism (kqueue, epoll, etc.)
*/
/** Removes the callback for a specified URI */
int evhttp_del_cb(struct evhttp *, const char *);
-/**
+/**
Set a callback for all requests that are not caught by specific callbacks
Invokes the specified callback for all requests that do not match any of
void evhttp_connection_get_peer(struct evhttp_connection *evcon,
char **address, ev_uint16_t *port);
-/**
+/**
Make an HTTP request over the specified connection.
-
+
The connection gets ownership of the request.
@param evcon the evhttp_connection object over which to send the request
/**
Cancels a pending HTTP request.
-
+
Cancels an ongoing HTTP request. The callback associated with this request
is not executed and the request object is freed. If the request is
currently being processed, e.g. it is ongoing, the corresponding
/**
Finds the value belonging to a header.
-
+
@param headers the evkeyvalq object in which to find the header
@param key the name of the header to find
@returns a pointer to the value for the header or NULL if the header
/**
Removes a header from a list of exisiting headers.
-
+
@param headers the evkeyvalq object from which to remove a header
@param key the name of the header to remove
@returns 0 if the header was removed, -1 otherwise.
/**
Adds a header to a list of exisiting headers.
-
+
@param headers the evkeyvalq object to which to add a header
@param key the name of the header
@param value the value belonging to the header
#define _EVENT2_THREAD_H_
/** @file thread.h
-
+
Functions for multi-threaded applications using libevent.
When using a multi-threaded application in which multiple threads
return (NULL);
/* Initalize the kernel queue */
-
+
if ((kq = kqueue()) == -1) {
event_warn("kqueue");
mm_free (kqueueop);
kqueueop->changes[0].ident = -1;
kqueueop->changes[0].filter = EVFILT_READ;
kqueueop->changes[0].flags = EV_ADD;
- /*
+ /*
* If kqueue works, then kevent will succeed, and it will
* stick an error in events[0]. If kqueue is broken, then
* kevent will fail.
memcpy(&kqop->changes[kqop->nchanges++], kev, sizeof(struct kevent));
event_debug(("%s: fd %d %s%s",
- __func__, (int)kev->ident,
+ __func__, (int)kev->ident,
kev->filter == EVFILT_READ ? "EVFILT_READ" : "EVFILT_WRITE",
kev->flags == EV_DELETE ? " (del)" : ""));
int which = 0;
if (events[i].flags & EV_ERROR) {
- /*
+ /*
* Error messages that can happen, when a delete fails.
* EBADF happens when the file discriptor has been
* closed,
kev.flags = EV_ADD;
if (events & EV_ET)
kev.flags |= EV_CLEAR;
-
+
if (kq_insert(kqop, &kev) == -1)
return (-1);
}
kev.flags = EV_ADD;
if (events & EV_ET)
kev.flags |= EV_CLEAR;
-
+
if (kq_insert(kqop, &kev) == -1)
return (-1);
}
kev.ident = fd;
kev.filter = EVFILT_READ;
kev.flags = EV_DELETE;
-
+
if (kq_insert(kqop, &kev) == -1)
return (-1);
}
kev.ident = fd;
kev.filter = EVFILT_WRITE;
kev.flags = EV_DELETE;
-
+
if (kq_insert(kqop, &kev) == -1)
return (-1);
}
(void)p;
assert(nsignal >= 0 && nsignal < NSIG);
-
+
memset(&kev, 0, sizeof(kev));
kev.ident = nsignal;
kev.filter = EVFILT_SIGNAL;
kev.flags = EV_ADD;
-
+
/* Be ready for the signal if it is sent any
* time between now and the next call to
* kq_dispatch. */
if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1)
return (-1);
-
+
if (_evsig_set_handler(base, nsignal, kq_sighandler) == -1)
return (-1);
kev.ident = nsignal;
kev.filter = EVFILT_SIGNAL;
kev.flags = EV_DELETE;
-
+
/* Because we insert signal events
* immediately, we need to delete them
* immediately, too */
event_err(int eval, const char *fmt, ...)
{
va_list ap;
-
+
va_start(ap, fmt);
_warn_helper(_EVENT_LOG_ERR, strerror(errno), fmt, ap);
va_end(ap);
event_warn(const char *fmt, ...)
{
va_list ap;
-
+
va_start(ap, fmt);
_warn_helper(_EVENT_LOG_WARN, strerror(errno), fmt, ap);
va_end(ap);
event_errx(int eval, const char *fmt, ...)
{
va_list ap;
-
+
va_start(ap, fmt);
_warn_helper(_EVENT_LOG_ERR, NULL, fmt, ap);
va_end(ap);
event_warnx(const char *fmt, ...)
{
va_list ap;
-
+
va_start(ap, fmt);
_warn_helper(_EVENT_LOG_WARN, NULL, fmt, ap);
va_end(ap);
event_msgx(const char *fmt, ...)
{
va_list ap;
-
+
va_start(ap, fmt);
_warn_helper(_EVENT_LOG_MSG, NULL, fmt, ap);
va_end(ap);
_event_debugx(const char *fmt, ...)
{
va_list ap;
-
+
va_start(ap, fmt);
_warn_helper(_EVENT_LOG_DEBUG, NULL, fmt, ap);
va_end(ap);
#ifdef WIN32
len = ReadFile((HANDLE)fd, buf, sizeof(buf) - 1, &dwBytesRead, NULL);
- // Check for end of file.
+ // Check for end of file.
if(len && dwBytesRead == 0) {
fprintf(stderr, "End Of File");
event_del(ev);
struct event evfifo;
#ifdef WIN32
HANDLE socket;
- // Open a file.
- socket = CreateFile("test.txt", // open File
- GENERIC_READ, // open for reading
- 0, // do not share
- NULL, // no security
- OPEN_EXISTING, // existing file only
- FILE_ATTRIBUTE_NORMAL, // normal file
- NULL); // no attr. template
+ // Open a file.
+ socket = CreateFile("test.txt", // open File
+ GENERIC_READ, // open for reading
+ 0, // do not share
+ NULL, // no security
+ OPEN_EXISTING, // existing file only
+ FILE_ATTRIBUTE_NORMAL, // normal file
+ NULL); // no attr. template
if(socket == INVALID_HANDLE_VALUE)
return 1;
struct stat st;
const char *fifo = "event.fifo";
int socket;
-
+
if (lstat (fifo, &st) == 0) {
if ((st.st_mode & S_IFMT) == S_IFREG) {
errno = EEXIST;
/* Add it to the active events, without a timeout */
event_add(&evfifo, NULL);
-
+
event_dispatch();
#ifdef WIN32
CloseHandle(socket);
if (called >= 2)
event_del(signal);
-
+
called++;
}
main (int argc, char **argv)
{
struct event signal_int;
-
+
/* Initalize the event library */
event_init();
{
struct event timeout;
struct timeval tv;
-
+
/* Initalize the event library */
event_init();
event_add(&timeout, &tv);
lasttime = time(NULL);
-
+
event_dispatch();
return (0);
void
evsig_init(struct event_base *base)
{
- /*
+ /*
* Our signal handler is going to write to one end of the socket
* pair to wake up our event loop. The event loop then scans for
* signals that got delivered.
struct evsig_info *sig = &base->sig;
sig_atomic_t ncalls;
int i;
-
+
base->sig.evsig_caught = 0;
for (i = 1; i < NSIG; ++i) {
ncalls = sig->evsigcaught[i];
roff += len;
if (!usepersist) {
- if (event_add(ev, NULL) == -1)
+ if (event_add(ev, NULL) == -1)
exit(1);
}
}
/* Very simple read test */
setup_test("Simple read: ");
-
+
write(pair[0], TEST1, strlen(TEST1)+1);
shutdown(pair[0], SHUT_WR);
/* Very simple write test */
setup_test("Simple write: ");
-
+
event_set(&ev, pair[0], EV_WRITE, simple_write_cb, &ev);
if (event_add(&ev, NULL) == -1)
exit(1);
/* Very simple read test */
setup_test("Simple read to multiple evens: ");
-
+
write(pair[0], TEST1, strlen(TEST1)+1);
shutdown(pair[0], SHUT_WR);
event_base_free(current_base);
- /* we do not send an EOF; simple_read_cb requires an EOF
+ /* we do not send an EOF; simple_read_cb requires an EOF
* to set test_ok. we just verify that the callback was
* called. */
exit(test_ok != 0 || called != 2 ? -2 : 76);
fprintf(stdout, "FAILED (fork)\n");
exit(1);
}
-
+
if (WEXITSTATUS(status) != 76) {
fprintf(stdout, "FAILED (exit): %d\n", WEXITSTATUS(status));
exit(1);
setup_test("Loop Multiple exit: ");
base = event_base_new();
-
+
tv.tv_usec = 0;
tv.tv_sec = 1;
event_base_loopexit(base, &tv);
event_base_dispatch(base);
event_base_free(base);
-
+
test_ok = 1;
cleanup_test();
{
struct evbuffer_chain *chain, *previous = NULL;
size_t sum = 0;
-
+
if (buf->first == NULL) {
assert(buf->last == NULL);
assert(buf->previous_to_last == NULL);
evbuffer_validate(evb);
}
}
-
+
test_ok = 1;
-
+
out:
evbuffer_free(evb);
evbuffer_free(evb_two);
sum += j;
}
}
-
+
if (sum == EVBUFFER_LENGTH(buf))
test_ok = 1;
fprintf(stdout, "Testing evbuffer_find 1: ");
evbuffer_add(buf, (u_char*)test1, strlen(test1));
evbuffer_validate(buf);
- evbuffer_drain(buf, strlen(test1));
+ evbuffer_drain(buf, strlen(test1));
evbuffer_validate(buf);
evbuffer_add(buf, (u_char*)test2, strlen(test2));
evbuffer_validate(buf);
write(pair[1], TEST1, strlen(TEST1)+1);
event_loop(EVLOOP_ONCE);
event_del(&e1);
-
+
if (test_ok != 3)
test_ok = 0;
/* Very simple read test */
setup_test("Want read only once: ");
-
+
write(pair[0], TEST1, strlen(TEST1)+1);
/* Setup the loop termination */
evutil_timerclear(&tv);
tv.tv_sec = 1;
event_loopexit(&tv);
-
+
event_set(&ev, pair[1], EV_READ, read_once_cb, &ev);
if (event_add(&ev, NULL) == -1)
exit(1);
fprintf(stderr, "Incorrect note strings encoded.\n");
exit(1);
}
-
+
if (EVTAG_GET(run, large_number, &large_number) == -1 ||
large_number != 0xdead0a0bcafebeefLL) {
fprintf(stderr, "Incorrrect large_number.\n");
test_signal_assert();
test_signal_while_processing();
#endif
-
+
return (0);
}
struct sockaddr *sa;
int slen;
int fd;
-
+
#ifdef WIN32
if (!(he = gethostbyname(address))) {
event_warn("gethostbyname");
sa = aitop->ai_addr;
slen = aitop->ai_addrlen;
#endif
-
+
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1)
event_err(1, "socket failed");
const char *what = BASIC_REQUEST_BODY;
event_debug(("%s: %s\n", __func__, EVBUFFER_DATA(EVBUFFER_INPUT(bev))));
-
+
if (evbuffer_find(EVBUFFER_INPUT(bev),
(const unsigned char*) what, strlen(what)) != NULL) {
struct evhttp_request *req = evhttp_request_new(NULL, NULL);
int empty = evhttp_find_header(req->input_headers, "Empty") != NULL;
event_debug(("%s: called\n", __func__));
evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
-
+
/* For multi-line headers test */
{
const char *multi =
if (strcmp(evhttp_request_uri(req), "/streamed") == 0) {
evhttp_add_header(req->output_headers, "Content-Length", "39");
}
-
+
/* generate a chunked/streamed reply */
evhttp_send_reply_start(req, HTTP_OK, "Everything is fine");
fprintf(stdout, "FAILED (bind)\n");
exit(1);
}
-
+
fd = http_connect("127.0.0.1", port);
/* Stupid thing to send a request */
timerclear(&tv);
tv.tv_usec = 10000;
event_once(-1, EV_TIMEOUT, http_complete_write, bev, &tv);
-
+
event_dispatch();
if (test_ok != 3) {
"\r\n";
bufferevent_write(bev, http_request, strlen(http_request));
-
+
event_dispatch();
bufferevent_free(bev);
EVUTIL_CLOSESOCKET(fd);
evhttp_free(http);
-
+
if (test_ok != 5) {
fprintf(stdout, "FAILED\n");
exit(1);
fprintf(stdout, "Testing HTTP DELETE Request: ");
http = http_setup(&port, NULL);
-
+
fd = http_connect("127.0.0.1", port);
/* Stupid thing to send a request */
"\r\n";
bufferevent_write(bev, http_request, strlen(http_request));
-
+
event_dispatch();
bufferevent_free(bev);
EVUTIL_CLOSESOCKET(fd);
evhttp_free(http);
-
+
if (test_ok != 2) {
fprintf(stdout, "FAILED\n");
exit(1);
}
-
+
fprintf(stdout, "OK\n");
}
short port = -1;
struct evhttp_connection *evcon = NULL;
struct evhttp_request *req = NULL;
-
+
test_ok = 0;
fprintf(stdout, "Testing Request Connection Pipeline %s: ",
persistent ? "(persistent)" : "");
/* try to make another request over the same connection */
test_ok = 0;
-
+
req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
/* Add the information that we care about */
evhttp_add_header(req->output_headers, "Host", "somehost");
- /*
+ /*
* if our connections are not supposed to be persistent; request
* a close from the server.
*/
/* make another request: request empty reply */
test_ok = 0;
-
+
req = evhttp_request_new(http_request_empty_done, NULL);
/* Add the information that we care about */
evhttp_connection_free(evcon);
evhttp_free(http);
-
+
fprintf(stdout, "OK\n");
}
struct evhttp_connection *evcon = NULL;
struct evhttp_request *req = NULL;
struct timeval tv;
-
+
test_ok = 0;
fprintf(stdout, "Testing Request Cancelation: ");
/* try to make another request over the same connection */
test_ok = 0;
-
+
req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
/* Add the information that we care about */
/* make another request: request empty reply */
test_ok = 0;
-
+
req = evhttp_request_new(http_request_empty_done, NULL);
/* Add the information that we care about */
evhttp_connection_free(evcon);
evhttp_free(http);
-
+
fprintf(stdout, "OK\n");
}
fprintf(stderr, "FAILED\n");
exit(1);
}
-
+
if (memcmp(EVBUFFER_DATA(req->input_buffer), what, strlen(what)) != 0) {
fprintf(stderr, "FAILED\n");
exit(1);
struct evhttp_connection *evcon = NULL;
struct evhttp_request *req = NULL;
struct evhttp *second = NULL, *third = NULL;
-
+
test_ok = 0;
fprintf(stdout, "Testing Virtual Hosts: ");
evhttp_connection_free(evcon);
evhttp_free(http);
-
+
fprintf(stdout, "OK\n");
}
exit(1);
}
-
+
if (evhttp_find_header(req->input_headers, "Content-Length") == NULL) {
fprintf(stderr, "FAILED\n");
exit(1);
EVBUFFER_LENGTH(req->input_buffer), strlen(what));
exit(1);
}
-
+
if (memcmp(EVBUFFER_DATA(req->input_buffer), what, strlen(what)) != 0) {
fprintf(stderr, "FAILED (data)\n");
exit(1);
/* Add the information that we care about */
evhttp_add_header(req->output_headers, "Host", "somehost");
-
+
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/?arg=val") == -1) {
fprintf(stdout, "FAILED\n");
exit(1);
evhttp_connection_free(evcon);
evhttp_free(http);
-
+
if (test_ok != 1) {
fprintf(stdout, "FAILED: %d\n", test_ok);
exit(1);
}
-
+
fprintf(stdout, "OK\n");
}
/* Add the information that we care about */
evhttp_add_header(req->output_headers, "Host", "somehost");
evbuffer_add_printf(req->output_buffer, POST_DATA);
-
+
if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/postit") == -1) {
fprintf(stdout, "FAILED\n");
exit(1);
evhttp_connection_free(evcon);
evhttp_free(http);
-
+
if (test_ok != 1) {
fprintf(stdout, "FAILED: %d\n", test_ok);
exit(1);
}
-
+
fprintf(stdout, "OK\n");
}
fprintf(stdout, "Want:%s\n", POST_DATA);
exit(1);
}
-
+
evb = evbuffer_new();
evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
}
if (req->response_code != HTTP_OK) {
-
+
fprintf(stderr, "FAILED (response code)\n");
exit(1);
}
EVBUFFER_LENGTH(req->input_buffer), strlen(what));
exit(1);
}
-
+
if (memcmp(EVBUFFER_DATA(req->input_buffer), what, strlen(what)) != 0) {
fprintf(stderr, "FAILED (data)\n");
exit(1);
/* Add the information that we care about */
evhttp_add_header(req->output_headers, "Host", "someotherhost");
evbuffer_add_printf(req->output_buffer, PUT_DATA);
-
+
if (evhttp_make_request(evcon, req, EVHTTP_REQ_PUT, "/putit") == -1) {
fprintf(stdout, "FAILED\n");
exit(1);
evhttp_connection_free(evcon);
evhttp_free(http);
-
+
if (test_ok != 1) {
fprintf(stdout, "FAILED: %d\n", test_ok);
exit(1);
}
-
+
fprintf(stdout, "OK\n");
}
fprintf(stdout, "Want:%s\n", PUT_DATA);
exit(1);
}
-
+
evb = evbuffer_new();
evbuffer_add_printf(evb, "That ain't funny");
}
if (req->response_code != HTTP_OK) {
-
+
fprintf(stderr, "FAILED (response code)\n");
exit(1);
}
EVBUFFER_LENGTH(req->input_buffer), strlen(what));
exit(1);
}
-
+
if (memcmp(EVBUFFER_DATA(req->input_buffer), what, strlen(what)) != 0) {
fprintf(stderr, "FAILED (data)\n");
exit(1);
fprintf(stdout, "Testing Bad HTTP Request: ");
http = http_setup(&port, NULL);
-
+
fd = http_connect("127.0.0.1", port);
/* Stupid thing to send a request */
http_request = "illegal request\r\n";
bufferevent_write(bev, http_request, strlen(http_request));
-
+
event_dispatch();
bufferevent_free(bev);
EVUTIL_CLOSESOCKET(fd);
evhttp_free(http);
-
+
if (test_ok != 2) {
fprintf(stdout, "FAILED\n");
exit(1);
}
-
+
fprintf(stdout, "OK\n");
}
struct timeval tv;
if (req != NULL && req->response_code != HTTP_OK) {
-
+
fprintf(stderr, "FAILED\n");
exit(1);
}
short port = -1;
struct evhttp_connection *evcon = NULL;
struct evhttp_request *req = NULL;
-
+
test_ok = 0;
fprintf(stdout, "Testing Connection Close Detection%s: ",
with_delay ? " (with delay)" : "");
evhttp_connection_free(evcon);
evhttp_free(http);
-
+
fprintf(stdout, "OK\n");
}
{
int i = -1;
struct evhttp *myhttp = NULL;
-
+
fprintf(stdout, "Testing HTTP Server with high port: ");
/* Try a few different ports */
if (evhttp_add_header(&headers, "One", "Two") != 0)
goto fail;
-
+
if (evhttp_add_header(&headers, "One\r", "Two") != -1)
goto fail;
base = event_init();
- /*
+ /*
* create another bogus base - which is being used by all subsequen
* tests - yuck!
*/
tmp = event_init();
http = http_setup(&port, base);
-
+
fd = http_connect("127.0.0.1", port);
/* Stupid thing to send a request */
"\r\n";
bufferevent_write(bev, http_request, strlen(http_request));
-
+
event_base_dispatch(base);
bufferevent_free(bev);
event_base_free(base);
base = tmp;
-
+
if (test_ok != 2) {
fprintf(stdout, "FAILED\n");
exit(1);
}
-
+
fprintf(stdout, "OK\n");
}
fd = http_connect("127.0.0.1", port);
/* Stupid thing to send a request */
- bev = bufferevent_new(fd,
+ bev = bufferevent_new(fd,
http_incomplete_readcb, http_incomplete_writecb,
http_incomplete_errorcb, use_timeout ? NULL : &fd);
bufferevent_write(bev, http_request, strlen(http_request));
evutil_gettimeofday(&tv_start, NULL);
-
+
event_dispatch();
evutil_gettimeofday(&tv_end, NULL);
fprintf(stdout, "FAILED\n");
exit(1);
}
-
+
fprintf(stdout, "OK\n");
}
struct evhttp_request *req = evhttp_request_new(NULL, NULL);
const char *header;
enum message_read_status done;
-
+
req->kind = EVHTTP_RESPONSE;
done = evhttp_parse_firstline(req, EVBUFFER_INPUT(bev));
if (done != ALL_DATA_READ)
fprintf(stderr, "FAILED\n");
exit(1);
}
-
+
test_ok = 1;
event_loopexit(NULL);
}
fd = http_connect("127.0.0.1", port);
/* Stupid thing to send a request */
- bev = bufferevent_new(fd,
+ bev = bufferevent_new(fd,
http_chunked_readcb, http_chunked_writecb,
http_chunked_errorcb, NULL);
bufferevent_write(bev, http_request, strlen(http_request));
evutil_gettimeofday(&tv_start, NULL);
-
+
event_dispatch();
bufferevent_free(bev);
evhttp_connection_free(evcon);
evhttp_free(http);
-
+
fprintf(stdout, "OK\n");
}
short port = -1;
struct evhttp_connection *evcon = NULL;
struct evhttp_request *req = NULL;
-
+
test_ok = 0;
printf("Tests streaming responses out: ");
evhttp_connection_free(evcon);
evhttp_free(http);
-
+
fprintf(stdout, "OK\n");
}
fprintf(stderr, "FAILED (connection aborted)\n");
exit(1);
}
-
+
if (req->response_code == HTTP_OK) {
fprintf(stderr, "FAILED\n");
exit(1);
fprintf(stderr, "FAILED (length)\n");
exit(1);
}
-
+
test_ok = 1;
event_loopexit(NULL);
}
/* Add the information that we care about */
evhttp_add_header(req->output_headers, "Host", "somehost");
-
+
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
"/?arg=val") == -1) {
fprintf(stdout, "FAILED\n");
/* Add the information that we care about */
evhttp_add_header(req->output_headers, "Host", "somehost");
-
+
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
"/?arg=val") == -1) {
fprintf(stdout, "FAILED\n");
/* Add the information that we care about */
evhttp_add_header(req->output_headers, "Host", "somehost");
-
+
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
"/?arg=val") == -1) {
fprintf(stdout, "FAILED\n");
evhttp_connection_free(evcon);
evhttp_free(http);
-
+
fprintf(stdout, "OK\n");
}
int fd;
const char *http_start_request;
short port = -1;
-
+
test_ok = 0;
fprintf(stdout, "Testing HTTP Server with multi line: ");
http = http_setup(&port, NULL);
-
+
fd = http_connect("127.0.0.1", port);
/* Stupid thing to send a request */
"\tEND\r\n"
"X-Last: last\r\n"
"\r\n";
-
+
bufferevent_write(bev, http_start_request, strlen(http_start_request));
event_dispatch();
-
+
bufferevent_free(bev);
close(fd);
fprintf(stdout, "FAILED\n");
exit(1);
}
-
+
fprintf(stdout, "OK\n");
}
short port = -1;
struct evhttp_connection *evcon = NULL;
struct evhttp_request *req = NULL;
-
+
test_ok = 0;
fprintf(stdout, "Testing HTTP Negative Content Length: ");
http = http_setup(&port);
base = evrpc_init(http);
-
+
EVRPC_REGISTER(base, Message, msg, kill, MessageCb, NULL);
EVRPC_REGISTER(base, NeverReply, msg, kill, NeverReplyCb, NULL);
rpc_postrequest_failure(struct evhttp_request *req, void *arg)
{
if (req->response_code != HTTP_SERVUNAVAIL) {
-
+
fprintf(stderr, "FAILED (response code)\n");
exit(1);
}
/* Add the information that we care about */
evhttp_add_header(req->output_headers, "Host", "somehost");
evbuffer_add_printf(req->output_buffer, "Some Nonsense");
-
+
if (evhttp_make_request(evcon, req,
EVHTTP_REQ_POST,
"/.rpc.Message") == -1) {
evhttp_connection_free(evcon);
rpc_teardown(base);
-
+
if (test_ok != 1) {
fprintf(stdout, "FAILED\n");
exit(1);
struct kill* kill_reply = NULL;
if (req->response_code != HTTP_OK) {
-
+
fprintf(stderr, "FAILED (response code)\n");
exit(1);
}
fprintf(stderr, "FAILED (unmarshal)\n");
exit(1);
}
-
+
kill_free(kill_reply);
test_ok = 1;
event_dispatch();
evhttp_connection_free(evcon);
-
+
rpc_teardown(base);
-
+
if (test_ok != 1) {
fprintf(stdout, "FAILED\n");
exit(1);
assert(evcon != NULL);
evrpc_pool_add_connection(pool, evcon);
-
+
return (pool);
}
const char *hook_type = arg;
if (strcmp("input", hook_type) == 0)
evhttp_add_header(req->input_headers, "X-Hook", hook_type);
- else
+ else
evhttp_add_header(req->output_headers, "X-Hook", hook_type);
assert(evrpc_hook_get_connection(ctx) != NULL);
test_ok = 0;
event_dispatch();
-
+
if (test_ok != 1) {
fprintf(stdout, "FAILED (1)\n");
exit(1);
EVRPC_MAKE_REQUEST(Message, pool, msg, kill, GotKillCb, NULL);
event_dispatch();
-
+
if (test_ok != 2) {
fprintf(stdout, "FAILED (2)\n");
exit(1);
}
event_dispatch();
-
+
rpc_teardown(base);
-
+
if (test_ok != 3) {
fprintf(stdout, "FAILED (3)\n");
exit(1);
need_output_hook = 0;
}
-/*
+/*
* We are testing that the second requests gets send over the same
* connection after the first RPCs completes.
*/
test_ok = 0;
event_dispatch();
-
+
rpc_teardown(base);
-
+
if (test_ok != 2) {
fprintf(stdout, "FAILED (1)\n");
exit(1);
test_ok = 0;
event_dispatch();
-
+
if (test_ok != 1 || hook_pause_cb_called != 4) {
fprintf(stdout, "FAILED\n");
exit(1);
}
rpc_teardown(base);
-
+
fprintf(stdout, "OK\n");
msg_free(msg);
test_ok = 0;
event_dispatch();
-
+
/* free the saved RPC structure up */
EVRPC_REQUEST_DONE(saved_rpc);
rpc_teardown(base);
-
+
if (test_ok != 2) {
fprintf(stdout, "FAILED (1)\n");
exit(1);
if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
return (1);
-
+
write(pair[0], test, strlen(test)+1);
shutdown(pair[0], SHUT_WR);