Changed command payload to use new generic payloads.
Changed channel payload to protocol compliant.
silccommand.c \
silcpacket.c \
silcprotocol.c \
- silcsockconn.c
+ silcsockconn.c \
+ silcpayload.c \
+ silcnotify.c
EXTRA_DIST = *.h
GNU General Public License for more details.
*/
-/*
- * $Id$
- * $Log$
- * Revision 1.2 2000/07/05 06:06:35 priikone
- * Global cosmetic change.
- *
- * Revision 1.1.1.1 2000/06/27 11:36:55 priikone
- * Imported from internal CVS/Added Log headers.
- *
- *
- */
+/* Channel Payload and Channel Key Payload implementations. */
+/* $Id$ */
#include "silcincludes.h"
#include "silcchannel.h"
+/******************************************************************************
+
+ Channel Payload
+
+******************************************************************************/
+
/* Channel Payload structure. Contents of this structure is parsed
from SILC packets. */
struct SilcChannelPayloadStruct {
- unsigned short nick_len;
- unsigned char *nick;
unsigned short data_len;
unsigned char *data;
unsigned short iv_len;
unsigned char *iv;
};
-/* Channel Key Payload structrue. Channel keys are parsed from SILC
- packets into this structure. */
-struct SilcChannelKeyPayloadStruct {
- unsigned short id_len;
- unsigned char *id;
- unsigned short cipher_len;
- unsigned char *cipher;
- unsigned short key_len;
- unsigned char *key;
-};
-
/* Parses channel payload returning new channel payload structure */
-SilcChannelPayload silc_channel_parse_payload(SilcBuffer buffer)
+SilcChannelPayload silc_channel_payload_parse(SilcBuffer buffer)
{
SilcChannelPayload new;
/* Parse the Channel Payload. Ignore padding and IV, we don't need
them. */
silc_buffer_unformat(buffer,
- SILC_STR_UI16_NSTRING_ALLOC(&new->nick, &new->nick_len),
SILC_STR_UI16_NSTRING_ALLOC(&new->data, &new->data_len),
SILC_STR_UI16_NSTRING_ALLOC(NULL, NULL),
SILC_STR_END);
- if (new->data_len < 1) {
+ if (new->data_len < 1 || new->data_len > buffer->len) {
SILC_LOG_ERROR(("Incorrect channel payload in packet, packet dropped"));
goto err;
}
return new;
err:
- if (new->nick)
- silc_free(new->nick);
if (new->data)
silc_free(new->data);
if (new->iv)
encrypted separately from other parts of the packet padding must
be applied to the payload. */
-SilcBuffer silc_channel_encode_payload(unsigned short nick_len,
- unsigned char *nick,
- unsigned short data_len,
+SilcBuffer silc_channel_payload_encode(unsigned short data_len,
unsigned char *data,
unsigned short iv_len,
unsigned char *iv,
/* Calculate length of padding. IV is not included into the calculation
since it is not encrypted. */
- len = 2 + nick_len + 2 + data_len + 2;
+ len = 2 + data_len + 2;
pad_len = SILC_PACKET_PADLEN((len + 2));
/* Allocate channel payload buffer */
/* Encode the Channel Payload */
silc_buffer_format(buffer,
- SILC_STR_UI_SHORT(nick_len),
- SILC_STR_UI_XNSTRING(nick, nick_len),
SILC_STR_UI_SHORT(data_len),
SILC_STR_UI_XNSTRING(data, data_len),
SILC_STR_UI_SHORT(pad_len),
/* Free's Channel Payload */
-void silc_channel_free_payload(SilcChannelPayload payload)
+void silc_channel_payload_free(SilcChannelPayload payload)
{
if (payload) {
if (payload->data)
}
}
-/* Return nickname */
-
-unsigned char *silc_channel_get_nickname(SilcChannelPayload payload,
- unsigned int *nick_len)
-{
- if (nick_len)
- *nick_len = payload->nick_len;
-
- return payload->nick;
-}
-
/* Return data */
unsigned char *silc_channel_get_data(SilcChannelPayload payload,
return payload->iv;
}
+/******************************************************************************
+
+ Channel Key Payload
+
+******************************************************************************/
+
+/* Channel Key Payload structrue. Channel keys are parsed from SILC
+ packets into this structure. */
+struct SilcChannelKeyPayloadStruct {
+ unsigned short id_len;
+ unsigned char *id;
+ unsigned short cipher_len;
+ unsigned char *cipher;
+ unsigned short key_len;
+ unsigned char *key;
+};
+
/* Parses channel key payload returning new channel key payload structure */
-SilcChannelKeyPayload silc_channel_key_parse_payload(SilcBuffer buffer)
+SilcChannelKeyPayload silc_channel_key_payload_parse(SilcBuffer buffer)
{
SilcChannelKeyPayload new;
/* Encodes channel key payload into a buffer and returns it. This is used
to add channel key payload into a packet. */
-SilcBuffer silc_channel_key_encode_payload(unsigned short id_len,
+SilcBuffer silc_channel_key_payload_encode(unsigned short id_len,
unsigned char *id,
unsigned short cipher_len,
unsigned char *cipher,
/* Free's Channel Key Payload */
-void silc_channel_key_free_payload(SilcChannelKeyPayload payload)
+void silc_channel_key_payload_free(SilcChannelKeyPayload payload)
{
if (payload) {
if (payload->id)
#define SILC_CHANNEL_UMODE_CHANOP 0x0002 /* channel operator */
/* Prototypes */
-SilcChannelPayload silc_channel_parse_payload(SilcBuffer buffer);
-SilcBuffer silc_channel_encode_payload(unsigned short nick_len,
- unsigned char *nick,
- unsigned short data_len,
+SilcChannelPayload silc_channel_payload_parse(SilcBuffer buffer);
+SilcBuffer silc_channel_payload_encode(unsigned short data_len,
unsigned char *data,
unsigned short iv_len,
unsigned char *iv,
SilcRng rng);
-void silc_channel_free_payload(SilcChannelPayload payload);
-unsigned char *silc_channel_get_nickname(SilcChannelPayload payload,
- unsigned int *nick_len);
+void silc_channel_payload_free(SilcChannelPayload payload);
unsigned char *silc_channel_get_data(SilcChannelPayload payload,
unsigned int *data_len);
unsigned char *silc_channel_get_iv(SilcChannelPayload payload,
unsigned int *iv_len);
-SilcChannelKeyPayload silc_channel_key_parse_payload(SilcBuffer buffer);
-SilcBuffer silc_channel_key_encode_payload(unsigned short id_len,
+SilcChannelKeyPayload silc_channel_key_payload_parse(SilcBuffer buffer);
+SilcBuffer silc_channel_key_payload_encode(unsigned short id_len,
unsigned char *id,
unsigned short cipher_len,
unsigned char *cipher,
unsigned short key_len,
unsigned char *key);
-void silc_channel_key_free_payload(SilcChannelKeyPayload payload);
+void silc_channel_key_payload_free(SilcChannelKeyPayload payload);
unsigned char *silc_channel_key_get_id(SilcChannelKeyPayload payload,
unsigned int *id_len);
unsigned char *silc_channel_key_get_cipher(SilcChannelKeyPayload payload,
GNU General Public License for more details.
*/
-/*
- * $Id$
- * $Log$
- * Revision 1.3 2000/07/06 07:11:06 priikone
- * Removed status paylaod encoding functions -> not needed anymore.
- * Added encode_reply_payload_va to encode reply packets only.
- * Normal encode_payload_va accepts now argument type as variable
- * argument as well.
- *
- * Revision 1.2 2000/07/05 06:06:35 priikone
- * Global cosmetic change.
- *
- * Revision 1.1.1.1 2000/06/27 11:36:55 priikone
- * Imported from internal CVS/Added Log headers.
- *
- *
- */
+/* $Id$ */
#include "silcincludes.h"
#include "silccommand.h"
+/******************************************************************************
+
+ Command Payload
+
+******************************************************************************/
+
/* Command Payload structure. Contents of this structure is parsed
from SILC packets. */
struct SilcCommandPayloadStruct {
SilcCommand cmd;
- unsigned int argc;
- unsigned char **argv;
- unsigned int *argv_lens;
- unsigned int *argv_types;
- unsigned int pos;
+ unsigned short ident;
+ SilcArgumentPayload args;
};
/* Length of the command payload */
-#define SILC_COMMAND_PAYLOAD_LEN 4
+#define SILC_COMMAND_PAYLOAD_LEN 6
/* Parses command payload returning new command payload structure */
-SilcCommandPayload silc_command_parse_payload(SilcBuffer buffer)
+SilcCommandPayload silc_command_payload_parse(SilcBuffer buffer)
{
SilcCommandPayload new;
- unsigned short payload_len = 0;
- unsigned char args_num = 0;
- unsigned char arg_num = 0;
- unsigned int arg_type = 0;
- unsigned int pull_len = 0;
- int i = 0;
+ unsigned char args_num;
+ unsigned short payload_len;
SILC_LOG_DEBUG(("Parsing command payload"));
/* Parse the Command Payload */
silc_buffer_unformat(buffer,
+ SILC_STR_UI_SHORT(&payload_len),
SILC_STR_UI_CHAR(&new->cmd),
SILC_STR_UI_CHAR(&args_num),
- SILC_STR_UI_SHORT(&payload_len),
+ SILC_STR_UI_SHORT(&new->ident),
SILC_STR_END);
if (payload_len != buffer->len) {
SILC_LOG_ERROR(("Incorrect command payload in packet, packet dropped"));
+ silc_free(new);
return NULL;
}
- if (new->cmd == 0)
+ if (new->cmd == 0) {
+ silc_free(new);
return NULL;
-
- if (args_num && payload_len) {
-
- new->argv = silc_calloc(args_num, sizeof(unsigned char *));
- new->argv_lens = silc_calloc(args_num, sizeof(unsigned int));
- new->argv_types = silc_calloc(args_num, sizeof(unsigned int));
-
- silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
- pull_len += SILC_COMMAND_PAYLOAD_LEN;
-
- /* Parse Command Argument Payloads */
- arg_num = 1;
- while(arg_num) {
- silc_buffer_unformat(buffer,
- SILC_STR_UI_CHAR(&arg_num),
- SILC_STR_UI_CHAR(&arg_type),
- SILC_STR_UI_SHORT(&payload_len),
- SILC_STR_END);
-
- /* Check that argument number is correct */
- if (arg_num != i + 1)
- goto err;
-
- new->argv_lens[i] = payload_len;
- new->argv_types[i] = arg_type;
-
- /* Get argument data */
- silc_buffer_pull(buffer, 4);
- silc_buffer_unformat(buffer,
- SILC_STR_UI_XNSTRING_ALLOC(&new->argv[i],
- payload_len),
- SILC_STR_END);
- silc_buffer_pull(buffer, payload_len);
- pull_len += 4 + payload_len;
-
- i++;
-
- if (i == args_num)
- break;
- }
-
- /* Check the number of arguments */
- if (arg_num != args_num)
- goto err;
}
- new->argc = i;
- new->pos = 0;
-
- silc_buffer_push(buffer, pull_len);
-
- return new;
-
- err:
- if (i) {
- int k;
-
- for (k = 0; k < i; k++)
- silc_free(new->argv[k]);
- }
-
- silc_free(new->argv);
- silc_free(new->argv_lens);
- silc_free(new->argv_types);
-
- if (new)
+ silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
+ new->args = silc_argument_payload_parse(buffer, args_num);
+ if (!new->args) {
silc_free(new);
+ return NULL;
+ }
+ silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN);
- return NULL;
+ return new;
}
/* Encodes Command Payload returning it to SilcBuffer. */
-SilcBuffer silc_command_encode_payload(SilcCommand cmd,
+SilcBuffer silc_command_payload_encode(SilcCommand cmd,
unsigned int argc,
unsigned char **argv,
unsigned int *argv_lens,
- unsigned int *argv_types)
+ unsigned int *argv_types,
+ unsigned short ident)
{
SilcBuffer buffer;
- unsigned int len;
- int i;
+ SilcBuffer args = NULL;
+ unsigned int len = 0;
SILC_LOG_DEBUG(("Encoding command payload"));
- len = 1 + 1 + 2;
- for (i = 0; i < argc; i++)
- len += 1 + 1 + 2 + argv_lens[i];
+ if (argc) {
+ args = silc_argument_payload_encode(argc, argv, argv_lens, argv_types);
+ len = args->len;
+ }
+ len += SILC_COMMAND_PAYLOAD_LEN;
buffer = silc_buffer_alloc(len);
silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
/* Create Command payload */
silc_buffer_format(buffer,
+ SILC_STR_UI_SHORT(len),
SILC_STR_UI_CHAR(cmd),
SILC_STR_UI_CHAR(argc),
- SILC_STR_UI_SHORT(len),
+ SILC_STR_UI_SHORT(ident),
SILC_STR_END);
- /* Put arguments */
+ /* Add arguments */
if (argc) {
- silc_buffer_pull(buffer, 4);
-
- for (i = 0; i < argc; i++) {
- silc_buffer_format(buffer,
- SILC_STR_UI_CHAR(i + 1),
- SILC_STR_UI_CHAR(argv_types[i]),
- SILC_STR_UI_SHORT(argv_lens[i]),
- SILC_STR_UI_XNSTRING(argv[i], argv_lens[i]),
- SILC_STR_END);
- silc_buffer_pull(buffer, 4 + argv_lens[i]);
- }
-
- silc_buffer_push(buffer, len);
+ silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
+ silc_buffer_format(buffer,
+ SILC_STR_UI_XNSTRING(args->data, args->len),
+ SILC_STR_END);
+ silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN);
+ silc_free(args);
}
return buffer;
equals two (2), and so on. This has to be preserved or bad things
will happen. The variable arguments is: {type, data, data_len}. */
-SilcBuffer silc_command_encode_payload_va(SilcCommand cmd,
+SilcBuffer silc_command_payload_encode_va(SilcCommand cmd,
+ unsigned short ident,
unsigned int argc, ...)
{
va_list ap;
argv_types[i] = x_type;
}
- buffer = silc_command_encode_payload(cmd, argc, argv,
- argv_lens, argv_types);
+ buffer = silc_command_payload_encode(cmd, argc, argv,
+ argv_lens, argv_types, ident);
for (i = 0; i < argc; i++)
silc_free(argv[i]);
as on argument. */
SilcBuffer
-silc_command_encode_reply_payload_va(SilcCommand cmd,
+silc_command_reply_payload_encode_va(SilcCommand cmd,
SilcCommandStatus status,
+ unsigned short ident,
unsigned int argc, ...)
{
va_list ap;
argv_types[i] = x_type;
}
- buffer = silc_command_encode_payload(cmd, argc, argv,
- argv_lens, argv_types);
+ buffer = silc_command_payload_encode(cmd, argc, argv,
+ argv_lens, argv_types, ident);
for (i = 0; i < argc; i++)
silc_free(argv[i]);
void silc_command_free_payload(SilcCommandPayload payload)
{
- int i;
-
if (payload) {
- for (i = 0; i < payload->argc; i++)
- silc_free(payload->argv[i]);
-
- silc_free(payload->argv);
+ silc_argument_payload_free(payload->args);
silc_free(payload);
}
}
-/* Returns the command type in payload */
+/* Returns command */
SilcCommand silc_command_get(SilcCommandPayload payload)
{
return payload->cmd;
}
-/* Returns number of arguments in payload */
+/* Retuns arguments payload */
-unsigned int silc_command_get_arg_num(SilcCommandPayload payload)
+SilcArgumentPayload silc_command_get_args(SilcCommandPayload payload)
{
- return payload->argc;
-}
-
-/* Returns first argument from payload. */
-
-unsigned char *silc_command_get_first_arg(SilcCommandPayload payload,
- unsigned int *ret_len)
-{
- payload->pos = 0;
-
- if (ret_len)
- *ret_len = payload->argv_lens[payload->pos];
-
- return payload->argv[payload->pos++];
+ return payload->args;
}
-/* Returns next argument from payload or NULL if no more arguments. */
+/* Returns identifier */
-unsigned char *silc_command_get_next_arg(SilcCommandPayload payload,
- unsigned int *ret_len)
+unsigned short silc_command_get_ident(SilcCommandPayload payload)
{
- if (payload->pos >= payload->argc)
- return NULL;
-
- if (ret_len)
- *ret_len = payload->argv_lens[payload->pos];
-
- return payload->argv[payload->pos++];
-}
-
-/* Returns argument which type is `type'. */
-
-unsigned char *silc_command_get_arg_type(SilcCommandPayload payload,
- unsigned int type,
- unsigned int *ret_len)
-{
- int i;
-
- for (i = 0; i < payload->argc; i++)
- if (payload->argv_types[i] == type)
- break;
-
- if (i >= payload->argc)
- return NULL;
-
- if (ret_len)
- *ret_len = payload->argv_lens[i];
-
- return payload->argv[i];
+ return payload->ident;
}
#define SILC_STATUS_ERR_AUTH_FAILED 43
/* Prototypes */
-SilcCommandPayload silc_command_parse_payload(SilcBuffer buffer);
-SilcBuffer silc_command_encode_payload(SilcCommand cmd,
+SilcCommandPayload silc_command_payload_parse(SilcBuffer buffer);
+SilcBuffer silc_command_payload_encode(SilcCommand cmd,
unsigned int argc,
unsigned char **argv,
unsigned int *argv_lens,
- unsigned int *argv_types);
-SilcBuffer silc_command_encode_payload_va(SilcCommand cmd,
+ unsigned int *argv_types,
+ unsigned short ident);
+SilcBuffer silc_command_payload_encode_va(SilcCommand cmd,
+ unsigned short ident,
unsigned int argc, ...);
SilcBuffer
-silc_command_encode_reply_payload_va(SilcCommand cmd,
+silc_command_reply_payload_encode_va(SilcCommand cmd,
SilcCommandStatus status,
+ unsigned short ident,
unsigned int argc, ...);
void silc_command_free_payload(SilcCommandPayload payload);
SilcCommand silc_command_get(SilcCommandPayload payload);
-unsigned int silc_command_get_arg_num(SilcCommandPayload payload);
-unsigned char *silc_command_get_first_arg(SilcCommandPayload payload,
- unsigned int *ret_len);
-unsigned char *silc_command_get_next_arg(SilcCommandPayload payload,
- unsigned int *ret_len);
-unsigned char *silc_command_get_arg_type(SilcCommandPayload payload,
- unsigned int type,
- unsigned int *ret_len);
+SilcArgumentPayload silc_command_get_args(SilcCommandPayload payload);
+unsigned short silc_command_get_ident(SilcCommandPayload payload);
#endif
#ifndef SILCNOTIFY_H
#define SILCNOTIFY_H
+/* Forward declarations */
+typedef struct SilcNotifyPayloadStruct *SilcNotifyPayload;
+
/* Type definition of notify type */
typedef unsigned short SilcNotifyType;
#define SILC_NOTIFY_TYPE_TOPIC_SET 5 /* "topic has been changed" */
#define SILC_NOTIFY_TYPE_NICK_CHANGE 6 /* "has changed nickname" */
+/* Prototypes */
+SilcNotifyPayload silc_notify_payload_parse(SilcBuffer buffer);
+SilcBuffer silc_notify_payload_encode(SilcNotifyType type, char *message,
+ unsigned int argc, va_list ap);
+void silc_notify_payload_free(SilcNotifyPayload payload);
+SilcNotifyType silc_notify_get_type(SilcNotifyPayload payload);
+unsigned int silc_notify_get_arg_num(SilcNotifyPayload payload);
+unsigned char *silc_notify_get_message(SilcNotifyPayload payload);
+SilcArgumentPayload silc_notify_get_args(SilcNotifyPayload payload);
+
#endif
--- /dev/null
+/*
+
+ silcpayload.c
+
+ Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ Copyright (C) 2000 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+/* Implementation of generic payloads described in the protocol
+ specification drafts. */
+/* $Id$ */
+
+#include "silcincludes.h"
+#include "silcpayload.h"
+
+/******************************************************************************
+
+ ID Payload
+
+******************************************************************************/
+
+struct SilcIDPayloadStruct {
+ SilcIdType type;
+ unsigned short len;
+ unsigned char *id;
+};
+
+/* Parses data and return ID payload into payload structure */
+
+SilcIDPayload silc_id_payload_parse(SilcBuffer buffer)
+{
+ SilcIDPayload new;
+
+ SILC_LOG_DEBUG(("Parsing ID payload"));
+
+ new = silc_calloc(1, sizeof(*new));
+
+ silc_buffer_unformat(buffer,
+ SILC_STR_UI_SHORT(&new->type),
+ SILC_STR_UI_SHORT(&new->len),
+ SILC_STR_END);
+
+ if (new->len > buffer->len)
+ goto err;
+
+ silc_buffer_pull(buffer, 4);
+ silc_buffer_unformat(buffer,
+ SILC_STR_UI_XNSTRING_ALLOC(&new->id, new->len),
+ SILC_STR_END);
+ silc_buffer_push(buffer, 4);
+
+ return new;
+
+ err:
+ silc_free(new);
+ return NULL;
+}
+
+/* Encodes ID Payload */
+
+SilcBuffer silc_id_payload_encode(void *id, unsigned short len,
+ SilcIdType type)
+{
+ SilcBuffer buffer;
+ unsigned char *id_data;
+
+ SILC_LOG_DEBUG(("Parsing ID payload"));
+
+ id_data = silc_id_id2str(id, type);
+
+ buffer = silc_buffer_alloc(4 + len);
+ silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
+ silc_buffer_format(buffer,
+ SILC_STR_UI_SHORT(type),
+ SILC_STR_UI_SHORT(len),
+ SILC_STR_UI_XNSTRING(id_data, len),
+ SILC_STR_END);
+ silc_free(id_data);
+
+ return buffer;
+}
+
+/* Free ID Payload */
+
+void silc_id_payload_free(SilcIDPayload payload)
+{
+ if (payload) {
+ silc_free(payload->id);
+ }
+}
+
+/* Get ID type */
+
+SilcIdType silc_id_payload_get_type(SilcIDPayload payload)
+{
+ return payload->type;
+}
+
+/* Get ID */
+
+void *silc_id_payload_get_id(SilcIDPayload payload)
+{
+ return silc_id_str2id(payload->id, payload->type);
+}
+
+/******************************************************************************
+
+ Argument Payload
+
+******************************************************************************/
+
+struct SilcArgumentPayloadStruct {
+ unsigned int argc;
+ unsigned char **argv;
+ unsigned int *argv_lens;
+ unsigned int *argv_types;
+ unsigned int pos;
+};
+
+/* Parses arguments and returns them into Argument Payload structure. */
+
+SilcArgumentPayload silc_argument_payload_parse(SilcBuffer buffer,
+ unsigned int argc)
+{
+ SilcArgumentPayload new;
+ unsigned short payload_len = 0;
+ unsigned char arg_num = 0;
+ unsigned int arg_type = 0;
+ unsigned int pull_len = 0;
+ int i = 0;
+
+ SILC_LOG_DEBUG(("Parsing argument payload"));
+
+ new = silc_calloc(1, sizeof(*new));
+ new->argv = silc_calloc(argc, sizeof(unsigned char *));
+ new->argv_lens = silc_calloc(argc, sizeof(unsigned int));
+ new->argv_types = silc_calloc(argc, sizeof(unsigned int));
+
+ /* Get arguments */
+ arg_num = 1;
+ for (i = 0; i < argc; i++) {
+ silc_buffer_unformat(buffer,
+ SILC_STR_UI_SHORT(&payload_len),
+ SILC_STR_UI_CHAR(&arg_type),
+ SILC_STR_END);
+
+ new->argv_lens[i] = payload_len;
+ new->argv_types[i] = arg_type;
+
+ if (payload_len > buffer->len)
+ break;
+
+ /* Get argument data */
+ silc_buffer_pull(buffer, 3);
+ silc_buffer_unformat(buffer,
+ SILC_STR_UI_XNSTRING_ALLOC(&new->argv[i],
+ payload_len),
+ SILC_STR_END);
+
+ silc_buffer_pull(buffer, payload_len);
+ pull_len += 3 + payload_len;
+ }
+
+ if (buffer->len != 0)
+ goto err;
+
+ new->argc = argc;
+ new->pos = 0;
+
+ silc_buffer_push(buffer, pull_len);
+
+ return new;
+
+ err:
+ if (i) {
+ int k;
+
+ for (k = 0; k < i; k++)
+ silc_free(new->argv[k]);
+ }
+
+ silc_free(new->argv);
+ silc_free(new->argv_lens);
+ silc_free(new->argv_types);
+
+ if (new)
+ silc_free(new);
+
+ return NULL;
+}
+
+/* Encodes arguments in to Argument Paylods returning them to SilcBuffer. */
+
+SilcBuffer silc_argument_payload_encode(unsigned int argc,
+ unsigned char **argv,
+ unsigned int *argv_lens,
+ unsigned int *argv_types)
+{
+ SilcBuffer buffer;
+ unsigned int len;
+ int i;
+
+ SILC_LOG_DEBUG(("Encoding Argument payload"));
+
+ len = 0;
+ for (i = 0; i < argc; i++)
+ len += 3 + argv_lens[i];
+
+ buffer = silc_buffer_alloc(len);
+ silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
+
+ /* Put arguments */
+ for (i = 0; i < argc; i++) {
+ silc_buffer_format(buffer,
+ SILC_STR_UI_SHORT(argv_lens[i]),
+ SILC_STR_UI_CHAR(argv_types[i]),
+ SILC_STR_UI_XNSTRING(argv[i], argv_lens[i]),
+ SILC_STR_END);
+ silc_buffer_pull(buffer, 3 + argv_lens[i]);
+ }
+
+ silc_buffer_push(buffer, len);
+
+ return buffer;
+}
+
+#if 0
+/* Encodes Argument payload with variable argument list. The arguments
+ must be: unsigned int, unsigned char *, unsigned int, ... One
+ {unsigned int, unsigned char * and unsigned int} forms one argument,
+ thus `argc' in case when sending one {unsigned int, unsigned char *
+ and unsigned int} equals one (1) and when sending two of those it
+ equals two (2), and so on. This has to be preserved or bad things
+ will happen. The variable arguments is: {type, data, data_len}. */
+
+SilcBuffer silc_command_encode_payload_va(unsigned int argc, ...)
+{
+ va_list ap;
+ unsigned char **argv;
+ unsigned int *argv_lens = NULL, *argv_types = NULL;
+ unsigned char *x;
+ unsigned int x_len;
+ unsigned int x_type;
+ SilcBuffer buffer;
+ int i;
+
+ va_start(ap, argc);
+
+ argv = silc_calloc(argc, sizeof(unsigned char *));
+ argv_lens = silc_calloc(argc, sizeof(unsigned int));
+ argv_types = silc_calloc(argc, sizeof(unsigned int));
+
+ for (i = 0; i < argc; i++) {
+ x_type = va_arg(ap, unsigned int);
+ x = va_arg(ap, unsigned char *);
+ x_len = va_arg(ap, unsigned int);
+
+ argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
+ memcpy(argv[i], x, x_len);
+ argv_lens[i] = x_len;
+ argv_types[i] = x_type;
+ }
+
+ buffer = silc_argument_payload_encode(argc, argv,
+ argv_lens, argv_types);
+
+ for (i = 0; i < argc; i++)
+ silc_free(argv[i]);
+ silc_free(argv);
+ silc_free(argv_lens);
+ silc_free(argv_types);
+
+ return buffer;
+}
+#endif
+
+/* Free's Command Payload */
+
+void silc_argument_payload_free(SilcArgumentPayload payload)
+{
+ int i;
+
+ if (payload) {
+ for (i = 0; i < payload->argc; i++)
+ silc_free(payload->argv[i]);
+
+ silc_free(payload->argv);
+ silc_free(payload);
+ }
+}
+
+/* Returns number of arguments in payload */
+
+unsigned int silc_argument_get_arg_num(SilcArgumentPayload payload)
+{
+ return payload->argc;
+}
+
+/* Returns first argument from payload. */
+
+unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
+ unsigned int *ret_len)
+{
+ payload->pos = 0;
+
+ if (ret_len)
+ *ret_len = payload->argv_lens[payload->pos];
+
+ return payload->argv[payload->pos++];
+}
+
+/* Returns next argument from payload or NULL if no more arguments. */
+
+unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
+ unsigned int *ret_len)
+{
+ if (payload->pos >= payload->argc)
+ return NULL;
+
+ if (ret_len)
+ *ret_len = payload->argv_lens[payload->pos];
+
+ return payload->argv[payload->pos++];
+}
+
+/* Returns argument which type is `type'. */
+
+unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
+ unsigned int type,
+ unsigned int *ret_len)
+{
+ int i;
+
+ for (i = 0; i < payload->argc; i++)
+ if (payload->argv_types[i] == type)
+ break;
+
+ if (i >= payload->argc)
+ return NULL;
+
+ if (ret_len)
+ *ret_len = payload->argv_lens[i];
+
+ return payload->argv[i];
+}
--- /dev/null
+/*
+
+ silcpayload.h
+
+ Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ Copyright (C) 2000 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#ifndef SILCPAYLOAD_H
+#define SILCPAYLOAD_H
+
+/* Forward declarations */
+typedef struct SilcIDPayloadStruct *SilcIDPayload;
+typedef struct SilcArgumentPayloadStruct *SilcArgumentPayload;
+
+/* Prototypes */
+SilcIDPayload silc_id_payload_parse(SilcBuffer buffer);
+SilcBuffer silc_id_payload_encode(void *id, unsigned short len,
+ SilcIdType type);
+SilcArgumentPayload silc_argument_payload_parse(SilcBuffer buffer,
+ unsigned int argc);
+void silc_id_payload_free(SilcIDPayload payload);
+SilcIdType silc_id_payload_get_type(SilcIDPayload payload);
+void *silc_id_payload_get_id(SilcIDPayload payload);
+SilcBuffer silc_argument_payload_encode(unsigned int argc,
+ unsigned char **argv,
+ unsigned int *argv_lens,
+ unsigned int *argv_types);
+void silc_argument_payload_free(SilcArgumentPayload payload);
+unsigned int silc_argument_get_arg_num(SilcArgumentPayload payload);
+unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
+ unsigned int *ret_len);
+unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
+ unsigned int *ret_len);
+unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
+ unsigned int type,
+ unsigned int *ret_len);
+
+#endif