/* silcnotify.c Author: Pekka Riikonen Copyright (C) 2000 - 2002 Pekka Riikonen The contents of this file are subject to one of the Licenses specified in the COPYING file; You may not use this file except in compliance with the License. The software distributed under the License is distributed on an "AS IS" basis, in the hope that it will be useful, but WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the COPYING file for more information. */ /* $Id: silcnotify.c,v 1.14.2.1 2002/12/29 21:27:37 priikone Exp $ */ #include "silcincludes.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 > buffer.len) goto err; if (newp->argc) { silc_buffer_pull(&buffer, 5); newp->args = silc_argument_payload_parse(buffer.data, buffer.len, newp->argc); 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 = args->len; 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_pull(buffer, 5); silc_buffer_format(buffer, SILC_STR_UI_XNSTRING(args->data, args->len), SILC_STR_END); silc_buffer_push(buffer, 5); 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 ? args->len : 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_pull(buffer, 5); silc_buffer_format(buffer, SILC_STR_UI_XNSTRING(args->data, args->len), SILC_STR_END); silc_buffer_push(buffer, 5); } 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; }