2003-01-31 Havoc Pennington <hp@pobox.com>
authorHavoc Pennington <hp@redhat.com>
Fri, 31 Jan 2003 03:49:42 +0000 (03:49 +0000)
committerHavoc Pennington <hp@redhat.com>
Fri, 31 Jan 2003 03:49:42 +0000 (03:49 +0000)
* doc/dbus-specification.sgml: fully specify the header.  Add
flags and major protocol version, and change header/body len to
unsigned.

* dbus/dbus-message-builder.c (append_saved_length): append length
as uint32

* dbus/dbus-message.c (dbus_message_create_header): change header
length and body length to unsigned. Add the new fields from the
spec
(_dbus_message_loader_return_buffer): unsigned header/body len

ChangeLog
dbus/dbus-message-builder.c
dbus/dbus-message.c
dbus/dbus-protocol.h
doc/dbus-specification.sgml

index 1407218..6ea0bfa 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2003-01-31  Havoc Pennington  <hp@pobox.com>
+
+       * doc/dbus-specification.sgml: fully specify the header.  Add
+       flags and major protocol version, and change header/body len to
+       unsigned.
+
+       * dbus/dbus-message-builder.c (append_saved_length): append length
+       as uint32
+
+       * dbus/dbus-message.c (dbus_message_create_header): change header
+       length and body length to unsigned. Add the new fields from the
+       spec
+       (_dbus_message_loader_return_buffer): unsigned header/body len
+
 2003-01-30  Havoc Pennington  <hp@pobox.com>
 
        * dbus/dbus-auth.c: rework to use only REJECTED, no 
index 8d01229..4731333 100644 (file)
@@ -312,8 +312,8 @@ append_saved_length (DBusString       *dest,
       return FALSE;
     }
   
-  if (!_dbus_marshal_int32 (dest, endian,
-                            -1))
+  if (!_dbus_marshal_uint32 (dest, endian,
+                             -1))
     {
       _dbus_warn ("failed to append a length\n");
       return FALSE;
index b485f63..3d0de77 100644 (file)
@@ -422,6 +422,36 @@ set_int_field (DBusMessage *message,
 }
 
 static dbus_bool_t
+set_uint_field (DBusMessage  *message,
+                int           field,
+                dbus_uint32_t value)
+{
+  int offset = message->header_fields[field].offset;
+
+  _dbus_assert (!message->locked);
+  
+  if (offset < 0)
+    {
+      /* need to append the field */
+
+      switch (field)
+        {
+        default:
+          _dbus_assert_not_reached ("appending a uint field we don't support appending");
+          return FALSE;
+        }
+    }
+  else
+    {
+      _dbus_marshal_set_uint32 (&message->header,
+                                message->byte_order,
+                                offset, value);
+
+      return TRUE;
+    }
+}
+
+static dbus_bool_t
 set_string_field (DBusMessage *message,
                   int          field,
                   const char  *value)
@@ -581,19 +611,28 @@ static dbus_bool_t
 dbus_message_create_header (DBusMessage *message,
                             const char  *service,
                             const char  *name)
-{  
+{
+  unsigned int flags;
+  
   if (!_dbus_string_append_byte (&message->header, message->byte_order))
     return FALSE;
-  
-  if (!_dbus_string_append_len (&message->header, "\0\0\0", 3))
+
+  flags = 0;
+  if (!_dbus_string_append_byte (&message->header, flags))
+    return FALSE;
+
+  if (!_dbus_string_append_byte (&message->header, DBUS_MAJOR_PROTOCOL_VERSION))
+    return FALSE;
+
+  if (!_dbus_string_append_byte (&message->header, 0))
     return FALSE;
 
   message->header_fields[FIELD_HEADER_LENGTH].offset = 4;
-  if (!_dbus_marshal_int32 (&message->header, message->byte_order, 0))
+  if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
     return FALSE;
 
   message->header_fields[FIELD_BODY_LENGTH].offset = 8;
-  if (!_dbus_marshal_int32 (&message->header, message->byte_order, 0))
+  if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
     return FALSE;
 
   message->header_fields[FIELD_CLIENT_SERIAL].offset = 12;
@@ -635,13 +674,13 @@ _dbus_message_lock (DBusMessage  *message)
   if (!message->locked)
     {
       /* Fill in our lengths */
-      set_int_field (message,
-                     FIELD_HEADER_LENGTH,
-                     _dbus_string_get_length (&message->header));
+      set_uint_field (message,
+                      FIELD_HEADER_LENGTH,
+                      _dbus_string_get_length (&message->header));
 
-      set_int_field (message,
-                     FIELD_BODY_LENGTH,
-                     _dbus_string_get_length (&message->body));
+      set_uint_field (message,
+                      FIELD_BODY_LENGTH,
+                      _dbus_string_get_length (&message->body));
 
       message->locked = TRUE;
     }
@@ -1955,6 +1994,7 @@ _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
       DBusMessage *message;      
       const char *header_data;
       int byte_order, header_len, body_len;
+      dbus_uint32_t header_len_unsigned, body_len_unsigned;
       
       _dbus_string_get_const_data_len (&loader->data, &header_data, 0, 16);
 
@@ -1971,18 +2011,34 @@ _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
          return;
        }
 
-      header_len = _dbus_unpack_int32 (byte_order, header_data + 4);
-      body_len = _dbus_unpack_int32 (byte_order, header_data + 8);
+      header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
+      body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
 
-      if (header_len < 16 || body_len < 0)
+      if (header_len_unsigned < 16)
         {
-          _dbus_verbose ("Message had broken too-small header or body len %d %d\n",
-                         header_len, body_len);
+          _dbus_verbose ("Message had broken too-small header length %u\n",
+                         header_len_unsigned);
           loader->corrupted = TRUE;
           return;
         }
 
-      if (_DBUS_ALIGN_VALUE (header_len, 8) != (unsigned int) header_len)
+      if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
+          body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
+        {
+          _dbus_verbose ("Header or body length too large (%u %u)\n",
+                         header_len_unsigned,
+                         body_len_unsigned);
+          loader->corrupted = TRUE;
+          return;
+        }      
+
+      /* Now that we know the values are in signed range, get
+       * rid of stupid unsigned, just causes bugs
+       */
+      header_len = header_len_unsigned;
+      body_len = body_len_unsigned;
+      
+      if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
         {
           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
                          header_len);
@@ -1998,7 +2054,7 @@ _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
          return;
        }
 
-      if (_dbus_string_get_length (&loader->data) >= header_len + body_len)
+      if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
        {
           HeaderField fields[FIELD_LAST];
           int i;
index 774ccf2..0df6c2e 100644 (file)
@@ -36,6 +36,9 @@ extern "C" {
 #define DBUS_LITTLE_ENDIAN ('l')  /* LSB first */
 #define DBUS_BIG_ENDIAN    ('B')  /* MSB first */    
 
+/* Protocol version */
+#define DBUS_MAJOR_PROTOCOL_VERSION 0
+
 /* Data types */
 #define DBUS_TYPE_INVALID       0
 #define DBUS_TYPE_NIL           1
index 632575b..b8d80bb 100644 (file)
     <sect2 id="message-protocol-header-encoding">
       <title>Header Encoding</title>
       <para>
-        [document the required header fields and how they are encoded]
+        Following the mandatory fields, there are zero or more named fields (see
+        <xref linkend="message-protocol-header-fields">), and then nul bytes
+        padding the header such that its total length in bytes is a multiple of
+        8.
+      </para>
+      <para>
+        The header MUST begin with the following mandatory fields in the following
+        order:
+        <informaltable>
+          <tgroup cols=2>
+            <thead>
+              <row>
+                <entry>Size</entry>
+                <entry>Description</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry>1 byte</entry>
+                <entry>Endianness flag; ASCII 'l' for little-endian 
+                  or ASCII 'B' for big-endian.</entry>
+              </row>
+              <row>
+                <entry>1 byte</entry>
+                <entry>Bitwise OR of flags. Unknown flags
+                  MUST be ignored. Currently-defined flags are described below.
+                </entry>
+              </row>
+              <row>
+                <entry>1 byte</entry>
+                <entry>Major protocol version of the sending application.  If
+                the major protocol version of the receiving application does not
+                match, the applications will not be able to communicate and the
+                D-BUS connection MUST be disconnected. The major protocol
+                version for this version of the specification is 0.
+                </entry>
+              </row>
+              <row>
+                <entry>1 byte</entry>
+                <entry>A nul byte, reserved for future use.
+                  Any value for this byte MUST be accepted.
+                </entry>
+              </row>
+              <row>
+                <entry>4 bytes</entry>
+                <entry>An unsigned 32-bit integer in the
+                  message's byte order, indicating the total length in bytes of
+                  the header including named fields and any alignment padding.
+                  MUST be a multiple of 8.
+                </entry>
+              </row>
+              <row>
+                <entry>4 bytes</entry>
+                <entry>An unsigned 32-bit integer in the
+                  message's byte order, indicating the total length in bytes of
+                  the message body.
+                </entry>
+              </row>      
+              <row>
+                <entry>4 bytes</entry>
+                <entry>The message's serial number, a signed 32-bit integer in
+                  the message's byte order. Applications MUST NOT reuse the same
+                  serial number for different messages more often than 32-bit
+                  integer wraparound. Serial numbers must be greater than 
+                  zero.
+                </entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
+      </para>
+      <para>
+        Flags that can appear in the second byte of the header:
+        <informaltable id="message-protocol-header-flags">
+          <tgroup cols=2>
+            <thead>
+              <row>
+                <entry>Hex value</entry>
+                <entry>Description</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry>0x1</entry>
+                <entry>This message is an error reply.</entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
       </para>
     </sect2>
 
           invent their own header fields; only changes to 
           this specification may introduce new header fields.
       </para>
+      
     </sect2>
+    <sect2 id="message-protocol-header-padding">
+      <title>Header Alignment Padding</title>
+      <para>
+        To allow implementations to keep the header and the body in a single
+        buffer while keeping data types aligned, the total length of the header
+        must be a multiple of 8 bytes.  To achieve this, the header MUST be padded
+        with nul bytes to align its total length on an 8-byte boundary. 
+        The minimum number of padding bytes MUST be used. Because all possible 
+        named fields use at least 8 bytes, implementations can distinguish 
+        padding (which must be less than 8 bytes) from additional named fields
+        (which must be at least 8 bytes).
+      </para>
+    </sect2>
+
     <sect2 id="message-protocol-arguments">
       <title>Message Arguments</title>
       <para>