esl_event.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982
  1. /*
  2. * Copyright (c) 2007-2014, Anthony Minessale II
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of the original author; nor the names of any contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
  25. * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  26. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  27. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  28. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  29. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. #include <esl.h>
  34. #include <esl_event.h>
  35. static char *my_dup(const char *s)
  36. {
  37. size_t len = strlen(s) + 1;
  38. void *new = malloc(len);
  39. esl_assert(new);
  40. return (char *) memcpy(new, s, len);
  41. }
  42. #ifndef ALLOC
  43. #define ALLOC(size) malloc(size)
  44. #endif
  45. #ifndef DUP
  46. #define DUP(str) my_dup(str)
  47. #endif
  48. #ifndef FREE
  49. #define FREE(ptr) esl_safe_free(ptr)
  50. #endif
  51. /* make sure this is synced with the esl_event_types_t enum in esl_types.h
  52. also never put any new ones before EVENT_ALL
  53. */
  54. static const char *EVENT_NAMES[] = {
  55. "CUSTOM",
  56. "CLONE",
  57. "CHANNEL_CREATE",
  58. "CHANNEL_DESTROY",
  59. "CHANNEL_STATE",
  60. "CHANNEL_CALLSTATE",
  61. "CHANNEL_ANSWER",
  62. "CHANNEL_HANGUP",
  63. "CHANNEL_HANGUP_COMPLETE",
  64. "CHANNEL_EXECUTE",
  65. "CHANNEL_EXECUTE_COMPLETE",
  66. "CHANNEL_HOLD",
  67. "CHANNEL_UNHOLD",
  68. "CHANNEL_BRIDGE",
  69. "CHANNEL_UNBRIDGE",
  70. "CHANNEL_PROGRESS",
  71. "CHANNEL_PROGRESS_MEDIA",
  72. "CHANNEL_OUTGOING",
  73. "CHANNEL_PARK",
  74. "CHANNEL_UNPARK",
  75. "CHANNEL_APPLICATION",
  76. "CHANNEL_ORIGINATE",
  77. "CHANNEL_UUID",
  78. "API",
  79. "LOG",
  80. "INBOUND_CHAN",
  81. "OUTBOUND_CHAN",
  82. "STARTUP",
  83. "SHUTDOWN",
  84. "PUBLISH",
  85. "UNPUBLISH",
  86. "TALK",
  87. "NOTALK",
  88. "SESSION_CRASH",
  89. "MODULE_LOAD",
  90. "MODULE_UNLOAD",
  91. "DTMF",
  92. "MESSAGE",
  93. "PRESENCE_IN",
  94. "NOTIFY_IN",
  95. "PRESENCE_OUT",
  96. "PRESENCE_PROBE",
  97. "MESSAGE_WAITING",
  98. "MESSAGE_QUERY",
  99. "ROSTER",
  100. "CODEC",
  101. "BACKGROUND_JOB",
  102. "DETECTED_SPEECH",
  103. "DETECTED_TONE",
  104. "PRIVATE_COMMAND",
  105. "HEARTBEAT",
  106. "TRAP",
  107. "ADD_SCHEDULE",
  108. "DEL_SCHEDULE",
  109. "EXE_SCHEDULE",
  110. "RE_SCHEDULE",
  111. "RELOADXML",
  112. "NOTIFY",
  113. "PHONE_FEATURE",
  114. "PHONE_FEATURE_SUBSCRIBE",
  115. "SEND_MESSAGE",
  116. "RECV_MESSAGE",
  117. "REQUEST_PARAMS",
  118. "CHANNEL_DATA",
  119. "GENERAL",
  120. "COMMAND",
  121. "SESSION_HEARTBEAT",
  122. "CLIENT_DISCONNECTED",
  123. "SERVER_DISCONNECTED",
  124. "SEND_INFO",
  125. "RECV_INFO",
  126. "RECV_RTCP_MESSAGE",
  127. "CALL_SECURE",
  128. "NAT",
  129. "RECORD_START",
  130. "RECORD_STOP",
  131. "PLAYBACK_START",
  132. "PLAYBACK_STOP",
  133. "CALL_UPDATE",
  134. "FAILURE",
  135. "SOCKET_DATA",
  136. "MEDIA_BUG_START",
  137. "MEDIA_BUG_STOP",
  138. "CONFERENCE_DATA_QUERY",
  139. "CONFERENCE_DATA",
  140. "CALL_SETUP_REQ",
  141. "CALL_SETUP_RESULT",
  142. "CALL_DETAIL",
  143. "DEVICE_STATE",
  144. "ALL"
  145. };
  146. ESL_DECLARE(const char *)esl_event_name(esl_event_types_t event)
  147. {
  148. return EVENT_NAMES[event];
  149. }
  150. ESL_DECLARE(esl_status_t) esl_name_event(const char *name, esl_event_types_t *type)
  151. {
  152. esl_event_types_t x;
  153. for (x = 0; x <= ESL_EVENT_ALL; x++) {
  154. if ((strlen(name) > 13 && !strcasecmp(name + 13, EVENT_NAMES[x])) || !strcasecmp(name, EVENT_NAMES[x])) {
  155. *type = x;
  156. return ESL_SUCCESS;
  157. }
  158. }
  159. return ESL_FAIL;
  160. }
  161. ESL_DECLARE(esl_status_t) esl_event_create_subclass(esl_event_t **event, esl_event_types_t event_id, const char *subclass_name)
  162. {
  163. *event = NULL;
  164. if ((event_id != ESL_EVENT_CLONE && event_id != ESL_EVENT_CUSTOM) && subclass_name) {
  165. return ESL_FAIL;
  166. }
  167. *event = ALLOC(sizeof(esl_event_t));
  168. esl_assert(*event);
  169. memset(*event, 0, sizeof(esl_event_t));
  170. if (event_id != ESL_EVENT_CLONE) {
  171. (*event)->event_id = event_id;
  172. esl_event_add_header_string(*event, ESL_STACK_BOTTOM, "Event-Name", esl_event_name((*event)->event_id));
  173. }
  174. if (subclass_name) {
  175. (*event)->subclass_name = DUP(subclass_name);
  176. esl_event_add_header_string(*event, ESL_STACK_BOTTOM, "Event-Subclass", subclass_name);
  177. }
  178. return ESL_SUCCESS;
  179. }
  180. ESL_DECLARE(const char *)esl_priority_name(esl_priority_t priority)
  181. {
  182. switch (priority) { /*lol */
  183. case ESL_PRIORITY_NORMAL:
  184. return "NORMAL";
  185. case ESL_PRIORITY_LOW:
  186. return "LOW";
  187. case ESL_PRIORITY_HIGH:
  188. return "HIGH";
  189. default:
  190. return "INVALID";
  191. }
  192. }
  193. ESL_DECLARE(esl_status_t) esl_event_set_priority(esl_event_t *event, esl_priority_t priority)
  194. {
  195. event->priority = priority;
  196. esl_event_add_header_string(event, ESL_STACK_TOP, "priority", esl_priority_name(priority));
  197. return ESL_SUCCESS;
  198. }
  199. #define ESL_HASH_KEY_STRING -1
  200. static unsigned int esl_ci_hashfunc_default(const char *char_key, esl_ssize_t *klen)
  201. {
  202. unsigned int hash = 0;
  203. const unsigned char *key = (const unsigned char *)char_key;
  204. const unsigned char *p;
  205. esl_ssize_t i;
  206. if (*klen == ESL_HASH_KEY_STRING) {
  207. for (p = key; *p; p++) {
  208. hash = hash * 33 + tolower(*p);
  209. }
  210. *klen = p - key;
  211. }
  212. else {
  213. for (p = key, i = *klen; i; i--, p++) {
  214. hash = hash * 33 + tolower(*p);
  215. }
  216. }
  217. return hash;
  218. }
  219. ESL_DECLARE(esl_event_header_t *) esl_event_get_header_ptr(esl_event_t *event, const char *header_name)
  220. {
  221. esl_event_header_t *hp;
  222. esl_ssize_t hlen = -1;
  223. unsigned long hash = 0;
  224. esl_assert(event);
  225. if (!header_name)
  226. return NULL;
  227. hash = esl_ci_hashfunc_default(header_name, &hlen);
  228. for (hp = event->headers; hp; hp = hp->next) {
  229. if ((!hp->hash || hash == hp->hash) && !strcasecmp(hp->name, header_name)) {
  230. return hp;
  231. }
  232. }
  233. return NULL;
  234. }
  235. ESL_DECLARE(char *) esl_event_get_header_idx(esl_event_t *event, const char *header_name, int idx)
  236. {
  237. esl_event_header_t *hp;
  238. if ((hp = esl_event_get_header_ptr(event, header_name))) {
  239. if (idx > -1) {
  240. if (idx < hp->idx) {
  241. return hp->array[idx];
  242. } else {
  243. return NULL;
  244. }
  245. }
  246. return hp->value;
  247. } else if (header_name && !strcmp(header_name, "_body")) {
  248. return event->body;
  249. }
  250. return NULL;
  251. }
  252. ESL_DECLARE(char *)esl_event_get_body(esl_event_t *event)
  253. {
  254. return (event ? event->body : NULL);
  255. }
  256. ESL_DECLARE(esl_status_t) esl_event_del_header_val(esl_event_t *event, const char *header_name, const char *val)
  257. {
  258. esl_event_header_t *hp, *lp = NULL, *tp;
  259. esl_status_t status = (esl_status_t) ESL_FALSE;
  260. int x = 0;
  261. esl_ssize_t hlen = -1;
  262. unsigned long hash = 0;
  263. tp = event->headers;
  264. while (tp) {
  265. hp = tp;
  266. tp = tp->next;
  267. x++;
  268. esl_assert(x < 1000000);
  269. hash = esl_ci_hashfunc_default(header_name, &hlen);
  270. if ((!hp->hash || hash == hp->hash) && (hp->name && !strcasecmp(header_name, hp->name)) && (esl_strlen_zero(val) || (hp->value && !strcmp(hp->value, val)))) {
  271. if (lp) {
  272. lp->next = hp->next;
  273. } else {
  274. event->headers = hp->next;
  275. }
  276. if (hp == event->last_header || !hp->next) {
  277. event->last_header = lp;
  278. }
  279. FREE(hp->name);
  280. if (hp->idx) {
  281. int i = 0;
  282. for (i = 0; i < hp->idx; i++) {
  283. FREE(hp->array[i]);
  284. }
  285. FREE(hp->array);
  286. }
  287. FREE(hp->value);
  288. memset(hp, 0, sizeof(*hp));
  289. #ifdef ESL_EVENT_RECYCLE
  290. if (esl_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, hp) != ESL_SUCCESS) {
  291. FREE(hp);
  292. }
  293. #else
  294. FREE(hp);
  295. #endif
  296. status = ESL_SUCCESS;
  297. } else {
  298. lp = hp;
  299. }
  300. }
  301. return status;
  302. }
  303. static esl_event_header_t *new_header(const char *header_name)
  304. {
  305. esl_event_header_t *header;
  306. #ifdef ESL_EVENT_RECYCLE
  307. void *pop;
  308. if (esl_queue_trypop(EVENT_HEADER_RECYCLE_QUEUE, &pop) == ESL_SUCCESS) {
  309. header = (esl_event_header_t *) pop;
  310. } else {
  311. #endif
  312. header = ALLOC(sizeof(*header));
  313. esl_assert(header);
  314. #ifdef ESL_EVENT_RECYCLE
  315. }
  316. #endif
  317. memset(header, 0, sizeof(*header));
  318. header->name = DUP(header_name);
  319. return header;
  320. }
  321. ESL_DECLARE(int) esl_event_add_array(esl_event_t *event, const char *var, const char *val)
  322. {
  323. char *data;
  324. char **array;
  325. int max = 0;
  326. int len;
  327. const char *p;
  328. int i;
  329. if (strlen(val) < 8) {
  330. return -1;
  331. }
  332. p = val + 7;
  333. max = 1;
  334. while((p = strstr(p, "|:"))) {
  335. max++;
  336. p += 2;
  337. }
  338. data = strdup(val + 7);
  339. len = (sizeof(char *) * max) + 1;
  340. array = malloc(len);
  341. esl_assert(array);
  342. memset(array, 0, len);
  343. esl_separate_string_string(data, "|:", array, max);
  344. for(i = 0; i < max; i++) {
  345. esl_event_add_header_string(event, ESL_STACK_PUSH, var, array[i]);
  346. }
  347. free(array);
  348. free(data);
  349. return 0;
  350. }
  351. static esl_status_t esl_event_base_add_header(esl_event_t *event, esl_stack_t stack, const char *header_name, char *data)
  352. {
  353. esl_event_header_t *header = NULL;
  354. esl_ssize_t hlen = -1;
  355. int exists = 0, fly = 0;
  356. char *index_ptr;
  357. int index = 0;
  358. char *real_header_name = NULL;
  359. if (!strcmp(header_name, "_body")) {
  360. esl_event_set_body(event, data);
  361. }
  362. if ((index_ptr = strchr(header_name, '['))) {
  363. index_ptr++;
  364. index = atoi(index_ptr);
  365. real_header_name = DUP(header_name);
  366. if ((index_ptr = strchr(real_header_name, '['))) {
  367. *index_ptr++ = '\0';
  368. }
  369. header_name = real_header_name;
  370. }
  371. if (index_ptr || (stack & ESL_STACK_PUSH) || (stack & ESL_STACK_UNSHIFT)) {
  372. if (!(header = esl_event_get_header_ptr(event, header_name)) && index_ptr) {
  373. header = new_header(header_name);
  374. if (esl_test_flag(event, ESL_EF_UNIQ_HEADERS)) {
  375. esl_event_del_header(event, header_name);
  376. }
  377. fly++;
  378. }
  379. if (header || (header = esl_event_get_header_ptr(event, header_name))) {
  380. if (index_ptr) {
  381. if (index > -1 && index <= 4000) {
  382. if (index < header->idx) {
  383. FREE(header->array[index]);
  384. header->array[index] = DUP(data);
  385. } else {
  386. int i;
  387. char **m;
  388. m = realloc(header->array, sizeof(char *) * (index + 1));
  389. esl_assert(m);
  390. header->array = m;
  391. for (i = header->idx; i < index; i++) {
  392. m[i] = DUP("");
  393. }
  394. m[index] = DUP(data);
  395. header->idx = index + 1;
  396. if (!fly) {
  397. exists = 1;
  398. }
  399. goto redraw;
  400. }
  401. }
  402. goto end;
  403. } else {
  404. if ((stack & ESL_STACK_PUSH) || (stack & ESL_STACK_UNSHIFT)) {
  405. exists++;
  406. stack &= ~(ESL_STACK_TOP | ESL_STACK_BOTTOM);
  407. } else {
  408. header = NULL;
  409. }
  410. }
  411. }
  412. }
  413. if (!header) {
  414. if (esl_strlen_zero(data)) {
  415. esl_event_del_header(event, header_name);
  416. FREE(data);
  417. goto end;
  418. }
  419. if (esl_test_flag(event, ESL_EF_UNIQ_HEADERS)) {
  420. esl_event_del_header(event, header_name);
  421. }
  422. if (strstr(data, "ARRAY::")) {
  423. esl_event_add_array(event, header_name, data);
  424. FREE(data);
  425. goto end;
  426. }
  427. header = new_header(header_name);
  428. }
  429. if ((stack & ESL_STACK_PUSH) || (stack & ESL_STACK_UNSHIFT)) {
  430. char **m = NULL;
  431. esl_size_t len = 0;
  432. char *hv;
  433. int i = 0, j = 0;
  434. if (header->value && !header->idx) {
  435. m = malloc(sizeof(char *));
  436. esl_assert(m);
  437. m[0] = header->value;
  438. header->value = NULL;
  439. header->array = m;
  440. header->idx++;
  441. m = NULL;
  442. }
  443. i = header->idx + 1;
  444. m = realloc(header->array, sizeof(char *) * i);
  445. esl_assert(m);
  446. if ((stack & ESL_STACK_PUSH)) {
  447. m[header->idx] = data;
  448. } else if ((stack & ESL_STACK_UNSHIFT)) {
  449. for (j = header->idx; j > 0; j--) {
  450. m[j] = m[j-1];
  451. }
  452. m[0] = data;
  453. }
  454. header->idx++;
  455. header->array = m;
  456. redraw:
  457. len = 0;
  458. for(j = 0; j < header->idx; j++) {
  459. len += strlen(header->array[j]) + 2;
  460. }
  461. if (len) {
  462. len += 8;
  463. hv = realloc(header->value, len);
  464. esl_assert(hv);
  465. header->value = hv;
  466. if (header->idx > 1) {
  467. esl_snprintf(header->value, len, "ARRAY::");
  468. } else {
  469. *header->value = '\0';
  470. }
  471. for(j = 0; j < header->idx; j++) {
  472. esl_snprintf(header->value + strlen(header->value), len - strlen(header->value), "%s%s", j == 0 ? "" : "|:", header->array[j]);
  473. }
  474. }
  475. } else {
  476. header->value = data;
  477. }
  478. if (!exists) {
  479. header->hash = esl_ci_hashfunc_default(header->name, &hlen);
  480. if ((stack & ESL_STACK_TOP)) {
  481. header->next = event->headers;
  482. event->headers = header;
  483. if (!event->last_header) {
  484. event->last_header = header;
  485. }
  486. } else {
  487. if (event->last_header) {
  488. event->last_header->next = header;
  489. } else {
  490. event->headers = header;
  491. header->next = NULL;
  492. }
  493. event->last_header = header;
  494. }
  495. }
  496. end:
  497. esl_safe_free(real_header_name);
  498. return ESL_SUCCESS;
  499. }
  500. ESL_DECLARE(esl_status_t) esl_event_add_header(esl_event_t *event, esl_stack_t stack, const char *header_name, const char *fmt, ...)
  501. {
  502. int ret = 0;
  503. char *data;
  504. va_list ap;
  505. va_start(ap, fmt);
  506. ret = esl_vasprintf(&data, fmt, ap);
  507. va_end(ap);
  508. if (ret == -1) {
  509. return ESL_FAIL;
  510. }
  511. return esl_event_base_add_header(event, stack, header_name, data);
  512. }
  513. 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)
  514. {
  515. if (data) {
  516. return esl_event_base_add_header(event, stack, header_name, DUP(data));
  517. }
  518. return ESL_FAIL;
  519. }
  520. ESL_DECLARE(esl_status_t) esl_event_set_body(esl_event_t *event, const char *body)
  521. {
  522. esl_safe_free(event->body);
  523. if (body) {
  524. event->body = DUP(body);
  525. }
  526. return ESL_SUCCESS;
  527. }
  528. ESL_DECLARE(esl_status_t) esl_event_add_body(esl_event_t *event, const char *fmt, ...)
  529. {
  530. int ret = 0;
  531. char *data;
  532. va_list ap;
  533. if (fmt) {
  534. va_start(ap, fmt);
  535. ret = esl_vasprintf(&data, fmt, ap);
  536. va_end(ap);
  537. if (ret == -1) {
  538. return ESL_FAIL;
  539. } else {
  540. esl_safe_free(event->body);
  541. event->body = data;
  542. return ESL_SUCCESS;
  543. }
  544. } else {
  545. return ESL_FAIL;
  546. }
  547. }
  548. ESL_DECLARE(void) esl_event_destroy(esl_event_t **event)
  549. {
  550. esl_event_t *ep = *event;
  551. esl_event_header_t *hp, *this;
  552. if (ep) {
  553. for (hp = ep->headers; hp;) {
  554. this = hp;
  555. hp = hp->next;
  556. FREE(this->name);
  557. if (this->idx) {
  558. int i = 0;
  559. for (i = 0; i < this->idx; i++) {
  560. FREE(this->array[i]);
  561. }
  562. FREE(this->array);
  563. }
  564. FREE(this->value);
  565. #ifdef ESL_EVENT_RECYCLE
  566. if (esl_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, this) != ESL_SUCCESS) {
  567. FREE(this);
  568. }
  569. #else
  570. FREE(this);
  571. #endif
  572. }
  573. FREE(ep->body);
  574. FREE(ep->subclass_name);
  575. #ifdef ESL_EVENT_RECYCLE
  576. if (esl_queue_trypush(EVENT_RECYCLE_QUEUE, ep) != ESL_SUCCESS) {
  577. FREE(ep);
  578. }
  579. #else
  580. FREE(ep);
  581. #endif
  582. }
  583. *event = NULL;
  584. }
  585. ESL_DECLARE(void) esl_event_merge(esl_event_t *event, esl_event_t *tomerge)
  586. {
  587. esl_event_header_t *hp;
  588. esl_assert(tomerge && event);
  589. for (hp = tomerge->headers; hp; hp = hp->next) {
  590. if (hp->idx) {
  591. int i;
  592. for(i = 0; i < hp->idx; i++) {
  593. esl_event_add_header_string(event, ESL_STACK_PUSH, hp->name, hp->array[i]);
  594. }
  595. } else {
  596. esl_event_add_header_string(event, ESL_STACK_BOTTOM, hp->name, hp->value);
  597. }
  598. }
  599. }
  600. ESL_DECLARE(esl_status_t) esl_event_dup(esl_event_t **event, esl_event_t *todup)
  601. {
  602. esl_event_header_t *hp;
  603. if (esl_event_create_subclass(event, ESL_EVENT_CLONE, todup->subclass_name) != ESL_SUCCESS) {
  604. return ESL_GENERR;
  605. }
  606. (*event)->event_id = todup->event_id;
  607. (*event)->event_user_data = todup->event_user_data;
  608. (*event)->bind_user_data = todup->bind_user_data;
  609. (*event)->flags = todup->flags;
  610. for (hp = todup->headers; hp; hp = hp->next) {
  611. if (todup->subclass_name && !strcmp(hp->name, "Event-Subclass")) {
  612. continue;
  613. }
  614. if (hp->idx) {
  615. int i;
  616. for (i = 0; i < hp->idx; i++) {
  617. esl_event_add_header_string(*event, ESL_STACK_PUSH, hp->name, hp->array[i]);
  618. }
  619. } else {
  620. esl_event_add_header_string(*event, ESL_STACK_BOTTOM, hp->name, hp->value);
  621. }
  622. }
  623. if (todup->body) {
  624. (*event)->body = DUP(todup->body);
  625. }
  626. (*event)->key = todup->key;
  627. return ESL_SUCCESS;
  628. }
  629. ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, esl_bool_t encode)
  630. {
  631. esl_size_t len = 0;
  632. esl_event_header_t *hp;
  633. esl_size_t llen = 0, dlen = 0, blocksize = 512, encode_len = 1536, new_len = 0;
  634. char *buf;
  635. char *encode_buf = NULL; /* used for url encoding of variables to make sure unsafe things stay out of the serialized copy */
  636. *str = NULL;
  637. dlen = blocksize * 2;
  638. if (!(buf = malloc(dlen))) {
  639. abort();
  640. }
  641. /* go ahead and give ourselves some space to work with, should save a few reallocs */
  642. if (!(encode_buf = malloc(encode_len))) {
  643. abort();
  644. }
  645. /* esl_log_printf(ESL_CHANNEL_LOG, ESL_LOG_INFO, "hit serialized!.\n"); */
  646. for (hp = event->headers; hp; hp = hp->next) {
  647. /*
  648. * grab enough memory to store 3x the string (url encode takes one char and turns it into %XX)
  649. * so we could end up with a string that is 3 times the originals length, unlikely but rather
  650. * be safe than destroy the string, also add one for the null. And try to be smart about using
  651. * the memory, allocate and only reallocate if we need more. This avoids an alloc, free CPU
  652. * destroying loop.
  653. */
  654. if (hp->idx) {
  655. int i;
  656. new_len = 0;
  657. for(i = 0; i < hp->idx; i++) {
  658. new_len += (strlen(hp->array[i]) * 3) + 1;
  659. }
  660. } else {
  661. new_len = (strlen(hp->value) * 3) + 1;
  662. }
  663. if (encode_len < new_len) {
  664. char *tmp;
  665. /* keep track of the size of our allocation */
  666. encode_len = new_len;
  667. if (!(tmp = realloc(encode_buf, encode_len))) {
  668. abort();
  669. }
  670. encode_buf = tmp;
  671. }
  672. /* handle any bad things in the string like newlines : etc that screw up the serialized format */
  673. if (encode) {
  674. esl_url_encode(hp->value, encode_buf, encode_len);
  675. } else {
  676. esl_snprintf(encode_buf, encode_len, "%s", hp->value);
  677. }
  678. llen = strlen(hp->name) + strlen(encode_buf) + 8;
  679. if ((len + llen) > dlen) {
  680. char *m;
  681. char *old = buf;
  682. dlen += (blocksize + (len + llen));
  683. if ((m = realloc(buf, dlen))) {
  684. buf = m;
  685. } else {
  686. buf = old;
  687. abort();
  688. }
  689. }
  690. esl_snprintf(buf + len, dlen - len, "%s: %s\n", hp->name, *encode_buf == '\0' ? "_undef_" : encode_buf);
  691. len = strlen(buf);
  692. }
  693. /* we are done with the memory we used for encoding, give it back */
  694. esl_safe_free(encode_buf);
  695. if (event->body) {
  696. int blen = (int) strlen(event->body);
  697. llen = blen;
  698. if (blen) {
  699. llen += 25;
  700. } else {
  701. llen += 5;
  702. }
  703. if ((len + llen) > dlen) {
  704. char *m;
  705. char *old = buf;
  706. dlen += (blocksize + (len + llen));
  707. if ((m = realloc(buf, dlen))) {
  708. buf = m;
  709. } else {
  710. buf = old;
  711. abort();
  712. }
  713. }
  714. if (blen) {
  715. esl_snprintf(buf + len, dlen - len, "Content-Length: %d\n\n%s", blen, event->body);
  716. } else {
  717. esl_snprintf(buf + len, dlen - len, "\n");
  718. }
  719. } else {
  720. esl_snprintf(buf + len, dlen - len, "\n");
  721. }
  722. *str = buf;
  723. return ESL_SUCCESS;
  724. }
  725. ESL_DECLARE(esl_status_t) esl_event_create_json(esl_event_t **event, const char *json)
  726. {
  727. esl_event_t *new_event;
  728. cJSON *cj, *cjp;
  729. if (!(cj = cJSON_Parse(json))) {
  730. return (esl_status_t) ESL_FALSE;
  731. }
  732. if (esl_event_create(&new_event, ESL_EVENT_CLONE) != ESL_SUCCESS) {
  733. cJSON_Delete(cj);
  734. return (esl_status_t) ESL_FALSE;
  735. }
  736. for (cjp = cj->child; cjp; cjp = cjp->next) {
  737. char *name = cjp->string;
  738. char *value = cjp->valuestring;
  739. if (name && value) {
  740. if (!strcasecmp(name, "_body")) {
  741. esl_event_add_body(new_event, value, ESL_VA_NONE);
  742. } else {
  743. if (!strcasecmp(name, "event-name")) {
  744. esl_event_del_header(new_event, "event-name");
  745. esl_name_event(value, &new_event->event_id);
  746. }
  747. esl_event_add_header_string(new_event, ESL_STACK_BOTTOM, name, value);
  748. }
  749. } else if (name) {
  750. if (cjp->type == cJSON_Array) {
  751. int i, x = cJSON_GetArraySize(cjp);
  752. for (i = 0; i < x; i++) {
  753. cJSON *item = cJSON_GetArrayItem(cjp, i);
  754. if (item != NULL && item->type == cJSON_String && item->valuestring) {
  755. esl_event_add_header_string(new_event, ESL_STACK_PUSH, name, item->valuestring);
  756. }
  757. }
  758. }
  759. }
  760. }
  761. cJSON_Delete(cj);
  762. *event = new_event;
  763. return ESL_SUCCESS;
  764. }
  765. ESL_DECLARE(esl_status_t) esl_event_serialize_json(esl_event_t *event, char **str)
  766. {
  767. esl_event_header_t *hp;
  768. cJSON *cj;
  769. *str = NULL;
  770. cj = cJSON_CreateObject();
  771. for (hp = event->headers; hp; hp = hp->next) {
  772. if (hp->idx) {
  773. cJSON *a = cJSON_CreateArray();
  774. int i;
  775. for(i = 0; i < hp->idx; i++) {
  776. cJSON_AddItemToArray(a, cJSON_CreateString(hp->array[i]));
  777. }
  778. cJSON_AddItemToObject(cj, hp->name, a);
  779. } else {
  780. cJSON_AddItemToObject(cj, hp->name, cJSON_CreateString(hp->value));
  781. }
  782. }
  783. if (event->body) {
  784. int blen = (int) strlen(event->body);
  785. char tmp[25];
  786. esl_snprintf(tmp, sizeof(tmp), "%d", blen);
  787. cJSON_AddItemToObject(cj, "Content-Length", cJSON_CreateString(tmp));
  788. cJSON_AddItemToObject(cj, "_body", cJSON_CreateString(event->body));
  789. }
  790. *str = cJSON_Print(cj);
  791. cJSON_Delete(cj);
  792. return ESL_SUCCESS;
  793. }
  794. /* For Emacs:
  795. * Local Variables:
  796. * mode:c
  797. * indent-tabs-mode:t
  798. * tab-width:4
  799. * c-basic-offset:4
  800. * End:
  801. * For VIM:
  802. * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
  803. */