Added argument list payload parsing.
authorPekka Riikonen <priikone@silcnet.org>
Fri, 24 Nov 2006 14:47:03 +0000 (14:47 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Fri, 24 Nov 2006 14:47:03 +0000 (14:47 +0000)
lib/silccore/silcargument.c
lib/silccore/silcargument.h

index 18446fbe2f9242ca559051b619bddcf5441f64fa..aae2a6ef970ca233148975b61f3600a758fe3d2d 100644 (file)
 #include "silc.h"
 #include "silcargument.h"
 
-/******************************************************************************
-
-                             Argument Payload
-
-******************************************************************************/
+/*************************** Argument Payload *******************************/
 
 struct SilcArgumentPayloadStruct {
   SilcUInt32 argc;
@@ -300,29 +296,22 @@ unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
 
 /* Return argument already decoded */
 
-SilcBool silc_argument_get_decoded(SilcArgumentPayload payload,
-                                  SilcUInt32 type,
-                                  SilcArgumentDecodeType dec_type,
-                                  void *ret_arg,
-                                  void **ret_arg_alloc)
+static SilcBool silc_argument_decode(unsigned char *data,
+                                    SilcUInt32 data_len,
+                                    SilcArgumentDecodeType dec_type,
+                                    void *ret_arg,
+                                    void **ret_arg_alloc)
 {
-  unsigned char *tmp;
-  SilcUInt32 tmp_len;
-
-  tmp = silc_argument_get_arg_type(payload, type, &tmp_len);
-  if (!tmp)
-    return FALSE;
-
   switch (dec_type) {
 
   case SILC_ARGUMENT_ID:
     if (ret_arg)
-      if (!silc_id_payload_parse_id(tmp, tmp_len, (SilcID *)ret_arg))
+      if (!silc_id_payload_parse_id(data, data_len, (SilcID *)ret_arg))
        return FALSE;
 
     if (ret_arg_alloc) {
       SilcID id;
-      if (!silc_id_payload_parse_id(tmp, tmp_len, &id))
+      if (!silc_id_payload_parse_id(data, data_len, &id))
        return FALSE;
       *ret_arg_alloc = silc_memdup(&id, sizeof(id));
     }
@@ -335,7 +324,7 @@ SilcBool silc_argument_get_decoded(SilcArgumentPayload payload,
       if (!ret_arg_alloc)
        return FALSE;
 
-      if (!silc_public_key_payload_decode(tmp, tmp_len, &public_key))
+      if (!silc_public_key_payload_decode(data, data_len, &public_key))
        return FALSE;
 
       *ret_arg_alloc = public_key;
@@ -346,37 +335,37 @@ SilcBool silc_argument_get_decoded(SilcArgumentPayload payload,
     if (!ret_arg_alloc)
       return FALSE;
 
-    *ret_arg_alloc = silc_attribute_payload_parse(tmp, tmp_len);
+    *ret_arg_alloc = silc_attribute_payload_parse(data, data_len);
     break;
 
   case SILC_ARGUMENT_UINT32:
-    if (tmp_len != 4)
+    if (data_len != 4)
       return FALSE;
 
     if (ret_arg) {
       SilcUInt32 *i = ret_arg;
-      SILC_GET32_MSB(*i, tmp);
+      SILC_GET32_MSB(*i, data);
     }
 
     if (ret_arg_alloc) {
       SilcUInt32 i;
-      SILC_GET32_MSB(i, tmp);
+      SILC_GET32_MSB(i, data);
       *ret_arg_alloc = silc_memdup(&i, sizeof(i));
     }
     break;
 
   case SILC_ARGUMENT_BOOL:
-    if (tmp_len != 1)
+    if (data_len != 1)
       return FALSE;
 
     if (ret_arg) {
       SilcBool *b = ret_arg;
-      *b = (tmp[0] == 0x01 ? TRUE : FALSE);
+      *b = (data[0] == 0x01 ? TRUE : FALSE);
     }
 
     if (ret_arg_alloc) {
       SilcBool b;
-      b = (tmp[0] == 0x01 ? TRUE : FALSE);
+      b = (data[0] == 0x01 ? TRUE : FALSE);
       *ret_arg_alloc = silc_memdup(&b, sizeof(b));
     }
     break;
@@ -387,3 +376,122 @@ SilcBool silc_argument_get_decoded(SilcArgumentPayload payload,
 
   return TRUE;
 }
+
+/* Return argument already decoded */
+
+SilcBool silc_argument_get_decoded(SilcArgumentPayload payload,
+                                  SilcUInt32 type,
+                                  SilcArgumentDecodeType dec_type,
+                                  void *ret_arg,
+                                  void **ret_arg_alloc)
+{
+  unsigned char *tmp;
+  SilcUInt32 tmp_len;
+
+  tmp = silc_argument_get_arg_type(payload, type, &tmp_len);
+  if (!tmp)
+    return FALSE;
+
+  return silc_argument_decode(tmp, tmp_len, dec_type, ret_arg, ret_arg_alloc);
+}
+
+/************************* Argument List Payload ****************************/
+
+/* Parses argument payload list */
+
+SilcArgumentPayload
+silc_argument_list_parse(const unsigned char *payload,
+                        SilcUInt32 payload_len)
+{
+  SilcArgumentPayload arg;
+  SilcUInt16 argc;
+
+  if (payload_len < 5)
+    return NULL;
+
+  SILC_GET16_MSB(argc, payload);
+
+  arg = silc_argument_payload_parse(payload + 2, payload_len - 2, argc);
+
+  return arg;
+}
+
+/* Parses argument payload list of specific argument types */
+
+SilcDList
+silc_argument_list_parse_decoded(const unsigned char *payload,
+                                SilcUInt32 payload_len,
+                                SilcArgumentDecodeType dec_type)
+{
+  SilcArgumentPayload arg;
+  SilcArgumentDecodedList dec;
+  unsigned char *data;
+  SilcUInt32 data_len, type;
+  SilcDList list;
+
+  arg = silc_argument_list_parse(payload, payload_len);
+  if (!arg)
+    return NULL;
+
+  list = silc_dlist_init();
+  if (!list) {
+    silc_argument_payload_free(arg);
+    return NULL;
+  }
+
+  data = silc_argument_get_first_arg(arg, &type, &data_len);
+  while (data) {
+    dec = silc_calloc(1, sizeof(*dec));
+    if (!dec)
+      continue;
+    dec->arg_type = type;
+    if (silc_argument_decode(data, data_len, dec_type, NULL, &dec->argument))
+      silc_dlist_add(list, dec);
+    else
+      silc_free(dec);
+    data = silc_argument_get_next_arg(arg, &type, &data_len);
+  }
+
+  silc_argument_payload_free(arg);
+
+  silc_dlist_start(list);
+
+  return list;
+}
+
+/* Free decoded argument payload list */
+
+void silc_argument_list_free(SilcDList list, SilcArgumentDecodeType dec_type)
+{
+  SilcArgumentDecodedList dec;
+
+  if (!list)
+    return;
+
+  silc_dlist_start(list);
+  while ((dec = silc_dlist_get(list))) {
+    switch (dec_type) {
+
+    case SILC_ARGUMENT_ID:
+    case SILC_ARGUMENT_UINT32:
+    case SILC_ARGUMENT_BOOL:
+      silc_free(dec->argument);
+      break;
+
+    case SILC_ARGUMENT_PUBLIC_KEY:
+      silc_pkcs_public_key_free(dec->argument);
+      break;
+
+    case SILC_ARGUMENT_ATTRIBUTES:
+      silc_attribute_payload_free(dec->argument);
+      break;
+
+    default:
+      break;
+    }
+
+    silc_free(dec);
+  }
+
+  silc_dlist_uninit(list);
+}
index 24eb2809f374253325c138c5d3353e5cce269287..cde339f18392ab304133083e012d7c1ead159418 100644 (file)
  *
  * DESCRIPTION
  *
- * Implementation of the Argument Payload, that is used to include
- * argument to other payload that needs arguments.
+ * Implementations of the Argument Payload and Argument List Payload, that
+ * is used to include arguments to other payload that needs arguments.
  *
  ***/
 
-#ifndef SILCPAYLOAD_H
-#define SILCPAYLOAD_H
+#ifndef SILCARGUMENT_H
+#define SILCARGUMENT_H
 
 /****s* silccore/SilcArgumentAPI/SilcArgumentPayload
  *
@@ -277,4 +277,77 @@ SilcBool silc_argument_get_decoded(SilcArgumentPayload payload,
                                   void *ret_arg,
                                   void **ret_arg_alloc);
 
-#endif
+/****f* silccore/SilcArgumentAPI/silc_argument_list_parse
+ *
+ * SYNOPSIS
+ *
+ *    SilcArgumentPayload
+ *    silc_argument_list_parse(const unsigned char *payload,
+ *                             SilcUInt32 payload_len);
+ *
+ * DESCRIPTION
+ *
+ *    Parses argument list payload.  Returns parsed SilcArgumentPayload which
+ *    contains all the arguments from the list.  The caller must free the
+ *    returned context with silc_argument_payload_free.
+ *
+ ***/
+SilcArgumentPayload
+silc_argument_list_parse(const unsigned char *payload, SilcUInt32 payload_len);
+
+/****s* silccore/SilcArgumentAPI/SilcArgumentDecodedList
+ *
+ * NAME
+ *
+ *    typedef struct { ... } *SilcArgumentDecodedList;
+ *
+ * DESCRIPTION
+ *
+ *    This structure is in the list returned by the function
+ *    silc_argument_list_payload_parse_decoded.  The caller is responsible
+ *    of freeing the contents of the structure and the structure itself.
+ *
+ ***/
+typedef struct {
+  void *argument;           /* Decoded argument, caller must know its type */
+  SilcUInt32 arg_type;      /* Argument type from the payload */
+} *SilcArgumentDecodedList;
+
+/****f* silccore/SilcArgumentAPI/silc_argument_list_parse_decoded
+ *
+ * SYNOPSIS
+ *
+ *    SilcDList
+ *    silc_argument_list_parse_decoded(const unsigned char *payload,
+ *                                     SilcUInt32 payload_len,
+ *                                     SilcArgumentDecodeType dec_type);
+ *
+ * DESCRIPTION
+ *
+ *    Parses argument list payload of arguments of the type `dec_type'.
+ *    The returned list includes the already decoded arguments.  The caller
+ *    is responsible of freeing the the contents of the list and the list
+ *    itself.  Each entry in the list is SilcArgumentDecodedList.  The
+ *    caller must free the returned list with silc_argument_list_free.
+ *
+ ***/
+SilcDList
+silc_argument_list_parse_decoded(const unsigned char *payload,
+                                SilcUInt32 payload_len,
+                                SilcArgumentDecodeType dec_type);
+
+/****f* silccore/SilcArgumentAPI/silc_argument_list_free
+ *
+ * SYNOPSIS
+ *
+ *    void
+ *    silc_argument_list_free(SilcDList list, SilcArgumentDecodeType dec_type);
+ *
+ * DESCRIPTION
+ *
+ *    Free's the decoded argument list and its contents.
+ *
+ ***/
+void silc_argument_list_free(SilcDList list, SilcArgumentDecodeType dec_type);
+
+#endif /* SILCARGUMENT_H */