root/opal/mca/event/libevent2022/libevent/event_tagging.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. evtag_init
  2. encode_int_internal
  3. encode_int64_internal
  4. evtag_encode_int
  5. evtag_encode_int64
  6. evtag_encode_tag
  7. decode_tag_internal
  8. evtag_decode_tag
  9. evtag_marshal
  10. evtag_marshal_buffer
  11. evtag_marshal_int
  12. evtag_marshal_int64
  13. evtag_marshal_string
  14. evtag_marshal_timeval
  15. decode_int_internal
  16. decode_int64_internal
  17. evtag_decode_int
  18. evtag_decode_int64
  19. evtag_peek
  20. evtag_peek_length
  21. evtag_payload_length
  22. evtag_unmarshal_header
  23. evtag_consume
  24. evtag_unmarshal
  25. evtag_unmarshal_int
  26. evtag_unmarshal_int64
  27. evtag_unmarshal_fixed
  28. evtag_unmarshal_string
  29. evtag_unmarshal_timeval

   1 /*
   2  * Copyright (c) 2003-2009 Niels Provos <provos@citi.umich.edu>
   3  * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
   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 #include "event2/event-config.h"
  29 
  30 #ifdef _EVENT_HAVE_SYS_TYPES_H
  31 #include <sys/types.h>
  32 #endif
  33 #ifdef _EVENT_HAVE_SYS_PARAM_H
  34 #include <sys/param.h>
  35 #endif
  36 
  37 #ifdef WIN32
  38 #define WIN32_LEAN_AND_MEAN
  39 #include <winsock2.h>
  40 #include <windows.h>
  41 #undef WIN32_LEAN_AND_MEAN
  42 #else
  43 #include <sys/ioctl.h>
  44 #endif
  45 
  46 #include <sys/queue.h>
  47 #ifdef _EVENT_HAVE_SYS_TIME_H
  48 #include <sys/time.h>
  49 #endif
  50 
  51 #include <errno.h>
  52 #include <stdio.h>
  53 #include <stdlib.h>
  54 #include <string.h>
  55 #ifndef WIN32
  56 #include <syslog.h>
  57 #endif
  58 #ifdef _EVENT_HAVE_UNISTD_H
  59 #include <unistd.h>
  60 #endif
  61 #include <limits.h>
  62 
  63 #include "event2/event.h"
  64 #include "event2/tag.h"
  65 #include "event2/buffer.h"
  66 #include "log-internal.h"
  67 #include "mm-internal.h"
  68 #include "util-internal.h"
  69 
  70 /*
  71   Here's our wire format:
  72 
  73   Stream = TaggedData*
  74 
  75   TaggedData = Tag Length Data
  76        where the integer value of 'Length' is the length of 'data'.
  77 
  78   Tag = HByte* LByte
  79        where HByte is a byte with the high bit set, and LByte is a byte
  80        with the high bit clear. The integer value of the tag is taken
  81        by concatenating the lower 7 bits from all the tags.  So for example,
  82        the tag 0x66 is encoded as [66], whereas the tag 0x166 is encoded as
  83        [82 66]
  84 
  85   Length = Integer
  86 
  87   Integer = NNibbles Nibble* Padding?
  88        where NNibbles is a 4-bit value encoding the number of nibbles-1,
  89        and each Nibble is 4 bits worth of encoded integer, in big-endian
  90        order.  If the total encoded integer size is an odd number of nibbles,
  91        a final padding nibble with value 0 is appended.
  92 */
  93 
  94 int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf);
  95 int evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf);
  96 int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag);
  97 int evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf);
  98 
  99 void
 100 evtag_init(void)
 101 {
 102 }
 103 
 104 /*
 105  * We encode integers by nibbles; the first nibble contains the number
 106  * of significant nibbles - 1;  this allows us to encode up to 64-bit
 107  * integers.  This function is byte-order independent.
 108  *
 109  * @param number a 32-bit unsigned integer to encode
 110  * @param data a pointer to where the data should be written.  Must
 111  *    have at least 5 bytes free.
 112  * @return the number of bytes written into data.
 113  */
 114 
 115 #define ENCODE_INT_INTERNAL(data, number) do {                          \
 116         int off = 1, nibbles = 0;                                       \
 117                                                                         \
 118         memset(data, 0, sizeof(number)+1);                              \
 119         while (number) {                                                \
 120                 if (off & 0x1)                                          \
 121                         data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f); \
 122                 else                                                    \
 123                         data[off/2] = (data[off/2] & 0x0f) |            \
 124                             ((number & 0x0f) << 4);                     \
 125                 number >>= 4;                                           \
 126                 off++;                                                  \
 127         }                                                               \
 128                                                                         \
 129         if (off > 2)                                                    \
 130                 nibbles = off - 2;                                      \
 131                                                                         \
 132         /* Off - 1 is the number of encoded nibbles */                  \
 133         data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4);           \
 134                                                                         \
 135         return ((off + 1) / 2);                                         \
 136 } while (0)
 137 
 138 static inline int
 139 encode_int_internal(ev_uint8_t *data, ev_uint32_t number)
 140 {
 141         ENCODE_INT_INTERNAL(data, number);
 142 }
 143 
 144 static inline int
 145 encode_int64_internal(ev_uint8_t *data, ev_uint64_t number)
 146 {
 147         ENCODE_INT_INTERNAL(data, number);
 148 }
 149 
 150 void
 151 evtag_encode_int(struct evbuffer *evbuf, ev_uint32_t number)
 152 {
 153         ev_uint8_t data[5];
 154         int len = encode_int_internal(data, number);
 155         evbuffer_add(evbuf, data, len);
 156 }
 157 
 158 void
 159 evtag_encode_int64(struct evbuffer *evbuf, ev_uint64_t number)
 160 {
 161         ev_uint8_t data[9];
 162         int len = encode_int64_internal(data, number);
 163         evbuffer_add(evbuf, data, len);
 164 }
 165 
 166 /*
 167  * Support variable length encoding of tags; we use the high bit in each
 168  * octet as a continuation signal.
 169  */
 170 
 171 int
 172 evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag)
 173 {
 174         int bytes = 0;
 175         ev_uint8_t data[5];
 176 
 177         memset(data, 0, sizeof(data));
 178         do {
 179                 ev_uint8_t lower = tag & 0x7f;
 180                 tag >>= 7;
 181 
 182                 if (tag)
 183                         lower |= 0x80;
 184 
 185                 data[bytes++] = lower;
 186         } while (tag);
 187 
 188         if (evbuf != NULL)
 189                 evbuffer_add(evbuf, data, bytes);
 190 
 191         return (bytes);
 192 }
 193 
 194 static int
 195 decode_tag_internal(ev_uint32_t *ptag, struct evbuffer *evbuf, int dodrain)
 196 {
 197         ev_uint32_t number = 0;
 198         size_t len = evbuffer_get_length(evbuf);
 199         ev_uint8_t *data;
 200         size_t count = 0;
 201         int  shift = 0, done = 0;
 202 
 203         /*
 204          * the encoding of a number is at most one byte more than its
 205          * storage size.  however, it may also be much smaller.
 206          */
 207         data = evbuffer_pullup(
 208                 evbuf, len < sizeof(number) + 1 ? len : sizeof(number) + 1);
 209         if (!data)
 210                 return (-1);
 211 
 212         while (count++ < len) {
 213                 ev_uint8_t lower = *data++;
 214                 number |= (lower & 0x7f) << shift;
 215                 shift += 7;
 216 
 217                 if (!(lower & 0x80)) {
 218                         done = 1;
 219                         break;
 220                 }
 221         }
 222 
 223         if (!done)
 224                 return (-1);
 225 
 226         if (dodrain)
 227                 evbuffer_drain(evbuf, count);
 228 
 229         if (ptag != NULL)
 230                 *ptag = number;
 231 
 232         return count > INT_MAX ? INT_MAX : (int)(count);
 233 }
 234 
 235 int
 236 evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf)
 237 {
 238         return (decode_tag_internal(ptag, evbuf, 1 /* dodrain */));
 239 }
 240 
 241 /*
 242  * Marshal a data type, the general format is as follows:
 243  *
 244  * tag number: one byte; length: var bytes; payload: var bytes
 245  */
 246 
 247 void
 248 evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag,
 249     const void *data, ev_uint32_t len)
 250 {
 251         evtag_encode_tag(evbuf, tag);
 252         evtag_encode_int(evbuf, len);
 253         evbuffer_add(evbuf, (void *)data, len);
 254 }
 255 
 256 void
 257 evtag_marshal_buffer(struct evbuffer *evbuf, ev_uint32_t tag,
 258     struct evbuffer *data)
 259 {
 260         evtag_encode_tag(evbuf, tag);
 261         /* XXX support more than UINT32_MAX data */
 262         evtag_encode_int(evbuf, (ev_uint32_t)evbuffer_get_length(data));
 263         evbuffer_add_buffer(evbuf, data);
 264 }
 265 
 266 /* Marshaling for integers */
 267 void
 268 evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, ev_uint32_t integer)
 269 {
 270         ev_uint8_t data[5];
 271         int len = encode_int_internal(data, integer);
 272 
 273         evtag_encode_tag(evbuf, tag);
 274         evtag_encode_int(evbuf, len);
 275         evbuffer_add(evbuf, data, len);
 276 }
 277 
 278 void
 279 evtag_marshal_int64(struct evbuffer *evbuf, ev_uint32_t tag,
 280     ev_uint64_t integer)
 281 {
 282         ev_uint8_t data[9];
 283         int len = encode_int64_internal(data, integer);
 284 
 285         evtag_encode_tag(evbuf, tag);
 286         evtag_encode_int(evbuf, len);
 287         evbuffer_add(evbuf, data, len);
 288 }
 289 
 290 void
 291 evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, const char *string)
 292 {
 293         /* TODO support strings longer than UINT32_MAX ? */
 294         evtag_marshal(buf, tag, string, (ev_uint32_t)strlen(string));
 295 }
 296 
 297 void
 298 evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, struct timeval *tv)
 299 {
 300         ev_uint8_t data[10];
 301         int len = encode_int_internal(data, tv->tv_sec);
 302         len += encode_int_internal(data + len, tv->tv_usec);
 303         evtag_marshal(evbuf, tag, data, len);
 304 }
 305 
 306 #define DECODE_INT_INTERNAL(number, maxnibbles, pnumber, evbuf, offset) \
 307 do {                                                                    \
 308         ev_uint8_t *data;                                               \
 309         ev_ssize_t len = evbuffer_get_length(evbuf) - offset;           \
 310         int nibbles = 0;                                                \
 311                                                                         \
 312         if (len <= 0)                                                   \
 313                 return (-1);                                            \
 314                                                                         \
 315         /* XXX(niels): faster? */                                       \
 316         data = evbuffer_pullup(evbuf, offset + 1) + offset;             \
 317         if (!data)                                                      \
 318                 return (-1);                                            \
 319                                                                         \
 320         nibbles = ((data[0] & 0xf0) >> 4) + 1;                          \
 321         if (nibbles > maxnibbles || (nibbles >> 1) + 1 > len)           \
 322                 return (-1);                                            \
 323         len = (nibbles >> 1) + 1;                                       \
 324                                                                         \
 325         data = evbuffer_pullup(evbuf, offset + len) + offset;           \
 326         if (!data)                                                      \
 327                 return (-1);                                            \
 328                                                                         \
 329         while (nibbles > 0) {                                           \
 330                 number <<= 4;                                           \
 331                 if (nibbles & 0x1)                                      \
 332                         number |= data[nibbles >> 1] & 0x0f;            \
 333                 else                                                    \
 334                         number |= (data[nibbles >> 1] & 0xf0) >> 4;     \
 335                 nibbles--;                                              \
 336         }                                                               \
 337                                                                         \
 338         *pnumber = number;                                              \
 339                                                                         \
 340         return (int)(len);                                              \
 341 } while (0)
 342 
 343 /* Internal: decode an integer from an evbuffer, without draining it.
 344  *  Only integers up to 32-bits are supported.
 345  *
 346  * @param evbuf the buffer to read from
 347  * @param offset an index into the buffer at which we should start reading.
 348  * @param pnumber a pointer to receive the integer.
 349  * @return The length of the number as encoded, or -1 on error.
 350  */
 351 
 352 static int
 353 decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int offset)
 354 {
 355         ev_uint32_t number = 0;
 356         DECODE_INT_INTERNAL(number, 8, pnumber, evbuf, offset);
 357 }
 358 
 359 static int
 360 decode_int64_internal(ev_uint64_t *pnumber, struct evbuffer *evbuf, int offset)
 361 {
 362         ev_uint64_t number = 0;
 363         DECODE_INT_INTERNAL(number, 16, pnumber, evbuf, offset);
 364 }
 365 
 366 int
 367 evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf)
 368 {
 369         int res = decode_int_internal(pnumber, evbuf, 0);
 370         if (res != -1)
 371                 evbuffer_drain(evbuf, res);
 372 
 373         return (res == -1 ? -1 : 0);
 374 }
 375 
 376 int
 377 evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf)
 378 {
 379         int res = decode_int64_internal(pnumber, evbuf, 0);
 380         if (res != -1)
 381                 evbuffer_drain(evbuf, res);
 382 
 383         return (res == -1 ? -1 : 0);
 384 }
 385 
 386 int
 387 evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag)
 388 {
 389         return (decode_tag_internal(ptag, evbuf, 0 /* dodrain */));
 390 }
 391 
 392 int
 393 evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength)
 394 {
 395         int res, len;
 396 
 397         len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
 398         if (len == -1)
 399                 return (-1);
 400 
 401         res = decode_int_internal(plength, evbuf, len);
 402         if (res == -1)
 403                 return (-1);
 404 
 405         *plength += res + len;
 406 
 407         return (0);
 408 }
 409 
 410 int
 411 evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength)
 412 {
 413         int res, len;
 414 
 415         len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
 416         if (len == -1)
 417                 return (-1);
 418 
 419         res = decode_int_internal(plength, evbuf, len);
 420         if (res == -1)
 421                 return (-1);
 422 
 423         return (0);
 424 }
 425 
 426 /* just unmarshals the header and returns the length of the remaining data */
 427 
 428 int
 429 evtag_unmarshal_header(struct evbuffer *evbuf, ev_uint32_t *ptag)
 430 {
 431         ev_uint32_t len;
 432 
 433         if (decode_tag_internal(ptag, evbuf, 1 /* dodrain */) == -1)
 434                 return (-1);
 435         if (evtag_decode_int(&len, evbuf) == -1)
 436                 return (-1);
 437 
 438         if (evbuffer_get_length(evbuf) < len)
 439                 return (-1);
 440 
 441         return (len);
 442 }
 443 
 444 int
 445 evtag_consume(struct evbuffer *evbuf)
 446 {
 447         int len;
 448         if ((len = evtag_unmarshal_header(evbuf, NULL)) == -1)
 449                 return (-1);
 450         evbuffer_drain(evbuf, len);
 451 
 452         return (0);
 453 }
 454 
 455 /* Reads the data type from an event buffer */
 456 
 457 int
 458 evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, struct evbuffer *dst)
 459 {
 460         int len;
 461 
 462         if ((len = evtag_unmarshal_header(src, ptag)) == -1)
 463                 return (-1);
 464 
 465         if (evbuffer_add(dst, evbuffer_pullup(src, len), len) == -1)
 466                 return (-1);
 467 
 468         evbuffer_drain(src, len);
 469 
 470         return (len);
 471 }
 472 
 473 /* Marshaling for integers */
 474 
 475 int
 476 evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
 477     ev_uint32_t *pinteger)
 478 {
 479         ev_uint32_t tag;
 480         ev_uint32_t len;
 481         int result;
 482 
 483         if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1)
 484                 return (-1);
 485         if (need_tag != tag)
 486                 return (-1);
 487         if (evtag_decode_int(&len, evbuf) == -1)
 488                 return (-1);
 489 
 490         if (evbuffer_get_length(evbuf) < len)
 491                 return (-1);
 492 
 493         result = decode_int_internal(pinteger, evbuf, 0);
 494         evbuffer_drain(evbuf, len);
 495         if (result < 0 || (size_t)result > len) /* XXX Should this be != rather than > ?*/
 496                 return (-1);
 497         else
 498                 return result;
 499 }
 500 
 501 int
 502 evtag_unmarshal_int64(struct evbuffer *evbuf, ev_uint32_t need_tag,
 503     ev_uint64_t *pinteger)
 504 {
 505         ev_uint32_t tag;
 506         ev_uint32_t len;
 507         int result;
 508 
 509         if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1)
 510                 return (-1);
 511         if (need_tag != tag)
 512                 return (-1);
 513         if (evtag_decode_int(&len, evbuf) == -1)
 514                 return (-1);
 515 
 516         if (evbuffer_get_length(evbuf) < len)
 517                 return (-1);
 518 
 519         result = decode_int64_internal(pinteger, evbuf, 0);
 520         evbuffer_drain(evbuf, len);
 521         if (result < 0 || (size_t)result > len) /* XXX Should this be != rather than > ?*/
 522                 return (-1);
 523         else
 524                 return result;
 525 }
 526 
 527 /* Unmarshal a fixed length tag */
 528 
 529 int
 530 evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, void *data,
 531     size_t len)
 532 {
 533         ev_uint32_t tag;
 534         int tag_len;
 535 
 536         /* Now unmarshal a tag and check that it matches the tag we want */
 537         if ((tag_len = evtag_unmarshal_header(src, &tag)) < 0 ||
 538             tag != need_tag)
 539                 return (-1);
 540 
 541         if ((size_t)tag_len != len)
 542                 return (-1);
 543 
 544         evbuffer_remove(src, data, len);
 545         return (0);
 546 }
 547 
 548 int
 549 evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag,
 550     char **pstring)
 551 {
 552         ev_uint32_t tag;
 553         int tag_len;
 554 
 555         if ((tag_len = evtag_unmarshal_header(evbuf, &tag)) == -1 ||
 556             tag != need_tag)
 557                 return (-1);
 558 
 559         *pstring = mm_malloc(tag_len + 1);
 560         if (*pstring == NULL) {
 561                 event_warn("%s: malloc", __func__);
 562                 return -1;
 563         }
 564         evbuffer_remove(evbuf, *pstring, tag_len);
 565         (*pstring)[tag_len] = '\0';
 566 
 567         return (0);
 568 }
 569 
 570 int
 571 evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag,
 572     struct timeval *ptv)
 573 {
 574         ev_uint32_t tag;
 575         ev_uint32_t integer;
 576         int len, offset, offset2;
 577         int result = -1;
 578 
 579         if ((len = evtag_unmarshal_header(evbuf, &tag)) == -1)
 580                 return (-1);
 581         if (tag != need_tag)
 582                 goto done;
 583         if ((offset = decode_int_internal(&integer, evbuf, 0)) == -1)
 584                 goto done;
 585         ptv->tv_sec = integer;
 586         if ((offset2 = decode_int_internal(&integer, evbuf, offset)) == -1)
 587                 goto done;
 588         ptv->tv_usec = integer;
 589         if (offset + offset2 > len) /* XXX Should this be != instead of > ? */
 590                 goto done;
 591 
 592         result = 0;
 593  done:
 594         evbuffer_drain(evbuf, len);
 595         return result;
 596 }

/* [<][>][^][v][top][bottom][index][help] */