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) {
SILC_PUT16_MSB(len, str + 4);
memcpy(str + 6, service->address, len);
str[6 + len] = service->status;
+ object = str;
+ object_size = 7 + len;
}
break;
SILC_STR_UI16_STRING(geo->altitude),
SILC_STR_UI16_STRING(geo->accuracy),
SILC_STR_END);
+ object = tmpbuf->data;
+ object_size = tmpbuf->len;
}
break;
SILC_STR_UI16_STRING(dev->model),
SILC_STR_UI16_STRING(dev->language),
SILC_STR_END);
+ object = tmpbuf->data;
+ object_size = tmpbuf->len;
}
break;
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;
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;
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)
/* 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;
} 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
*
* 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.
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
*
* 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 */