/* silcnotify.c Author: Pekka Riikonen Copyright (C) 2000 - 2007 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; version 2 of the License. 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. */ /* $Id$ */ #include "silc.h" #include "silcnotify.h" /****************************************************************************** Notify Payload ******************************************************************************/ struct SilcNotifyPayloadStruct { SilcNotifyType type; unsigned char argc; SilcArgumentPayload args; }; /* Parse notify payload buffer and return data into payload structure */ SilcNotifyPayload silc_notify_payload_parse(const unsigned char *payload, SilcUInt32 payload_len) { SilcBufferStruct buffer; SilcNotifyPayload newp; SilcUInt16 len; int ret; SILC_LOG_DEBUG(("Parsing Notify payload")); silc_buffer_set(&buffer, (unsigned char *)payload, payload_len); newp = silc_calloc(1, sizeof(*newp)); if (!newp) return NULL; ret = silc_buffer_unformat(&buffer, SILC_STR_UI_SHORT(&newp->type), SILC_STR_UI_SHORT(&len), SILC_STR_UI_CHAR(&newp->argc), SILC_STR_END); if (ret == -1) goto err; if (len > silc_buffer_len(&buffer)) goto err; if (newp->argc) { silc_buffer_pull(&buffer, 5); newp->args = silc_argument_payload_parse(buffer.data, silc_buffer_len(&buffer), newp->argc); if (!newp->args) goto err; silc_buffer_push(&buffer, 5); } return newp; err: silc_free(newp); return NULL; } /* Encode notify payload with variable argument list. If `argc' is > 0 argument payloads will be associated to the notify payload. Variable arguments must be {usigned char *, SilcUInt32 (len)}. */ SilcBuffer silc_notify_payload_encode(SilcNotifyType type, SilcUInt32 argc, va_list ap) { SilcBuffer buffer; SilcBuffer args = NULL; unsigned char **argv; SilcUInt32 *argv_lens = NULL, *argv_types = NULL; unsigned char *x; SilcUInt32 x_len, len = 0; int i, k = 0; if (argc) { argv = silc_calloc(argc, sizeof(unsigned char *)); if (!argv) return NULL; argv_lens = silc_calloc(argc, sizeof(SilcUInt32)); if (!argv_lens) { silc_free(argv); return NULL; } argv_types = silc_calloc(argc, sizeof(SilcUInt32)); if (!argv_types) { silc_free(argv_lens); silc_free(argv); return NULL; } for (i = 0, k = 0; i < argc; i++) { x = va_arg(ap, unsigned char *); x_len = va_arg(ap, SilcUInt32); if (!x || !x_len) continue; argv[k] = silc_memdup(x, x_len); if (!argv[k]) return NULL; argv_lens[k] = x_len; argv_types[k] = i + 1; k++; } args = silc_argument_payload_encode(k, argv, argv_lens, argv_types); len = silc_buffer_len(args); for (i = 0; i < k; i++) silc_free(argv[i]); silc_free(argv); silc_free(argv_lens); silc_free(argv_types); } len += 5; buffer = silc_buffer_alloc_size(len); if (!buffer) return NULL; silc_buffer_format(buffer, SILC_STR_UI_SHORT(type), SILC_STR_UI_SHORT(len), SILC_STR_UI_CHAR(k), SILC_STR_END); if (k) { silc_buffer_format(buffer, SILC_STR_OFFSET(5), SILC_STR_DATA(args->data, silc_buffer_len(args)), SILC_STR_END); silc_buffer_free(args); } return buffer; } /* Same as above but takes argument from the `args' Argument Payload. */ SilcBuffer silc_notify_payload_encode_args(SilcNotifyType type, SilcUInt32 argc, SilcBuffer args) { SilcBuffer buffer; SilcUInt32 len; len = 5 + (args ? silc_buffer_len(args) : 0); buffer = silc_buffer_alloc_size(len); if (!buffer) return NULL; silc_buffer_format(buffer, SILC_STR_UI_SHORT(type), SILC_STR_UI_SHORT(len), SILC_STR_UI_CHAR(argc), SILC_STR_END); if (args) silc_buffer_format(buffer, SILC_STR_OFFSET(5), SILC_STR_DATA(args->data, silc_buffer_len(args)), SILC_STR_END); return buffer; } /* Frees notify payload */ void silc_notify_payload_free(SilcNotifyPayload payload) { if (payload) { silc_argument_payload_free(payload->args); silc_free(payload); } } /* Return notify type */ SilcNotifyType silc_notify_get_type(SilcNotifyPayload payload) { return payload->type; } /* Return argument nums */ SilcUInt32 silc_notify_get_arg_num(SilcNotifyPayload payload) { return payload->argc; } /* Return argument payload */ SilcArgumentPayload silc_notify_get_args(SilcNotifyPayload payload) { return payload->args; }