(linenum→info "unix/slp.c:2238")

dbus/1.0.2/dbus/dbus-marshal-header.c

    1: /* -*- mode: C; c-file-style: "gnu" -*- */
    2: /* dbus-marshal-header.c  Managing marshaling/demarshaling of message headers
    3:  *
    4:  * Copyright (C) 2005  Red Hat, Inc.
    5:  *
    6:  * Licensed under the Academic Free License version 2.1
    7:  *
    8:  * This program is free software; you can redistribute it and/or modify
    9:  * it under the terms of the GNU General Public License as published by
   10:  * the Free Software Foundation; either version 2 of the License, or
   11:  * (at your option) any later version.
   12:  *
   13:  * This program is distributed in the hope that it will be useful,
   14:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16:  * GNU General Public License for more details.
   17:  *
   18:  * You should have received a copy of the GNU General Public License
   19:  * along with this program; if not, write to the Free Software
   20:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   21:  *
   22:  */
   23: 
   24: #include "dbus/dbus-shared.h"
   25: #include "dbus-marshal-header.h"
   26: #include "dbus-marshal-recursive.h"
   27: #include "dbus-marshal-byteswap.h"
   28: 
   29: /**
   30:  * @addtogroup DBusMarshal
   31:  *
   32:  * @{
   33:  */
   34: 
   35: 
   36: /* Not thread locked, but strictly const/read-only so should be OK
   37:  */
   38: /** Static #DBusString containing the signature of a message header */
   39: _DBUS_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE);
   40: /** Static #DBusString containing the local interface */
   41: _DBUS_STRING_DEFINE_STATIC(_dbus_local_interface_str,  DBUS_INTERFACE_LOCAL);
   42: /** Static #DBusString containing the local path */
   43: _DBUS_STRING_DEFINE_STATIC(_dbus_local_path_str,       DBUS_PATH_LOCAL);
   44: 
   45: /** Offset from start of _dbus_header_signature_str to the signature of the fields array */
   46: #define FIELDS_ARRAY_SIGNATURE_OFFSET 6
   47: /** Offset from start of _dbus_header_signature_str to the signature of an element of the fields array */
   48: #define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET 7
   49: 
   50: 
   51: /** Offset to byte order from start of header */
   52: #define BYTE_ORDER_OFFSET    0
   53: /** Offset to type from start of header */
   54: #define TYPE_OFFSET          1
   55: /** Offset to flags from start of header */
   56: #define FLAGS_OFFSET         2
   57: /** Offset to version from start of header */
   58: #define VERSION_OFFSET       3
   59: /** Offset to body length from start of header */
   60: #define BODY_LENGTH_OFFSET 4
   61: /** Offset to client serial from start of header */
   62: #define SERIAL_OFFSET 8
   63: /** Offset to fields array length from start of header */
   64: #define FIELDS_ARRAY_LENGTH_OFFSET 12
   65: /** Offset to first field in header */
   66: #define FIRST_FIELD_OFFSET 16
   67: 
   68: typedef struct
   69: {
   70:   unsigned char code; /**< the field code */
   71:   unsigned char type; /**< the value type */
   72: } HeaderFieldType;
   73: 
   74: static const HeaderFieldType
   75: _dbus_header_field_types[DBUS_HEADER_FIELD_LAST+1] = {
   76:   { DBUS_HEADER_FIELD_INVALID, DBUS_TYPE_INVALID },
   77:   { DBUS_HEADER_FIELD_PATH, DBUS_TYPE_OBJECT_PATH },
   78:   { DBUS_HEADER_FIELD_INTERFACE, DBUS_TYPE_STRING },
   79:   { DBUS_HEADER_FIELD_MEMBER, DBUS_TYPE_STRING },
   80:   { DBUS_HEADER_FIELD_ERROR_NAME, DBUS_TYPE_STRING },
   81:   { DBUS_HEADER_FIELD_REPLY_SERIAL, DBUS_TYPE_UINT32 },
   82:   { DBUS_HEADER_FIELD_DESTINATION, DBUS_TYPE_STRING },
   83:   { DBUS_HEADER_FIELD_SENDER, DBUS_TYPE_STRING },
   84:   { DBUS_HEADER_FIELD_SIGNATURE, DBUS_TYPE_SIGNATURE }
   85: };
   86: 
   87: /** Macro to look up the correct type for a field */
   88: #define EXPECTED_TYPE_OF_FIELD(field) (_dbus_header_field_types[field].type)
   89: 
   90: /** The most padding we could ever need for a header */
   91: #define MAX_POSSIBLE_HEADER_PADDING 7
   92: static dbus_bool_t
   93: reserve_header_padding (DBusHeader *header)
   94: {
   95:   _dbus_assert (header->padding <= MAX_POSSIBLE_HEADER_PADDING);
   96: 
   97:   if (!_dbus_string_lengthen (&header->data,
   98:                               MAX_POSSIBLE_HEADER_PADDING - header->padding))
   99:     return FALSE;
  100:   header->padding = MAX_POSSIBLE_HEADER_PADDING;
  101:   return TRUE;
  102: }
  103: 
  104: static void
  105: correct_header_padding (DBusHeader *header)
  106: {
  107:   int unpadded_len;
  108: 
  109:   _dbus_assert (header->padding == 7);
  110: 
  111:   _dbus_string_shorten (&header->data, header->padding);
  112:   unpadded_len = _dbus_string_get_length (&header->data);
  113: 
  114:   if (!_dbus_string_align_length (&header->data, 8))
  115:     _dbus_assert_not_reached ("couldn't pad header though enough padding was preallocated");
  116: 
  117:   header->padding = _dbus_string_get_length (&header->data) - unpadded_len;
  118: }
  119: 
  120: /** Compute the end of the header, ignoring padding */
  121: #define HEADER_END_BEFORE_PADDING(header) \
  122:   (_dbus_string_get_length (&(header)->data) - (header)->padding)
  123: 
  124: /**
  125:  * Invalidates all fields in the cache. This may be used when the
  126:  * cache is totally uninitialized (contains junk) so should not
  127:  * look at what's in there now.
  128:  *
  129:  * @param header the header
  130:  */
  131: static void
  132: _dbus_header_cache_invalidate_all (DBusHeader *header)
  133: {
  134:   int i;
  135: 
  136:   i = 0;
  137:   while (i <= DBUS_HEADER_FIELD_LAST)
  138:     {
  139:       header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_UNKNOWN;
  140:       ++i;
  141:     }
  142: }
  143: 
  144: /**
  145:  * Caches one field
  146:  *
  147:  * @param header the header
  148:  * @param field_code the field
  149:  * @param variant_reader the reader for the variant in the field
  150:  */
  151: static void
  152: _dbus_header_cache_one (DBusHeader     *header,
  153:                         int             field_code,
  154:                         DBusTypeReader *variant_reader)
  155: {
  156:   header->fields[field_code].value_pos =
  157:     _dbus_type_reader_get_value_pos (variant_reader);
  158: 
  159: #if 0
  160:   _dbus_verbose ("cached value_pos %d for field %d\n",
  161:                  header->fields[field_code].value_pos, field_code)
  162: #endif
  163: }
  164: 
  165: /**
  166:  * Revalidates the fields cache
  167:  *
  168:  * @param header the header
  169:  */
  170: static void
  171: _dbus_header_cache_revalidate (DBusHeader *header)
  172: {
  173:   DBusTypeReader array;
  174:   DBusTypeReader reader;
  175:   int i;
  176: 
  177:   i = 0;
  178:   while (i <= DBUS_HEADER_FIELD_LAST)
  179:     {
  180:       header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
  181:       ++i;
  182:     }
  183: 
  184:   _dbus_type_reader_init (&reader,
  185:                           header->byte_order,
  186:                           &_dbus_header_signature_str,
  187:                           FIELDS_ARRAY_SIGNATURE_OFFSET,
  188:                           &header->data,
  189:                           FIELDS_ARRAY_LENGTH_OFFSET);
  190: 
  191:   _dbus_type_reader_recurse (&reader, &array);
  192: 
  193:   while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
  194:     {
  195:       DBusTypeReader sub;
  196:       DBusTypeReader variant;
  197:       unsigned char field_code;
  198: 
  199:       _dbus_type_reader_recurse (&array, &sub);
  200: 
  201:       _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
  202:       _dbus_type_reader_read_basic (&sub, &field_code);
  203: 
  204:       /* Unknown fields should be ignored */
  205:       if (field_code > DBUS_HEADER_FIELD_LAST)
  206:         goto next_field;
  207: 
  208:       _dbus_type_reader_next (&sub);
  209: 
  210:       _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_VARIANT);
  211:       _dbus_type_reader_recurse (&sub, &variant);
  212: 
  213:       _dbus_header_cache_one (header, field_code, &variant);
  214: 
  215:     next_field:
  216:       _dbus_type_reader_next (&array);
  217:     }
  218: }
  219: 
  220: /**
  221:  * Checks for a field, updating the cache if required.
  222:  *
  223:  * @param header the header
  224:  * @param field the field to check
  225:  * @returns #FALSE if the field doesn't exist
  226:  */
  227: static dbus_bool_t
  228: _dbus_header_cache_check (DBusHeader    *header,
  229:                           int            field)
  230: {
  231:   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
  232: 
  233:   if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
  234:     _dbus_header_cache_revalidate (header);
  235: 
  236:   if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT)
  237:     return FALSE;
  238: 
  239:   return TRUE;
  240: }
  241: 
  242: /**
  243:  * Checks whether a field is known not to exist. It may exist
  244:  * even if it's not known to exist.
  245:  *
  246:  * @param header the header
  247:  * @param field the field to check
  248:  * @returns #FALSE if the field definitely doesn't exist
  249:  */
  250: static dbus_bool_t
  251: _dbus_header_cache_known_nonexistent (DBusHeader    *header,
  252:                                       int            field)
  253: {
  254:   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
  255: 
  256:   return (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT);
  257: }
  258: 
  259: /**
  260:  * Writes a struct of { byte, variant } with the given basic type.
  261:  *
  262:  * @param writer the writer (should be ready to write a struct)
  263:  * @param type the type of the value
  264:  * @param value the value as for _dbus_marshal_set_basic()
  265:  * @returns #FALSE if no memory
  266:  */
  267: static dbus_bool_t
  268: write_basic_field (DBusTypeWriter *writer,
  269:                    int             field,
  270:                    int             type,
  271:                    const void     *value)
  272: {
  273:   DBusTypeWriter sub;
  274:   DBusTypeWriter variant;
  275:   int start;
  276:   int padding;
  277:   unsigned char field_byte;
  278:   DBusString contained_type;
  279:   char buf[2];
  280: 
  281:   start = writer->value_pos;
  282:   padding = _dbus_string_get_length (writer->value_str) - start;
  283: 
  284:   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
  285:                                   NULL, 0, &sub))
  286:     goto append_failed;
  287: 
  288:   field_byte = field;
  289:   if (!_dbus_type_writer_write_basic (&sub, DBUS_TYPE_BYTE,
  290:                                       &field_byte))
  291:     goto append_failed;
  292: 
  293:   buf[0] = type;
  294:   buf[1] = '\0';
  295:   _dbus_string_init_const_len (&contained_type, buf, 1);
  296: 
  297:   if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_VARIANT,
  298:                                   &contained_type, 0, &variant))
  299:     goto append_failed;
  300: 
  301:   if (!_dbus_type_writer_write_basic (&variant, type, value))
  302:     goto append_failed;
  303: 
  304:   if (!_dbus_type_writer_unrecurse (&sub, &variant))
  305:     goto append_failed;
  306: 
  307:   if (!_dbus_type_writer_unrecurse (writer, &sub))
  308:     goto append_failed;
  309: 
  310:   return TRUE;
  311: 
  312:  append_failed:
  313:   _dbus_string_delete (writer->value_str,
  314:                        start,
  315:                        _dbus_string_get_length (writer->value_str) - start - padding);
  316:   return FALSE;
  317: }
  318: 
  319: /**
  320:  * Sets a struct of { byte, variant } with the given basic type.
  321:  *
  322:  * @param reader the reader (should be iterating over the array pointing at the field to set)
  323:  * @param type the type of the value
  324:  * @param value the value as for _dbus_marshal_set_basic()
  325:  * @param realign_root where to realign from
  326:  * @returns #FALSE if no memory
  327:  */
  328: static dbus_bool_t
  329: set_basic_field (DBusTypeReader       *reader,
  330:                  int                   field,
  331:                  int                   type,
  332:                  const void           *value,
  333:                  const DBusTypeReader *realign_root)
  334: {
  335:   DBusTypeReader sub;
  336:   DBusTypeReader variant;
  337: 
  338:   _dbus_type_reader_recurse (reader, &sub);
  339: 
  340:   _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
  341: #ifndef DBUS_DISABLE_ASSERT
  342:  {
  343:    unsigned char v_BYTE;
  344:    _dbus_type_reader_read_basic (&sub, &v_BYTE);
  345:    _dbus_assert (((int) v_BYTE) == field);
  346:  }
  347: #endif
  348: 
  349:   if (!_dbus_type_reader_next (&sub))
  350:     _dbus_assert_not_reached ("no variant field?");
  351: 
  352:   _dbus_type_reader_recurse (&sub, &variant);
  353:   _dbus_assert (_dbus_type_reader_get_current_type (&variant) == type);
  354: 
  355:   if (!_dbus_type_reader_set_basic (&variant, value, realign_root))
  356:     return FALSE;
  357: 
  358:   return TRUE;
  359: }
  360: 
  361: /**
  362:  * Gets the type of the message.
  363:  *
  364:  * @param header the header
  365:  * @returns the type
  366:  */
  367: int
  368: _dbus_header_get_message_type (DBusHeader *header)
  369: {
  370:   int type;
  371: 
  372:   type = _dbus_string_get_byte (&header->data, TYPE_OFFSET);
  373:   _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
  374: 
  375:   return type;
  376: }
  377: 
  378: /**
  379:  * Sets the serial number of a header.  This can only be done once on
  380:  * a header.
  381:  *
  382:  * @param header the header
  383:  * @param serial the serial
  384:  */
  385: void
  386: _dbus_header_set_serial (DBusHeader    *header,
  387:                          dbus_uint32_t  serial)
  388: {
  389:   /* we use this function to set the serial on outgoing
  390:    * messages, and to reset the serial in dbus_message_copy;
  391:    * this assertion should catch a double-set on outgoing.
  392:    */
  393:   _dbus_assert (_dbus_header_get_serial (header) == 0 ||
  394:                 serial == 0);
  395: 
  396:   _dbus_marshal_set_uint32 (&header->data,
  397:                             SERIAL_OFFSET,
  398:                             serial,
  399:                             header->byte_order);
  400: }
  401: 
  402: /**
  403:  * See dbus_message_get_serial()
  404:  *
  405:  * @param header the header
  406:  * @returns the client serial
  407:  */
  408: dbus_uint32_t
  409: _dbus_header_get_serial (DBusHeader *header)
  410: {
  411:   return _dbus_marshal_read_uint32 (&header->data,
  412:                                     SERIAL_OFFSET,
  413:                                     header->byte_order,
  414:                                     NULL);
  415: }
  416: 
  417: /**
  418:  * Re-initializes a header that was previously initialized and never
  419:  * freed.  After this, to make the header valid you have to call
  420:  * _dbus_header_create().
  421:  *
  422:  * @param header header to re-initialize
  423:  * @param byte_order byte order of the header
  424:  */
  425: void
  426: _dbus_header_reinit (DBusHeader *header,
  427:                      int         byte_order)
  428: {
  429:   _dbus_string_set_length (&header->data, 0);
  430: 
  431:   header->byte_order = byte_order;
  432:   header->padding = 0;
  433: 
  434:   _dbus_header_cache_invalidate_all (header);
  435: }
  436: 
  437: /**
  438:  * Initializes a header, but doesn't prepare it for use;
  439:  * to make the header valid, you have to call _dbus_header_create().
  440:  *
  441:  * @param header header to initialize
  442:  * @param byte_order byte order of the header
  443:  * @returns #FALSE if not enough memory
  444:  */
  445: dbus_bool_t
  446: _dbus_header_init (DBusHeader *header,
  447:                    int         byte_order)
  448: {
  449:   if (!_dbus_string_init_preallocated (&header->data, 32))
  450:     return FALSE;
  451: 
  452:   _dbus_header_reinit (header, byte_order);
  453: 
  454:   return TRUE;
  455: }
  456: 
  457: /**
  458:  * Frees a header.
  459:  *
  460:  * @param header the header
  461:  */
  462: void
  463: _dbus_header_free (DBusHeader *header)
  464: {
  465:   _dbus_string_free (&header->data);
  466: }
  467: 
  468: /**
  469:  * Initializes dest with a copy of the given header.
  470:  * Resets the message serial to 0 on the copy.
  471:  *
  472:  * @param header header to copy
  473:  * @param dest destination for copy
  474:  * @returns #FALSE if not enough memory
  475:  */
  476: dbus_bool_t
  477: _dbus_header_copy (const DBusHeader *header,
  478:                    DBusHeader       *dest)
  479: {
  480:   *dest = *header;
  481: 
  482:   if (!_dbus_string_init_preallocated (&dest->data,
  483:                                        _dbus_string_get_length (&header->data)))
  484:     return FALSE;
  485: 
  486:   if (!_dbus_string_copy (&header->data, 0, &dest->data, 0))
  487:     {
  488:       _dbus_string_free (&dest->data);
  489:       return FALSE;
  490:     }
  491: 
  492:   /* Reset the serial */
  493:   _dbus_header_set_serial (dest, 0);
  494: 
  495:   return TRUE;
  496: }
  497: 
  498: /**
  499:  * Fills in the primary fields of the header, so the header is ready
  500:  * for use. #NULL may be specified for some or all of the fields to
  501:  * avoid adding those fields. Some combinations of fields don't make
  502:  * sense, and passing them in will trigger an assertion failure.
  503:  *
  504:  * @param header the header
  505:  * @param message_type the message type
  506:  * @param destination destination field or #NULL
  507:  * @param path path field or #NULL
  508:  * @param interface interface field or #NULL
  509:  * @param member member field or #NULL
  510:  * @param error_name error name or #NULL
  511:  * @returns #FALSE if not enough memory
  512:  */
  513: dbus_bool_t
  514: _dbus_header_create (DBusHeader  *header,
  515:                      int          message_type,
  516:                      const char  *destination,
  517:                      const char  *path,
  518:                      const char  *interface,
  519:                      const char  *member,
  520:                      const char  *error_name)
  521: {
  522:   unsigned char v_BYTE;
  523:   dbus_uint32_t v_UINT32;
  524:   DBusTypeWriter writer;
  525:   DBusTypeWriter array;
  526: 
  527:   _dbus_assert (((interface || message_type != DBUS_MESSAGE_TYPE_SIGNAL) && member) ||
  528:                 (error_name) ||
  529:                 !(interface || member || error_name));
  530:   _dbus_assert (_dbus_string_get_length (&header->data) == 0);
  531: 
  532:   if (!reserve_header_padding (header))
  533:     return FALSE;
  534: 
  535:   _dbus_type_writer_init_values_only (&writer, header->byte_order,
  536:                                       &_dbus_header_signature_str, 0,
  537:                                       &header->data,
  538:                                       HEADER_END_BEFORE_PADDING (header));
  539: 
  540:   v_BYTE = header->byte_order;
  541:   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
  542:                                       &v_BYTE))
  543:     goto oom;
  544: 
  545:   v_BYTE = message_type;
  546:   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
  547:                                       &v_BYTE))
  548:     goto oom;
  549: 
  550:   v_BYTE = 0; /* flags */
  551:   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
  552:                                       &v_BYTE))
  553:     goto oom;
  554: 
  555:   v_BYTE = DBUS_MAJOR_PROTOCOL_VERSION;
  556:   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
  557:                                       &v_BYTE))
  558:     goto oom;
  559: 
  560:   v_UINT32 = 0; /* body length */
  561:   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
  562:                                       &v_UINT32))
  563:     goto oom;
  564: 
  565:   v_UINT32 = 0; /* serial */
  566:   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
  567:                                       &v_UINT32))
  568:     goto oom;
  569: 
  570:   if (!_dbus_type_writer_recurse (&writer, DBUS_TYPE_ARRAY,
  571:                                   &_dbus_header_signature_str,
  572:                                   FIELDS_ARRAY_SIGNATURE_OFFSET,
  573:                                   &array))
  574:     goto oom;
  575: 
  576:   /* Marshal all the fields (Marshall Fields?) */
  577: 
  578:   if (path != NULL)
  579:     {
  580:       if (!write_basic_field (&array,
  581:                               DBUS_HEADER_FIELD_PATH,
  582:                               DBUS_TYPE_OBJECT_PATH,
  583:                               &path))
  584:         goto oom;
  585:     }
  586: 
  587:   if (destination != NULL)
  588:     {
  589:       if (!write_basic_field (&array,
  590:                               DBUS_HEADER_FIELD_DESTINATION,
  591:                               DBUS_TYPE_STRING,
  592:                               &destination))
  593:         goto oom;
  594:     }