Added silc_attribute_payload_encode_data, renamed parse_list to
authorPekka Riikonen <priikone@silcnet.org>
Wed, 9 Oct 2002 19:00:10 +0000 (19:00 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Wed, 9 Oct 2002 19:00:10 +0000 (19:00 +0000)
parse. Added silc_attribute_payload_alloc as well. Some bugfixes.

lib/silccore/silcattrs.c
lib/silccore/silcattrs.h

index 370d91ef7b6c8165c4739a171a61ebec67ccf097..302c17bebb2e661b45f00f055c62c81467fe2aa3 100644 (file)
@@ -35,62 +35,22 @@ struct SilcAttributePayloadStruct {
   unsigned char *data;
 };
 
-/* Parse one attribute payload */
-
-SilcAttributePayload
-silc_attribute_payload_parse(const unsigned char *payload,
-                            SilcUInt32 payload_len)
+/* Internal routine for encoding a attribute */
+
+static unsigned char *
+silc_attribute_payload_encode_int(SilcAttribute attribute,
+                                 SilcAttributeFlags flags,
+                                 void *object,
+                                 SilcUInt32 object_size,
+                                 SilcUInt32 *ret_len)
 {
-  SilcBufferStruct buffer;
-  SilcAttributePayload newp;
-  int ret;
-
-  SILC_LOG_DEBUG(("Parsing attribute payload"));
-
-  silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
-  newp = silc_calloc(1, sizeof(*newp));
-  if (!newp)
-    return NULL;
-
-  /* Parse the Attribute Payload. */
-  ret = silc_buffer_unformat(&buffer,
-                            SILC_STR_UI_CHAR(&newp->attribute),
-                            SILC_STR_UI_CHAR(&newp->flags),
-                            SILC_STR_UI16_NSTRING_ALLOC(&newp->data, 
-                                                        &newp->data_len),
-                            SILC_STR_END);
-  if (ret == -1)
-    goto err;
-
-  if (newp->data_len > buffer.len - 4) {
-    SILC_LOG_ERROR(("Incorrect attribute payload"));
-    goto err;
-  }
-
-  return newp;
-
- err:
-  silc_attribute_payload_free(newp);
-  return NULL;
-}
-
-/* Encode one attribute payload to buffer */
-
-SilcBuffer silc_attribute_payload_encode(SilcBuffer attrs,
-                                        SilcAttribute attribute,
-                                        SilcAttributeFlags flags,
-                                        void *object,
-                                        SilcUInt32 object_size)
-{
-  SilcBuffer buffer, tmpbuf = NULL;
-  unsigned char tmp[4], *str = NULL;
+  SilcBuffer tmpbuf = NULL;
+  unsigned char tmp[4], *str = NULL, *ret;
   int len;
 
-  SILC_LOG_DEBUG(("Encoding Attribute Payload"));
-
   /* Encode according to attribute type */
   if (flags & SILC_ATTRIBUTE_FLAG_VALID) {
-    if (!object || !object_size)
+    if (!object && !object_size)
       return NULL;
 
     switch (attribute) {
@@ -112,6 +72,8 @@ SilcBuffer silc_attribute_payload_encode(SilcBuffer attrs,
        SILC_PUT16_MSB(len, str + 4);
        memcpy(str + 6, service->address, len);
        str[6 + len] = service->status;
+       object = str;
+       object_size = 7 + len;
       }
       break;
 
@@ -174,6 +136,8 @@ SilcBuffer silc_attribute_payload_encode(SilcBuffer attrs,
                           SILC_STR_UI16_STRING(geo->altitude),
                           SILC_STR_UI16_STRING(geo->accuracy),
                           SILC_STR_END);
+       object = tmpbuf->data;
+       object_size = tmpbuf->len;
       }
       break;
 
@@ -197,6 +161,8 @@ SilcBuffer silc_attribute_payload_encode(SilcBuffer attrs,
                           SILC_STR_UI16_STRING(dev->model),
                           SILC_STR_UI16_STRING(dev->language),
                           SILC_STR_END);
+       object = tmpbuf->data;
+       object_size = tmpbuf->len;
       }
       break;
 
@@ -215,6 +181,8 @@ SilcBuffer silc_attribute_payload_encode(SilcBuffer attrs,
                           SILC_STR_UI16_STRING(pk->type),
                           SILC_STR_UI_XNSTRING(pk->data, pk->data_len),
                           SILC_STR_END);
+       object = tmpbuf->data;
+       object_size = tmpbuf->len;
       }
       break;
 
@@ -233,41 +201,53 @@ SilcBuffer silc_attribute_payload_encode(SilcBuffer attrs,
       return NULL;
       break;
     }
-  }
 
-  buffer = attrs;
-  len = 4 + object_size;
+    ret = silc_memdup(object, object_size);
+
+    if (tmpbuf)
+      silc_buffer_free(tmpbuf);
+    silc_free(str);
 
-  if (!buffer) {
-    buffer = silc_buffer_alloc_size(len);
-  } else {
-    buffer = silc_buffer_realloc(buffer,
-                                (buffer ? buffer->truelen + len : len));
-    silc_buffer_pull_tail(buffer, (buffer->end - buffer->data));
+    if (ret_len)
+      *ret_len = object_size;
+
+    return ret;
   }
 
-  silc_buffer_format(buffer, 
-                    SILC_STR_UI_CHAR(attribute),
-                    SILC_STR_UI_CHAR(flags),
-                    SILC_STR_UI_SHORT((SilcUInt16)object_size),
-                    SILC_STR_UI_XNSTRING(object, object_size),
-                    SILC_STR_END);
+  return NULL;
+}
 
-  silc_buffer_pull(buffer, len);
-  if (buffer)
-    silc_buffer_push(buffer, buffer->data - buffer->head);
+/* Allocates attribute payload and encodes the attribute there */
 
-  if (tmpbuf)
-    silc_buffer_free(tmpbuf);
-  silc_free(str);
+SilcAttributePayload silc_attribute_payload_alloc(SilcAttribute attribute,
+                                                 SilcAttributeFlags flags,
+                                                 void *object,
+                                                 SilcUInt32 object_size)
+{
+  SilcAttributePayload attr;
 
-  return buffer;
+  attr = silc_calloc(1, sizeof(*attr));
+  if (!attr)
+    return NULL;
+
+  attr->attribute = attribute;
+  attr->flags = flags;
+  attr->data =
+    silc_attribute_payload_encode_int(attribute, flags, object,
+                                     object_size,
+                                     (SilcUInt32 *)&attr->data_len);
+  if (!attr->data) {
+    silc_free(attr);
+    return NULL;
+  }
+
+  return attr;
 }
 
 /* Parse list of payloads */
 
-SilcDList silc_attribute_payload_parse_list(const unsigned char *payload,
-                                           SilcUInt32 payload_len)
+SilcDList silc_attribute_payload_parse(const unsigned char *payload,
+                                      SilcUInt32 payload_len)
 {
   SilcBufferStruct buffer;
   SilcDList list;
@@ -312,6 +292,53 @@ SilcDList silc_attribute_payload_parse_list(const unsigned char *payload,
   return NULL;
 }
 
+/* Encode one attribute payload to buffer */
+
+SilcBuffer silc_attribute_payload_encode(SilcBuffer attrs,
+                                        SilcAttribute attribute,
+                                        SilcAttributeFlags flags,
+                                        void *object,
+                                        SilcUInt32 object_size)
+{
+  object = silc_attribute_payload_encode_int(attribute, flags, object,
+                                            object_size, &object_size);
+  attrs = silc_attribute_payload_encode_data(attrs, attribute, flags,
+                                            (const unsigned char *)object,
+                                            object_size);
+  silc_free(object);
+  return attrs;
+}
+
+/* Encoded the attribute data directly to buffer */
+
+SilcBuffer silc_attribute_payload_encode_data(SilcBuffer attrs,
+                                             SilcAttribute attribute,
+                                             SilcAttributeFlags flags,
+                                             const unsigned char *data,
+                                             SilcUInt32 data_len)
+{
+  SilcBuffer buffer = attrs;
+  int len;
+
+  len = 4 + data_len;
+  buffer = silc_buffer_realloc(buffer,
+                              (buffer ? buffer->truelen + len : len));
+  if (!buffer)
+    return NULL;
+  silc_buffer_pull(buffer, buffer->len);
+  silc_buffer_pull_tail(buffer, len);
+  silc_buffer_format(buffer, 
+                    SILC_STR_UI_CHAR(attribute),
+                    SILC_STR_UI_CHAR(flags),
+                    SILC_STR_UI_SHORT((SilcUInt16)data_len),
+                    SILC_STR_UI_XNSTRING(data, data_len),
+                    SILC_STR_END);
+  if (buffer)
+    silc_buffer_push(buffer, buffer->data - buffer->head);
+
+  return buffer;
+}
+
 /* Free Attribute Payload */
 
 void silc_attribute_payload_free(SilcAttributePayload payload)
@@ -362,17 +389,15 @@ const unsigned char *silc_attribute_get_data(SilcAttributePayload payload,
 /* Return parsed attribute object */
 
 bool silc_attribute_get_object(SilcAttributePayload payload,
-                              SilcAttribute attribute,
                               void **object, SilcUInt32 object_size)
 {
   SilcUInt16 len;
   bool ret = FALSE;
 
-  if (!attribute || payload->attribute != attribute || !object || !(*object) ||
-      payload->flags & SILC_ATTRIBUTE_FLAG_INVALID)
+  if (!object || !(*object) ||  payload->flags & SILC_ATTRIBUTE_FLAG_INVALID)
     return FALSE;
 
-  switch (attribute) {
+  switch (payload->attribute) {
   case SILC_ATTRIBUTE_USER_INFO:
     SILC_NOT_IMPLEMENTED("SILC_ATTRIBUTE_USER_INFO");
     break;
index dd924708260c90b2610583e562bd73606336f393..deb8a026b898a8738a0daa2b6a09a442424ac7a6 100644 (file)
@@ -177,23 +177,48 @@ typedef enum {
 } SilcAttributeDevice;
 /***/
 
+/****f* silccore/SilcAttributesAPI/silc_attribute_payload_alloc
+ *
+ * SYNOPSIS
+ *
+ *    SilcAttributesPayload
+ *    silc_attribute_payload_alloc(SilcAttribute attribute,
+ *                                 SilcAttributeFlags flags,
+ *                                 void *object,
+ *                                 SilcUInt32 object_size);
+ *
+ * DESCRIPTION
+ *
+ *    Allocates and encodes the attribute indicated by `attribute' and
+ *    returns pointer to the attribute.
+ *
+ *    The `object' must always be the same data type as defined with
+ *    SilcAttribute (see the comments) for all attributes.
+ *
+ ***/
+SilcAttributePayload silc_attribute_payload_alloc(SilcAttribute attribute,
+                                                 SilcAttributeFlags flags,
+                                                 void *object,
+                                                 SilcUInt32 object_size);
+
 /****f* silccore/SilcAttributesAPI/silc_attribute_payload_parse
  *
  * SYNOPSIS
  *
- *    SilcAttributePayload
+ *    SilcDList
  *    silc_attribute_payload_parse(const unsigned char *payload,
  *                                 SilcUInt32 payload_len);
  *
  * DESCRIPTION
  *
- *    Parses one attribute payload sent as argument and saves it to
- *    SilcAttributePayload context.  The new allocated context is returned.
+ *    Parses list of Attribute payloads returning list of payloads.
+ *    One entry in the returned list is SilcAttributesPayload.  You
+ *    can produce such a list with silc_attribute_payload_encode
+ *    function.
  *
  ***/
-SilcAttributePayload
-silc_attribute_payload_parse(const unsigned char *payload,
-                            SilcUInt32 payload_len);
+SilcDList silc_attribute_payload_parse(const unsigned char *payload,
+                                      SilcUInt32 payload_len);
 
 /****f* silccore/SilcAttributesAPI/silc_attribute_payload_encode
  *
@@ -212,7 +237,8 @@ silc_attribute_payload_parse(const unsigned char *payload,
  *    was reallocated.  If `attrs' is NULL for first attribute this
  *    allocates the buffer and returns it.  This can be called multiple
  *    times to add multiple attributes to the `attrs' buffer.  The `flags'
- *    indicates the validity of the added attribute.
+ *    indicates the validity of the added attribute.  Returns NULL on
+ *    error.
  *
  *    The `object' must always be the same data type as defined with
  *    SilcAttribute (see the comments) for all attributes.
@@ -224,25 +250,32 @@ SilcBuffer silc_attribute_payload_encode(SilcBuffer attrs,
                                         void *object,
                                         SilcUInt32 object_size);
 
-/****f* silccore/SilcAttributesAPI/silc_attribute_payload_parse_list
+/****f* silccore/SilcAttributesAPI/silc_attribute_payload_encode_data
  *
  * SYNOPSIS
  *
- *    SilcDList
- *    silc_attribute_payload_parse_list(const unsigned char *payload,
- *                                      SilcUInt32 payload_len);
+ *    SilcBuffer
+ *    silc_attribute_payload_encode_data(SilcBuffer attrs,
+ *                                       SilcAttribute attribute,
+ *                                       SilcAttributeFlags flags,
+ *                                       const unsigned char *data,
+ *                                       SilcUInt32 data_len);
  *
  * DESCRIPTION
  *
- *    Parses list of Attribute payloads returning list of payloads. This
- *    is equivalent to the silc_attribute_payload_parse except that the
- *    `buffer' now includes multiple Attribute Payloads one after the other.
- *    You can produce such a list with silc_attribute_payload_encode
- *    function.
+ *    Same function as silc_attribute_payload_encode except the attribute
+ *    is already encoded into `data' of `data_len' bytes in length.
+ *    Encodes the attribute into the `attrs' buffer and returns pointer
+ *    to the buffer, which may be different in case the buffer was
+ *    reallocated.  If `attrs' is NULL for first attribute this allocates
+ *    the buffer and returns it.  Returns NULL on error.
  *
  ***/
-SilcDList silc_attribute_payload_parse_list(const unsigned char *payload,
-                                           SilcUInt32 payload_len);
+SilcBuffer silc_attribute_payload_encode_data(SilcBuffer attrs,
+                                             SilcAttribute attribute,
+                                             SilcAttributeFlags flags,
+                                             const unsigned char *data,
+                                             SilcUInt32 data_len);
 
 /****f* silccore/SilcAttributesAPI/silc_attribute_payload_free
  *
@@ -424,24 +457,24 @@ typedef struct {
  * SYNOPSIS
  *
  *    bool silc_attribute_get_object(SilcAttributePayload payload,
- *                                   SilcAttribute attribute,
  *                                   void **object,
  *                                   SilcUInt32 object_size);
  *
  * DESCRIPTION
  *
- *    Returns the already parsed attribute object by the attribute type
- *    indicated by `attribute'.  Copies the data into the `object' which
+ *    Returns the already parsed attribute object from the payload
+ *    indicated by `payload'.  Copies the data into the `object' which
  *    must be sent as argument (and must be of correct type and size).
  *    The `object_size' indicates the size of the `*object' sent.
  *    Returns TRUE if the `attribute' attribute was found and FALSE
  *    if such attribute is not present in the `payload', or the `object_size'
  *    is not sufficient.  See the definition of SilcAttribute for the
  *    list of attributes and the required object types for attributes.
+ *    You can use silc_attribute_get_attribute to get the SilcAttribute
+ *    type from the `payload'.
  *
  ***/
 bool silc_attribute_get_object(SilcAttributePayload payload,
-                              SilcAttribute attribute,
                               void **object, SilcUInt32 object_size);
 
 #endif /* SILCATTRS_H */