123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982 |
- /*
- * Copyright (c) 2007-2014, Anthony Minessale II
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include <esl.h>
- #include <esl_event.h>
- static char *my_dup(const char *s)
- {
- size_t len = strlen(s) + 1;
- void *new = malloc(len);
- esl_assert(new);
- return (char *) memcpy(new, s, len);
- }
- #ifndef ALLOC
- #define ALLOC(size) malloc(size)
- #endif
- #ifndef DUP
- #define DUP(str) my_dup(str)
- #endif
- #ifndef FREE
- #define FREE(ptr) esl_safe_free(ptr)
- #endif
- /* make sure this is synced with the esl_event_types_t enum in esl_types.h
- also never put any new ones before EVENT_ALL
- */
- static const char *EVENT_NAMES[] = {
- "CUSTOM",
- "CLONE",
- "CHANNEL_CREATE",
- "CHANNEL_DESTROY",
- "CHANNEL_STATE",
- "CHANNEL_CALLSTATE",
- "CHANNEL_ANSWER",
- "CHANNEL_HANGUP",
- "CHANNEL_HANGUP_COMPLETE",
- "CHANNEL_EXECUTE",
- "CHANNEL_EXECUTE_COMPLETE",
- "CHANNEL_HOLD",
- "CHANNEL_UNHOLD",
- "CHANNEL_BRIDGE",
- "CHANNEL_UNBRIDGE",
- "CHANNEL_PROGRESS",
- "CHANNEL_PROGRESS_MEDIA",
- "CHANNEL_OUTGOING",
- "CHANNEL_PARK",
- "CHANNEL_UNPARK",
- "CHANNEL_APPLICATION",
- "CHANNEL_ORIGINATE",
- "CHANNEL_UUID",
- "API",
- "LOG",
- "INBOUND_CHAN",
- "OUTBOUND_CHAN",
- "STARTUP",
- "SHUTDOWN",
- "PUBLISH",
- "UNPUBLISH",
- "TALK",
- "NOTALK",
- "SESSION_CRASH",
- "MODULE_LOAD",
- "MODULE_UNLOAD",
- "DTMF",
- "MESSAGE",
- "PRESENCE_IN",
- "NOTIFY_IN",
- "PRESENCE_OUT",
- "PRESENCE_PROBE",
- "MESSAGE_WAITING",
- "MESSAGE_QUERY",
- "ROSTER",
- "CODEC",
- "BACKGROUND_JOB",
- "DETECTED_SPEECH",
- "DETECTED_TONE",
- "PRIVATE_COMMAND",
- "HEARTBEAT",
- "TRAP",
- "ADD_SCHEDULE",
- "DEL_SCHEDULE",
- "EXE_SCHEDULE",
- "RE_SCHEDULE",
- "RELOADXML",
- "NOTIFY",
- "PHONE_FEATURE",
- "PHONE_FEATURE_SUBSCRIBE",
- "SEND_MESSAGE",
- "RECV_MESSAGE",
- "REQUEST_PARAMS",
- "CHANNEL_DATA",
- "GENERAL",
- "COMMAND",
- "SESSION_HEARTBEAT",
- "CLIENT_DISCONNECTED",
- "SERVER_DISCONNECTED",
- "SEND_INFO",
- "RECV_INFO",
- "RECV_RTCP_MESSAGE",
- "CALL_SECURE",
- "NAT",
- "RECORD_START",
- "RECORD_STOP",
- "PLAYBACK_START",
- "PLAYBACK_STOP",
- "CALL_UPDATE",
- "FAILURE",
- "SOCKET_DATA",
- "MEDIA_BUG_START",
- "MEDIA_BUG_STOP",
- "CONFERENCE_DATA_QUERY",
- "CONFERENCE_DATA",
- "CALL_SETUP_REQ",
- "CALL_SETUP_RESULT",
- "CALL_DETAIL",
- "DEVICE_STATE",
- "ALL"
- };
- ESL_DECLARE(const char *)esl_event_name(esl_event_types_t event)
- {
- return EVENT_NAMES[event];
- }
- ESL_DECLARE(esl_status_t) esl_name_event(const char *name, esl_event_types_t *type)
- {
- esl_event_types_t x;
- for (x = 0; x <= ESL_EVENT_ALL; x++) {
- if ((strlen(name) > 13 && !strcasecmp(name + 13, EVENT_NAMES[x])) || !strcasecmp(name, EVENT_NAMES[x])) {
- *type = x;
- return ESL_SUCCESS;
- }
- }
- return ESL_FAIL;
- }
- ESL_DECLARE(esl_status_t) esl_event_create_subclass(esl_event_t **event, esl_event_types_t event_id, const char *subclass_name)
- {
- *event = NULL;
- if ((event_id != ESL_EVENT_CLONE && event_id != ESL_EVENT_CUSTOM) && subclass_name) {
- return ESL_FAIL;
- }
- *event = ALLOC(sizeof(esl_event_t));
- esl_assert(*event);
- memset(*event, 0, sizeof(esl_event_t));
- if (event_id != ESL_EVENT_CLONE) {
- (*event)->event_id = event_id;
- esl_event_add_header_string(*event, ESL_STACK_BOTTOM, "Event-Name", esl_event_name((*event)->event_id));
- }
- if (subclass_name) {
- (*event)->subclass_name = DUP(subclass_name);
- esl_event_add_header_string(*event, ESL_STACK_BOTTOM, "Event-Subclass", subclass_name);
- }
-
- return ESL_SUCCESS;
- }
- ESL_DECLARE(const char *)esl_priority_name(esl_priority_t priority)
- {
- switch (priority) { /*lol */
- case ESL_PRIORITY_NORMAL:
- return "NORMAL";
- case ESL_PRIORITY_LOW:
- return "LOW";
- case ESL_PRIORITY_HIGH:
- return "HIGH";
- default:
- return "INVALID";
- }
- }
- ESL_DECLARE(esl_status_t) esl_event_set_priority(esl_event_t *event, esl_priority_t priority)
- {
- event->priority = priority;
- esl_event_add_header_string(event, ESL_STACK_TOP, "priority", esl_priority_name(priority));
- return ESL_SUCCESS;
- }
- #define ESL_HASH_KEY_STRING -1
- static unsigned int esl_ci_hashfunc_default(const char *char_key, esl_ssize_t *klen)
- {
- unsigned int hash = 0;
- const unsigned char *key = (const unsigned char *)char_key;
- const unsigned char *p;
- esl_ssize_t i;
- if (*klen == ESL_HASH_KEY_STRING) {
- for (p = key; *p; p++) {
- hash = hash * 33 + tolower(*p);
- }
- *klen = p - key;
- }
- else {
- for (p = key, i = *klen; i; i--, p++) {
- hash = hash * 33 + tolower(*p);
- }
- }
- return hash;
- }
- ESL_DECLARE(esl_event_header_t *) esl_event_get_header_ptr(esl_event_t *event, const char *header_name)
- {
- esl_event_header_t *hp;
- esl_ssize_t hlen = -1;
- unsigned long hash = 0;
- esl_assert(event);
- if (!header_name)
- return NULL;
- hash = esl_ci_hashfunc_default(header_name, &hlen);
- for (hp = event->headers; hp; hp = hp->next) {
- if ((!hp->hash || hash == hp->hash) && !strcasecmp(hp->name, header_name)) {
- return hp;
- }
- }
- return NULL;
- }
- ESL_DECLARE(char *) esl_event_get_header_idx(esl_event_t *event, const char *header_name, int idx)
- {
- esl_event_header_t *hp;
- if ((hp = esl_event_get_header_ptr(event, header_name))) {
- if (idx > -1) {
- if (idx < hp->idx) {
- return hp->array[idx];
- } else {
- return NULL;
- }
- }
- return hp->value;
- } else if (header_name && !strcmp(header_name, "_body")) {
- return event->body;
- }
- return NULL;
- }
- ESL_DECLARE(char *)esl_event_get_body(esl_event_t *event)
- {
- return (event ? event->body : NULL);
- }
- ESL_DECLARE(esl_status_t) esl_event_del_header_val(esl_event_t *event, const char *header_name, const char *val)
- {
- esl_event_header_t *hp, *lp = NULL, *tp;
- esl_status_t status = (esl_status_t) ESL_FALSE;
- int x = 0;
- esl_ssize_t hlen = -1;
- unsigned long hash = 0;
- tp = event->headers;
- while (tp) {
- hp = tp;
- tp = tp->next;
- x++;
- esl_assert(x < 1000000);
- hash = esl_ci_hashfunc_default(header_name, &hlen);
- if ((!hp->hash || hash == hp->hash) && (hp->name && !strcasecmp(header_name, hp->name)) && (esl_strlen_zero(val) || (hp->value && !strcmp(hp->value, val)))) {
- if (lp) {
- lp->next = hp->next;
- } else {
- event->headers = hp->next;
- }
- if (hp == event->last_header || !hp->next) {
- event->last_header = lp;
- }
- FREE(hp->name);
- if (hp->idx) {
- int i = 0;
- for (i = 0; i < hp->idx; i++) {
- FREE(hp->array[i]);
- }
- FREE(hp->array);
- }
- FREE(hp->value);
-
- memset(hp, 0, sizeof(*hp));
- #ifdef ESL_EVENT_RECYCLE
- if (esl_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, hp) != ESL_SUCCESS) {
- FREE(hp);
- }
- #else
- FREE(hp);
- #endif
- status = ESL_SUCCESS;
- } else {
- lp = hp;
- }
- }
- return status;
- }
- static esl_event_header_t *new_header(const char *header_name)
- {
- esl_event_header_t *header;
- #ifdef ESL_EVENT_RECYCLE
- void *pop;
- if (esl_queue_trypop(EVENT_HEADER_RECYCLE_QUEUE, &pop) == ESL_SUCCESS) {
- header = (esl_event_header_t *) pop;
- } else {
- #endif
- header = ALLOC(sizeof(*header));
- esl_assert(header);
- #ifdef ESL_EVENT_RECYCLE
- }
- #endif
- memset(header, 0, sizeof(*header));
- header->name = DUP(header_name);
- return header;
- }
- ESL_DECLARE(int) esl_event_add_array(esl_event_t *event, const char *var, const char *val)
- {
- char *data;
- char **array;
- int max = 0;
- int len;
- const char *p;
- int i;
- if (strlen(val) < 8) {
- return -1;
- }
- p = val + 7;
- max = 1;
- while((p = strstr(p, "|:"))) {
- max++;
- p += 2;
- }
- data = strdup(val + 7);
-
- len = (sizeof(char *) * max) + 1;
- array = malloc(len);
- esl_assert(array);
- memset(array, 0, len);
-
- esl_separate_string_string(data, "|:", array, max);
-
- for(i = 0; i < max; i++) {
- esl_event_add_header_string(event, ESL_STACK_PUSH, var, array[i]);
- }
- free(array);
- free(data);
- return 0;
- }
- static esl_status_t esl_event_base_add_header(esl_event_t *event, esl_stack_t stack, const char *header_name, char *data)
- {
- esl_event_header_t *header = NULL;
- esl_ssize_t hlen = -1;
- int exists = 0, fly = 0;
- char *index_ptr;
- int index = 0;
- char *real_header_name = NULL;
- if (!strcmp(header_name, "_body")) {
- esl_event_set_body(event, data);
- }
- if ((index_ptr = strchr(header_name, '['))) {
- index_ptr++;
- index = atoi(index_ptr);
- real_header_name = DUP(header_name);
- if ((index_ptr = strchr(real_header_name, '['))) {
- *index_ptr++ = '\0';
- }
- header_name = real_header_name;
- }
-
- if (index_ptr || (stack & ESL_STACK_PUSH) || (stack & ESL_STACK_UNSHIFT)) {
-
- if (!(header = esl_event_get_header_ptr(event, header_name)) && index_ptr) {
- header = new_header(header_name);
- if (esl_test_flag(event, ESL_EF_UNIQ_HEADERS)) {
- esl_event_del_header(event, header_name);
- }
- fly++;
- }
-
- if (header || (header = esl_event_get_header_ptr(event, header_name))) {
-
- if (index_ptr) {
- if (index > -1 && index <= 4000) {
- if (index < header->idx) {
- FREE(header->array[index]);
- header->array[index] = DUP(data);
- } else {
- int i;
- char **m;
-
- m = realloc(header->array, sizeof(char *) * (index + 1));
- esl_assert(m);
- header->array = m;
- for (i = header->idx; i < index; i++) {
- m[i] = DUP("");
- }
- m[index] = DUP(data);
- header->idx = index + 1;
- if (!fly) {
- exists = 1;
- }
- goto redraw;
- }
- }
- goto end;
- } else {
- if ((stack & ESL_STACK_PUSH) || (stack & ESL_STACK_UNSHIFT)) {
- exists++;
- stack &= ~(ESL_STACK_TOP | ESL_STACK_BOTTOM);
- } else {
- header = NULL;
- }
- }
- }
- }
- if (!header) {
- if (esl_strlen_zero(data)) {
- esl_event_del_header(event, header_name);
- FREE(data);
- goto end;
- }
- if (esl_test_flag(event, ESL_EF_UNIQ_HEADERS)) {
- esl_event_del_header(event, header_name);
- }
- if (strstr(data, "ARRAY::")) {
- esl_event_add_array(event, header_name, data);
- FREE(data);
- goto end;
- }
- header = new_header(header_name);
- }
-
- if ((stack & ESL_STACK_PUSH) || (stack & ESL_STACK_UNSHIFT)) {
- char **m = NULL;
- esl_size_t len = 0;
- char *hv;
- int i = 0, j = 0;
- if (header->value && !header->idx) {
- m = malloc(sizeof(char *));
- esl_assert(m);
- m[0] = header->value;
- header->value = NULL;
- header->array = m;
- header->idx++;
- m = NULL;
- }
- i = header->idx + 1;
- m = realloc(header->array, sizeof(char *) * i);
- esl_assert(m);
- if ((stack & ESL_STACK_PUSH)) {
- m[header->idx] = data;
- } else if ((stack & ESL_STACK_UNSHIFT)) {
- for (j = header->idx; j > 0; j--) {
- m[j] = m[j-1];
- }
- m[0] = data;
- }
- header->idx++;
- header->array = m;
- redraw:
- len = 0;
- for(j = 0; j < header->idx; j++) {
- len += strlen(header->array[j]) + 2;
- }
- if (len) {
- len += 8;
- hv = realloc(header->value, len);
- esl_assert(hv);
- header->value = hv;
- if (header->idx > 1) {
- esl_snprintf(header->value, len, "ARRAY::");
- } else {
- *header->value = '\0';
- }
- for(j = 0; j < header->idx; j++) {
- esl_snprintf(header->value + strlen(header->value), len - strlen(header->value), "%s%s", j == 0 ? "" : "|:", header->array[j]);
- }
- }
- } else {
- header->value = data;
- }
- if (!exists) {
- header->hash = esl_ci_hashfunc_default(header->name, &hlen);
- if ((stack & ESL_STACK_TOP)) {
- header->next = event->headers;
- event->headers = header;
- if (!event->last_header) {
- event->last_header = header;
- }
- } else {
- if (event->last_header) {
- event->last_header->next = header;
- } else {
- event->headers = header;
- header->next = NULL;
- }
- event->last_header = header;
- }
- }
- end:
- esl_safe_free(real_header_name);
- return ESL_SUCCESS;
- }
- ESL_DECLARE(esl_status_t) esl_event_add_header(esl_event_t *event, esl_stack_t stack, const char *header_name, const char *fmt, ...)
- {
- int ret = 0;
- char *data;
- va_list ap;
- va_start(ap, fmt);
- ret = esl_vasprintf(&data, fmt, ap);
- va_end(ap);
- if (ret == -1) {
- return ESL_FAIL;
- }
- return esl_event_base_add_header(event, stack, header_name, data);
- }
- ESL_DECLARE(esl_status_t) esl_event_add_header_string(esl_event_t *event, esl_stack_t stack, const char *header_name, const char *data)
- {
- if (data) {
- return esl_event_base_add_header(event, stack, header_name, DUP(data));
- }
- return ESL_FAIL;
- }
- ESL_DECLARE(esl_status_t) esl_event_set_body(esl_event_t *event, const char *body)
- {
- esl_safe_free(event->body);
- if (body) {
- event->body = DUP(body);
- }
-
- return ESL_SUCCESS;
- }
- ESL_DECLARE(esl_status_t) esl_event_add_body(esl_event_t *event, const char *fmt, ...)
- {
- int ret = 0;
- char *data;
- va_list ap;
- if (fmt) {
- va_start(ap, fmt);
- ret = esl_vasprintf(&data, fmt, ap);
- va_end(ap);
- if (ret == -1) {
- return ESL_FAIL;
- } else {
- esl_safe_free(event->body);
- event->body = data;
- return ESL_SUCCESS;
- }
- } else {
- return ESL_FAIL;
- }
- }
- ESL_DECLARE(void) esl_event_destroy(esl_event_t **event)
- {
- esl_event_t *ep = *event;
- esl_event_header_t *hp, *this;
- if (ep) {
- for (hp = ep->headers; hp;) {
- this = hp;
- hp = hp->next;
- FREE(this->name);
- if (this->idx) {
- int i = 0;
- for (i = 0; i < this->idx; i++) {
- FREE(this->array[i]);
- }
- FREE(this->array);
- }
- FREE(this->value);
-
- #ifdef ESL_EVENT_RECYCLE
- if (esl_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, this) != ESL_SUCCESS) {
- FREE(this);
- }
- #else
- FREE(this);
- #endif
- }
- FREE(ep->body);
- FREE(ep->subclass_name);
- #ifdef ESL_EVENT_RECYCLE
- if (esl_queue_trypush(EVENT_RECYCLE_QUEUE, ep) != ESL_SUCCESS) {
- FREE(ep);
- }
- #else
- FREE(ep);
- #endif
- }
- *event = NULL;
- }
- ESL_DECLARE(void) esl_event_merge(esl_event_t *event, esl_event_t *tomerge)
- {
- esl_event_header_t *hp;
-
- esl_assert(tomerge && event);
- for (hp = tomerge->headers; hp; hp = hp->next) {
- if (hp->idx) {
- int i;
-
- for(i = 0; i < hp->idx; i++) {
- esl_event_add_header_string(event, ESL_STACK_PUSH, hp->name, hp->array[i]);
- }
- } else {
- esl_event_add_header_string(event, ESL_STACK_BOTTOM, hp->name, hp->value);
- }
- }
- }
- ESL_DECLARE(esl_status_t) esl_event_dup(esl_event_t **event, esl_event_t *todup)
- {
- esl_event_header_t *hp;
- if (esl_event_create_subclass(event, ESL_EVENT_CLONE, todup->subclass_name) != ESL_SUCCESS) {
- return ESL_GENERR;
- }
- (*event)->event_id = todup->event_id;
- (*event)->event_user_data = todup->event_user_data;
- (*event)->bind_user_data = todup->bind_user_data;
- (*event)->flags = todup->flags;
- for (hp = todup->headers; hp; hp = hp->next) {
- if (todup->subclass_name && !strcmp(hp->name, "Event-Subclass")) {
- continue;
- }
-
- if (hp->idx) {
- int i;
- for (i = 0; i < hp->idx; i++) {
- esl_event_add_header_string(*event, ESL_STACK_PUSH, hp->name, hp->array[i]);
- }
- } else {
- esl_event_add_header_string(*event, ESL_STACK_BOTTOM, hp->name, hp->value);
- }
- }
- if (todup->body) {
- (*event)->body = DUP(todup->body);
- }
- (*event)->key = todup->key;
- return ESL_SUCCESS;
- }
- ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, esl_bool_t encode)
- {
- esl_size_t len = 0;
- esl_event_header_t *hp;
- esl_size_t llen = 0, dlen = 0, blocksize = 512, encode_len = 1536, new_len = 0;
- char *buf;
- char *encode_buf = NULL; /* used for url encoding of variables to make sure unsafe things stay out of the serialized copy */
- *str = NULL;
- dlen = blocksize * 2;
- if (!(buf = malloc(dlen))) {
- abort();
- }
- /* go ahead and give ourselves some space to work with, should save a few reallocs */
- if (!(encode_buf = malloc(encode_len))) {
- abort();
- }
- /* esl_log_printf(ESL_CHANNEL_LOG, ESL_LOG_INFO, "hit serialized!.\n"); */
- for (hp = event->headers; hp; hp = hp->next) {
- /*
- * grab enough memory to store 3x the string (url encode takes one char and turns it into %XX)
- * so we could end up with a string that is 3 times the originals length, unlikely but rather
- * be safe than destroy the string, also add one for the null. And try to be smart about using
- * the memory, allocate and only reallocate if we need more. This avoids an alloc, free CPU
- * destroying loop.
- */
- if (hp->idx) {
- int i;
- new_len = 0;
- for(i = 0; i < hp->idx; i++) {
- new_len += (strlen(hp->array[i]) * 3) + 1;
- }
- } else {
- new_len = (strlen(hp->value) * 3) + 1;
- }
- if (encode_len < new_len) {
- char *tmp;
- /* keep track of the size of our allocation */
- encode_len = new_len;
- if (!(tmp = realloc(encode_buf, encode_len))) {
- abort();
- }
- encode_buf = tmp;
- }
- /* handle any bad things in the string like newlines : etc that screw up the serialized format */
- if (encode) {
- esl_url_encode(hp->value, encode_buf, encode_len);
- } else {
- esl_snprintf(encode_buf, encode_len, "%s", hp->value);
- }
- llen = strlen(hp->name) + strlen(encode_buf) + 8;
- if ((len + llen) > dlen) {
- char *m;
- char *old = buf;
- dlen += (blocksize + (len + llen));
- if ((m = realloc(buf, dlen))) {
- buf = m;
- } else {
- buf = old;
- abort();
- }
- }
- esl_snprintf(buf + len, dlen - len, "%s: %s\n", hp->name, *encode_buf == '\0' ? "_undef_" : encode_buf);
- len = strlen(buf);
- }
- /* we are done with the memory we used for encoding, give it back */
- esl_safe_free(encode_buf);
- if (event->body) {
- int blen = (int) strlen(event->body);
- llen = blen;
- if (blen) {
- llen += 25;
- } else {
- llen += 5;
- }
- if ((len + llen) > dlen) {
- char *m;
- char *old = buf;
- dlen += (blocksize + (len + llen));
- if ((m = realloc(buf, dlen))) {
- buf = m;
- } else {
- buf = old;
- abort();
- }
- }
- if (blen) {
- esl_snprintf(buf + len, dlen - len, "Content-Length: %d\n\n%s", blen, event->body);
- } else {
- esl_snprintf(buf + len, dlen - len, "\n");
- }
- } else {
- esl_snprintf(buf + len, dlen - len, "\n");
- }
- *str = buf;
- return ESL_SUCCESS;
- }
- ESL_DECLARE(esl_status_t) esl_event_create_json(esl_event_t **event, const char *json)
- {
- esl_event_t *new_event;
- cJSON *cj, *cjp;
- if (!(cj = cJSON_Parse(json))) {
- return (esl_status_t) ESL_FALSE;
- }
- if (esl_event_create(&new_event, ESL_EVENT_CLONE) != ESL_SUCCESS) {
- cJSON_Delete(cj);
- return (esl_status_t) ESL_FALSE;
- }
- for (cjp = cj->child; cjp; cjp = cjp->next) {
- char *name = cjp->string;
- char *value = cjp->valuestring;
- if (name && value) {
- if (!strcasecmp(name, "_body")) {
- esl_event_add_body(new_event, value, ESL_VA_NONE);
- } else {
- if (!strcasecmp(name, "event-name")) {
- esl_event_del_header(new_event, "event-name");
- esl_name_event(value, &new_event->event_id);
- }
- esl_event_add_header_string(new_event, ESL_STACK_BOTTOM, name, value);
- }
- } else if (name) {
- if (cjp->type == cJSON_Array) {
- int i, x = cJSON_GetArraySize(cjp);
- for (i = 0; i < x; i++) {
- cJSON *item = cJSON_GetArrayItem(cjp, i);
- if (item != NULL && item->type == cJSON_String && item->valuestring) {
- esl_event_add_header_string(new_event, ESL_STACK_PUSH, name, item->valuestring);
- }
- }
- }
- }
- }
-
- cJSON_Delete(cj);
- *event = new_event;
- return ESL_SUCCESS;
- }
- ESL_DECLARE(esl_status_t) esl_event_serialize_json(esl_event_t *event, char **str)
- {
- esl_event_header_t *hp;
- cJSON *cj;
- *str = NULL;
-
- cj = cJSON_CreateObject();
- for (hp = event->headers; hp; hp = hp->next) {
- if (hp->idx) {
- cJSON *a = cJSON_CreateArray();
- int i;
- for(i = 0; i < hp->idx; i++) {
- cJSON_AddItemToArray(a, cJSON_CreateString(hp->array[i]));
- }
-
- cJSON_AddItemToObject(cj, hp->name, a);
-
- } else {
- cJSON_AddItemToObject(cj, hp->name, cJSON_CreateString(hp->value));
- }
- }
- if (event->body) {
- int blen = (int) strlen(event->body);
- char tmp[25];
- esl_snprintf(tmp, sizeof(tmp), "%d", blen);
- cJSON_AddItemToObject(cj, "Content-Length", cJSON_CreateString(tmp));
- cJSON_AddItemToObject(cj, "_body", cJSON_CreateString(event->body));
- }
- *str = cJSON_Print(cj);
- cJSON_Delete(cj);
-
- return ESL_SUCCESS;
- }
- /* For Emacs:
- * Local Variables:
- * mode:c
- * indent-tabs-mode:t
- * tab-width:4
- * c-basic-offset:4
- * End:
- * For VIM:
- * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
- */
|