File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libevent / event_tagging.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:02:54 2012 UTC (12 years, 3 months ago) by misho
Branches: libevent, MAIN
CVS tags: v1_4_14bp0, v1_4_14b, HEAD
libevent

    1: /*
    2:  * Copyright (c) 2003, 2004 Niels Provos <provos@citi.umich.edu>
    3:  * All rights reserved.
    4:  *
    5:  * Redistribution and use in source and binary forms, with or without
    6:  * modification, are permitted provided that the following conditions
    7:  * are met:
    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.
   15:  *
   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.
   26:  */
   27: 
   28: #ifdef HAVE_CONFIG_H
   29: #include "config.h"
   30: #endif
   31: 
   32: #ifdef HAVE_SYS_TYPES_H
   33: #include <sys/types.h>
   34: #endif
   35: #ifdef HAVE_SYS_PARAM_H
   36: #include <sys/param.h>
   37: #endif
   38: 
   39: #ifdef WIN32
   40: #define WIN32_LEAN_AND_MEAN
   41: #include <winsock2.h>
   42: #include <windows.h>
   43: #undef WIN32_LEAN_AND_MEAN
   44: #else
   45: #include <sys/ioctl.h>
   46: #endif
   47: 
   48: #include <sys/queue.h>
   49: #ifdef HAVE_SYS_TIME_H
   50: #include <sys/time.h>
   51: #endif
   52: 
   53: #include <errno.h>
   54: #include <stdio.h>
   55: #include <stdlib.h>
   56: #include <string.h>
   57: #ifndef WIN32
   58: #include <syslog.h>
   59: #endif
   60: #ifdef HAVE_UNISTD_H
   61: #include <unistd.h>
   62: #endif
   63: 
   64: #include "event.h"
   65: #include "evutil.h"
   66: #include "log.h"
   67: 
   68: int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf);
   69: int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag);
   70: int evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf);
   71: 
   72: static struct evbuffer *_buf;	/* not thread safe */
   73: 
   74: void
   75: evtag_init(void)
   76: {
   77: 	if (_buf != NULL)
   78: 		return;
   79: 
   80: 	if ((_buf = evbuffer_new()) == NULL)
   81: 		event_err(1, "%s: malloc", __func__);
   82: }
   83: 
   84: /* 
   85:  * We encode integer's by nibbles; the first nibble contains the number
   86:  * of significant nibbles - 1;  this allows us to encode up to 64-bit
   87:  * integers.  This function is byte-order independent.
   88:  */
   89: 
   90: void
   91: encode_int(struct evbuffer *evbuf, ev_uint32_t number)
   92: {
   93: 	int off = 1, nibbles = 0;
   94: 	ev_uint8_t data[5];
   95: 
   96: 	memset(data, 0, sizeof(ev_uint32_t)+1);
   97: 	while (number) {
   98: 		if (off & 0x1)
   99: 			data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f);
  100: 		else
  101: 			data[off/2] = (data[off/2] & 0x0f) |
  102: 			    ((number & 0x0f) << 4);
  103: 		number >>= 4;
  104: 		off++;
  105: 	}
  106: 
  107: 	if (off > 2)
  108: 		nibbles = off - 2;
  109: 
  110: 	/* Off - 1 is the number of encoded nibbles */
  111: 	data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4);
  112: 
  113: 	evbuffer_add(evbuf, data, (off + 1) / 2);
  114: }
  115: 
  116: /*
  117:  * Support variable length encoding of tags; we use the high bit in each
  118:  * octet as a continuation signal.
  119:  */
  120: 
  121: int
  122: evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag)
  123: {
  124: 	int bytes = 0;
  125: 	ev_uint8_t data[5];
  126: 
  127: 	memset(data, 0, sizeof(data));
  128: 	do {
  129: 		ev_uint8_t lower = tag & 0x7f;
  130: 		tag >>= 7;
  131: 
  132: 		if (tag)
  133: 			lower |= 0x80;
  134: 
  135: 		data[bytes++] = lower;
  136: 	} while (tag);
  137: 
  138: 	if (evbuf != NULL)
  139: 		evbuffer_add(evbuf, data, bytes);
  140: 
  141: 	return (bytes);
  142: }
  143: 
  144: static int
  145: decode_tag_internal(ev_uint32_t *ptag, struct evbuffer *evbuf, int dodrain)
  146: {
  147: 	ev_uint32_t number = 0;
  148: 	ev_uint8_t *data = EVBUFFER_DATA(evbuf);
  149: 	int len = EVBUFFER_LENGTH(evbuf);
  150: 	int count = 0, shift = 0, done = 0;
  151: 
  152: 	while (count++ < len) {
  153: 		ev_uint8_t lower = *data++;
  154: 		number |= (lower & 0x7f) << shift;
  155: 		shift += 7;
  156: 
  157: 		if (!(lower & 0x80)) {
  158: 			done = 1;
  159: 			break;
  160: 		}
  161: 	}
  162: 
  163: 	if (!done)
  164: 		return (-1);
  165: 
  166: 	if (dodrain)
  167: 		evbuffer_drain(evbuf, count);
  168: 
  169: 	if (ptag != NULL)
  170: 		*ptag = number;
  171: 
  172: 	return (count);
  173: }
  174: 
  175: int
  176: evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf)
  177: {
  178: 	return (decode_tag_internal(ptag, evbuf, 1 /* dodrain */));
  179: }
  180: 
  181: /*
  182:  * Marshal a data type, the general format is as follows:
  183:  *
  184:  * tag number: one byte; length: var bytes; payload: var bytes
  185:  */
  186: 
  187: void
  188: evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag,
  189:     const void *data, ev_uint32_t len)
  190: {
  191: 	evtag_encode_tag(evbuf, tag);
  192: 	encode_int(evbuf, len);
  193: 	evbuffer_add(evbuf, (void *)data, len);
  194: }
  195: 
  196: /* Marshaling for integers */
  197: void
  198: evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, ev_uint32_t integer)
  199: {
  200: 	evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
  201: 	encode_int(_buf, integer);
  202: 
  203: 	evtag_encode_tag(evbuf, tag);
  204: 	encode_int(evbuf, EVBUFFER_LENGTH(_buf));
  205: 	evbuffer_add_buffer(evbuf, _buf);
  206: }
  207: 
  208: void
  209: evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, const char *string)
  210: {
  211: 	evtag_marshal(buf, tag, string, strlen(string));
  212: }
  213: 
  214: void
  215: evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, struct timeval *tv)
  216: {
  217: 	evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
  218: 
  219: 	encode_int(_buf, tv->tv_sec);
  220: 	encode_int(_buf, tv->tv_usec);
  221: 
  222: 	evtag_marshal(evbuf, tag, EVBUFFER_DATA(_buf),
  223: 	    EVBUFFER_LENGTH(_buf));
  224: }
  225: 
  226: static int
  227: decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int dodrain)
  228: {
  229: 	ev_uint32_t number = 0;
  230: 	ev_uint8_t *data = EVBUFFER_DATA(evbuf);
  231: 	int len = EVBUFFER_LENGTH(evbuf);
  232: 	int nibbles = 0;
  233: 
  234: 	if (!len)
  235: 		return (-1);
  236: 
  237: 	nibbles = ((data[0] & 0xf0) >> 4) + 1;
  238: 	if (nibbles > 8 || (nibbles >> 1) + 1 > len)
  239: 		return (-1);
  240: 	len = (nibbles >> 1) + 1;
  241: 
  242: 	while (nibbles > 0) {
  243: 		number <<= 4;
  244: 		if (nibbles & 0x1)
  245: 			number |= data[nibbles >> 1] & 0x0f;
  246: 		else
  247: 			number |= (data[nibbles >> 1] & 0xf0) >> 4;
  248: 		nibbles--;
  249: 	}
  250: 
  251: 	if (dodrain)
  252: 		evbuffer_drain(evbuf, len);
  253: 
  254: 	*pnumber = number;
  255: 
  256: 	return (len);
  257: }
  258: 
  259: int
  260: evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf)
  261: {
  262: 	return (decode_int_internal(pnumber, evbuf, 1) == -1 ? -1 : 0);
  263: }
  264: 
  265: int
  266: evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag)
  267: {
  268: 	return (decode_tag_internal(ptag, evbuf, 0 /* dodrain */));
  269: }
  270: 
  271: int
  272: evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength)
  273: {
  274: 	struct evbuffer tmp;
  275: 	int res, len;
  276: 
  277: 	len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
  278: 	if (len == -1)
  279: 		return (-1);
  280: 
  281: 	tmp = *evbuf;
  282: 	tmp.buffer += len;
  283: 	tmp.off -= len;
  284: 
  285: 	res = decode_int_internal(plength, &tmp, 0);
  286: 	if (res == -1)
  287: 		return (-1);
  288: 
  289: 	*plength += res + len;
  290: 
  291: 	return (0);
  292: }
  293: 
  294: int
  295: evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength)
  296: {
  297: 	struct evbuffer tmp;
  298: 	int res, len;
  299: 
  300: 	len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
  301: 	if (len == -1)
  302: 		return (-1);
  303: 
  304: 	tmp = *evbuf;
  305: 	tmp.buffer += len;
  306: 	tmp.off -= len;
  307: 
  308: 	res = decode_int_internal(plength, &tmp, 0);
  309: 	if (res == -1)
  310: 		return (-1);
  311: 
  312: 	return (0);
  313: }
  314: 
  315: int
  316: evtag_consume(struct evbuffer *evbuf)
  317: {
  318: 	ev_uint32_t len;
  319: 	if (decode_tag_internal(NULL, evbuf, 1 /* dodrain */) == -1)
  320: 		return (-1);
  321: 	if (evtag_decode_int(&len, evbuf) == -1)
  322: 		return (-1);
  323: 	evbuffer_drain(evbuf, len);
  324: 
  325: 	return (0);
  326: }
  327: 
  328: /* Reads the data type from an event buffer */
  329: 
  330: int
  331: evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, struct evbuffer *dst)
  332: {
  333: 	ev_uint32_t len;
  334: 	ev_uint32_t integer;
  335: 
  336: 	if (decode_tag_internal(ptag, src, 1 /* dodrain */) == -1)
  337: 		return (-1);
  338: 	if (evtag_decode_int(&integer, src) == -1)
  339: 		return (-1);
  340: 	len = integer;
  341: 
  342: 	if (EVBUFFER_LENGTH(src) < len)
  343: 		return (-1);
  344: 
  345: 	if (evbuffer_add(dst, EVBUFFER_DATA(src), len) == -1)
  346: 		return (-1);
  347: 
  348: 	evbuffer_drain(src, len);
  349: 
  350: 	return (len);
  351: }
  352: 
  353: /* Marshaling for integers */
  354: 
  355: int
  356: evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
  357:     ev_uint32_t *pinteger)
  358: {
  359: 	ev_uint32_t tag;
  360: 	ev_uint32_t len;
  361: 	ev_uint32_t integer;
  362: 
  363: 	if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1)
  364: 		return (-1);
  365: 	if (need_tag != tag)
  366: 		return (-1);
  367: 	if (evtag_decode_int(&integer, evbuf) == -1)
  368: 		return (-1);
  369: 	len = integer;
  370: 
  371: 	if (EVBUFFER_LENGTH(evbuf) < len)
  372: 		return (-1);
  373: 	
  374: 	evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
  375: 	if (evbuffer_add(_buf, EVBUFFER_DATA(evbuf), len) == -1)
  376: 		return (-1);
  377: 
  378: 	evbuffer_drain(evbuf, len);
  379: 
  380: 	return (evtag_decode_int(pinteger, _buf));
  381: }
  382: 
  383: /* Unmarshal a fixed length tag */
  384: 
  385: int
  386: evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, void *data,
  387:     size_t len)
  388: {
  389: 	ev_uint32_t tag;
  390: 
  391: 	/* Initialize this event buffer so that we can read into it */
  392: 	evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
  393: 
  394: 	/* Now unmarshal a tag and check that it matches the tag we want */
  395: 	if (evtag_unmarshal(src, &tag, _buf) == -1 || tag != need_tag)
  396: 		return (-1);
  397: 
  398: 	if (EVBUFFER_LENGTH(_buf) != len)
  399: 		return (-1);
  400: 
  401: 	memcpy(data, EVBUFFER_DATA(_buf), len);
  402: 	return (0);
  403: }
  404: 
  405: int
  406: evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag,
  407:     char **pstring)
  408: {
  409: 	ev_uint32_t tag;
  410: 
  411: 	evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
  412: 
  413: 	if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag)
  414: 		return (-1);
  415: 
  416: 	*pstring = calloc(EVBUFFER_LENGTH(_buf) + 1, 1);
  417: 	if (*pstring == NULL)
  418: 		event_err(1, "%s: calloc", __func__);
  419: 	evbuffer_remove(_buf, *pstring, EVBUFFER_LENGTH(_buf));
  420: 
  421: 	return (0);
  422: }
  423: 
  424: int
  425: evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag,
  426:     struct timeval *ptv)
  427: {
  428: 	ev_uint32_t tag;
  429: 	ev_uint32_t integer;
  430: 
  431: 	evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
  432: 	if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag)
  433: 		return (-1);
  434: 
  435: 	if (evtag_decode_int(&integer, _buf) == -1)
  436: 		return (-1);
  437: 	ptv->tv_sec = integer;
  438: 	if (evtag_decode_int(&integer, _buf) == -1)
  439: 		return (-1);
  440: 	ptv->tv_usec = integer;
  441: 
  442: 	return (0);
  443: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>