| OLD | NEW |
| (Empty) |
| 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 *t
v) | |
| 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 } | |
| OLD | NEW |