Bug Summary

File:libs/esl/src/esl.c
Location:line 1461, column 34
Description:Null pointer passed as an argument to a 'nonnull' parameter

Annotated Source Code

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
34
35/* Use select on windows and poll everywhere else.
36 Select is the devil. Especially if you are doing a lot of small socket connections.
37 If your FD number is bigger than 1024 you will silently create memory corruption.
38
39 If you have build errors on your platform because you don't have poll find a way to detect it and #define ESL_USE_SELECT and #undef ESL_USE_POLL
40 All of this will be upgraded to autoheadache eventually.
41*/
42
43/* TBD for win32 figure out how to tell if you have WSAPoll (vista or higher) and use it when available by #defining ESL_USE_WSAPOLL (see below) */
44
45#ifdef _MSC_VER
46#define FD_SETSIZE1024 8192
47#define ESL_USE_SELECT
48#else
49#define ESL_USE_POLL
50#endif
51
52#include <esl.h>
53#ifndef WIN32
54#define closesocket(x)shutdown(x, 2); close(x) shutdown(x, 2); close(x)
55#include <fcntl.h>
56#include <errno(*__errno_location ()).h>
57#else
58#pragma warning (disable:6386)
59/* These warnings need to be ignored warning in sdk header */
60#include <Ws2tcpip.h>
61#include <windows.h>
62#include <errno(*__errno_location ()).h>
63#ifndef errno(*__errno_location ())
64#define errno(*__errno_location ()) WSAGetLastError()
65#endif
66#ifndef EINTR4
67#define EINTR4 WSAEINTR
68#endif
69#pragma warning (default:6386)
70#endif
71
72#ifdef ESL_USE_POLL
73#include <poll.h>
74#endif
75
76#ifndef ESL_MIN
77#define ESL_MIN(x,y)((x) < (y) ? (x) : (y)) ((x) < (y) ? (x) : (y))
78#endif
79#ifndef ESL_MAX
80#define ESL_MAX(x,y)((x) > (y) ? (x) : (y)) ((x) > (y) ? (x) : (y))
81#endif
82#ifndef ESL_CLAMP
83#define ESL_CLAMP(min,max,val)(((max) < (((val) > (min) ? (val) : (min))) ? (max) : (
((val) > (min) ? (val) : (min)))))
(ESL_MIN(max,ESL_MAX(val,min))((max) < (((val) > (min) ? (val) : (min))) ? (max) : ((
(val) > (min) ? (val) : (min))))
)
84#endif
85
86
87/* Written by Marc Espie, public domain */
88#define ESL_CTYPE_NUM_CHARS256 256
89
90const short _esl_C_toupper_[1 + ESL_CTYPE_NUM_CHARS256] = {
91 EOF(-1),
92 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
93 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
94 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
95 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
96 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
97 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
98 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
99 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
100 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
101 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
102 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
103 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
104 0x60, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
105 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
106 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
107 'X', 'Y', 'Z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
108 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
109 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
110 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
111 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
112 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
113 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
114 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
115 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
116 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
117 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
118 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
119 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
120 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
121 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
122 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
123 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
124};
125
126const short *_esl_toupper_tab_ = _esl_C_toupper_;
127
128ESL_DECLARE(int)int esl_toupper(int c)
129{
130 if ((unsigned int)c > 255)
131 return(c);
132 if (c < -1)
133 return EOF(-1);
134 return((_esl_toupper_tab_ + 1)[c]);
135}
136
137const short _esl_C_tolower_[1 + ESL_CTYPE_NUM_CHARS256] = {
138 EOF(-1),
139 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
140 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
141 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
142 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
143 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
144 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
145 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
146 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
147 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
148 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
149 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
150 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
151 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
152 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
153 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
154 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
155 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
156 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
157 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
158 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
159 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
160 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
161 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
162 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
163 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
164 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
165 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
166 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
167 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
168 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
169 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
170 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
171};
172
173const short *_esl_tolower_tab_ = _esl_C_tolower_;
174
175ESL_DECLARE(int)int esl_tolower(int c)
176{
177 if ((unsigned int)c > 255)
178 return(c);
179 if (c < -1)
180 return EOF(-1);
181 return((_esl_tolower_tab_ + 1)[c]);
182}
183
184ESL_DECLARE(const char *)const char *esl_stristr(const char *instr, const char *str)
185{
186/*
187** Rev History: 16/07/97 Greg Thayer Optimized
188** 07/04/95 Bob Stout ANSI-fy
189** 02/03/94 Fred Cole Original
190** 09/01/03 Bob Stout Bug fix (lines 40-41) per Fred Bulback
191**
192** Hereby donated to public domain.
193*/
194 const char *pptr, *sptr, *start;
195
196 if (!str || !instr)
197 return NULL((void*)0);
198
199 for (start = str; *start; start++) {
200 /* find start of pattern in string */
201 for (; ((*start) && (esl_toupper(*start) != esl_toupper(*instr))); start++);
202
203 if (!*start)
204 return NULL((void*)0);
205
206 pptr = instr;
207 sptr = start;
208
209 while (esl_toupper(*sptr) == esl_toupper(*pptr)) {
210 sptr++;
211 pptr++;
212
213 /* if end of pattern then pattern was found */
214 if (!*pptr)
215 return (start);
216
217 if (!*sptr)
218 return NULL((void*)0);
219 }
220 }
221 return NULL((void*)0);
222}
223
224#ifdef WIN32
225#ifndef vsnprintf
226#define vsnprintf _vsnprintf
227#endif
228#endif
229
230
231int vasprintf(char **ret, const char *format, va_list ap);
232
233ESL_DECLARE(int)int esl_vasprintf(char **ret, const char *fmt, va_list ap)
234{
235#if !defined(WIN32) && !defined(__sun)
236 return vasprintf(ret, fmt, ap);
237#else
238 char *buf;
239 int len;
240 size_t buflen;
241 va_list ap2;
242 char *tmp = NULL((void*)0);
243
244#ifdef _MSC_VER
245#if _MSC_VER >= 1500
246 /* hack for incorrect assumption in msvc header files for code analysis */
247 __analysis_assume(tmp);
248#endif
249 ap2 = ap;
250#else
251 va_copy(ap2, ap)__builtin_va_copy(ap2, ap);
252#endif
253
254 len = vsnprintf(tmp, 0, fmt, ap2);
255
256 if (len > 0 && (buf = malloc((buflen = (size_t) (len + 1)))) != NULL((void*)0)) {
257 len = vsnprintf(buf, buflen, fmt, ap);
258 *ret = buf;
259 } else {
260 *ret = NULL((void*)0);
261 len = -1;
262 }
263
264 va_end(ap2)__builtin_va_end(ap2);
265 return len;
266#endif
267}
268
269
270
271
272ESL_DECLARE(int)int esl_snprintf(char *buffer, size_t count, const char *fmt, ...)
273{
274 va_list ap;
275 int ret;
276
277 va_start(ap, fmt)__builtin_va_start(ap, fmt);
278 ret = vsnprintf(buffer, count-1, fmt, ap);
279 if (ret < 0)
280 buffer[count-1] = '\0';
281 va_end(ap)__builtin_va_end(ap);
282 return ret;
283}
284
285static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
286{
287 if (file && func && line && level && fmt) {
288 return;
289 }
290 return;
291}
292
293
294static const char *LEVEL_NAMES[] = {
295 "EMERG",
296 "ALERT",
297 "CRIT",
298 "ERROR",
299 "WARNING",
300 "NOTICE",
301 "INFO",
302 "DEBUG",
303 NULL((void*)0)
304};
305
306static int esl_log_level = 7;
307
308static const char *cut_path(const char *in)
309{
310 const char *p, *ret = in;
311 char delims[] = "/\\";
312 char *i;
313
314 for (i = delims; *i; i++) {
315 p = in;
316 while ((p = strchr(p, *i)(__extension__ (__builtin_constant_p (*i) && !__builtin_constant_p
(p) && (*i) == '\0' ? (char *) __rawmemchr (p, *i) :
__builtin_strchr (p, *i)))
) != 0) {
317 ret = ++p;
318 }
319 }
320 return ret;
321}
322
323
324static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
325{
326 const char *fp;
327 char *data;
328 va_list ap;
329 int ret;
330
331 if (level < 0 || level > 7) {
332 level = 7;
333 }
334 if (level > esl_log_level) {
335 return;
336 }
337
338 fp = cut_path(file);
339
340 va_start(ap, fmt)__builtin_va_start(ap, fmt);
341
342 ret = esl_vasprintf(&data, fmt, ap);
343
344 if (ret != -1) {
345 fprintf(stderrstderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], fp, line, func, data);
346 free(data);
347 }
348
349 va_end(ap)__builtin_va_end(ap);
350
351}
352
353esl_logger_t esl_log = null_logger;
354
355ESL_DECLARE(void)void esl_global_set_logger(esl_logger_t logger)
356{
357 if (logger) {
358 esl_log = logger;
359 } else {
360 esl_log = null_logger;
361 }
362}
363
364ESL_DECLARE(void)void esl_global_set_default_logger(int level)
365{
366 if (level < 0 || level > 7) {
367 level = 7;
368 }
369
370 esl_log = default_logger;
371 esl_log_level = level;
372}
373
374ESL_DECLARE(size_t)size_t esl_url_encode(const char *url, char *buf, size_t len)
375{
376 const char *p;
377 size_t x = 0;
378 const char urlunsafe[] = "\r\n \"#%&+:;<=>?@[\\]^`{|}";
379 const char hex[] = "0123456789ABCDEF";
380
381 if (!buf) {
382 return 0;
383 }
384
385 if (!url) {
386 return 0;
387 }
388
389 len--;
390
391 for (p = url; *p; p++) {
392 if (x >= len) {
393 break;
394 }
395 if (*p < ' ' || *p > '~' || strchr(urlunsafe, *p)(__extension__ (__builtin_constant_p (*p) && !__builtin_constant_p
(urlunsafe) && (*p) == '\0' ? (char *) __rawmemchr (
urlunsafe, *p) : __builtin_strchr (urlunsafe, *p)))
) {
396 if ((x + 3) >= len) {
397 break;
398 }
399 buf[x++] = '%';
400 buf[x++] = hex[*p >> 4];
401 buf[x++] = hex[*p & 0x0f];
402 } else {
403 buf[x++] = *p;
404 }
405 }
406 buf[x] = '\0';
407
408 return x;
409}
410
411ESL_DECLARE(char *)char *esl_url_decode(char *s)
412{
413 char *o;
414 unsigned int tmp;
415
416 for (o = s; *s; s++, o++) {
417 if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) {
418 *o = (char) tmp;
419 s += 2;
420 } else {
421 *o = *s;
422 }
423 }
424 *o = '\0';
425 return s;
426}
427
428static int sock_setup(esl_handle_t *handle)
429{
430
431 if (handle->sock == ESL_SOCK_INVALID-1) {
432 return ESL_FAIL;
433 }
434
435#ifdef WIN32
436 {
437 BOOL bOptVal = TRUE;
438 int bOptLen = sizeof(BOOL);
439 setsockopt(handle->sock, IPPROTO_TCPIPPROTO_TCP, TCP_NODELAY1, (const char *)&bOptVal, bOptLen);
440 }
441#else
442 {
443 int x = 1;
444 setsockopt(handle->sock, IPPROTO_TCPIPPROTO_TCP, TCP_NODELAY1, &x, sizeof(x));
445 }
446#endif
447
448 return ESL_SUCCESS;
449}
450
451ESL_DECLARE(esl_status_t)esl_status_t esl_attach_handle(esl_handle_t *handle, esl_socket_t socket, struct sockaddr_in *addr)
452{
453
454 if (!handle || socket == ESL_SOCK_INVALID-1) {
455 return ESL_FAIL;
456 }
457
458 handle->sock = socket;
459
460 if (addr) {
461 handle->addr = *addr;
462 }
463
464 if (sock_setup(handle) != ESL_SUCCESS) {
465 return ESL_FAIL;
466 }
467
468 if (!handle->mutex) {
469 esl_mutex_create(&handle->mutex);
470 }
471
472 if (!handle->packet_buf) {
473 esl_buffer_create(&handle->packet_buf, BUF_CHUNK65536 * 50, BUF_START65536 * 100, 0);
474 }
475
476 handle->connected = 1;
477
478 esl_send_recv(handle, "connect\n\n")esl_send_recv_timed(handle, "connect\n\n", 0);
479
480 if (handle->last_sr_event) {
481 handle->info_event = handle->last_sr_event;
482 handle->last_sr_event = NULL((void*)0);
483 return ESL_SUCCESS;
484 }
485
486 esl_disconnect(handle);
487
488 return ESL_FAIL;
489}
490
491ESL_DECLARE(esl_status_t)esl_status_t esl_sendevent(esl_handle_t *handle, esl_event_t *event)
492{
493 char *txt;
494 char *event_buf = NULL((void*)0);
495 esl_status_t status = ESL_FAIL;
496 size_t len = 0;
497
498 if (!handle->connected || !event) {
499 return ESL_FAIL;
500 }
501
502 esl_event_serialize(event, &txt, ESL_FALSE);
503
504 esl_log(ESL_LOG_DEBUG"libs/esl/src/esl.c", (const char *)__func__, 504, 7, "SEND EVENT\n%s\n", txt);
505
506 len = strlen(txt) + 100;
507 event_buf = malloc(len);
508 assert(event_buf)((event_buf) ? (void) (0) : __assert_fail ("event_buf", "libs/esl/src/esl.c"
, 508, __PRETTY_FUNCTION__))
;
509
510 if (!event_buf) {
511 return ESL_FAIL;
512 }
513
514 memset(event_buf, 0, len);
515
516 snprintf(event_buf, len, "sendevent %s\n%s", esl_event_name(event->event_id), txt);
517
518 status = esl_send_recv(handle, event_buf)esl_send_recv_timed(handle, event_buf, 0);
519
520 free(txt);
521 free(event_buf);
522
523 return status;
524
525}
526
527ESL_DECLARE(esl_status_t)esl_status_t esl_execute(esl_handle_t *handle, const char *app, const char *arg, const char *uuid)
528{
529 char cmd_buf[128] = "sendmsg";
530 char app_buf[512] = "";
531 char arg_buf[4096] = "";
532 const char *el_buf = "event-lock: true\n";
533 const char *bl_buf = "async: true\n";
534 char send_buf[5120] = "";
535
536 if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID-1) {
537 return ESL_FAIL;
538 }
539
540 if (uuid) {
541 snprintf(cmd_buf, sizeof(cmd_buf), "sendmsg %s", uuid);
542 }
543
544 if (app) {
545 snprintf(app_buf, sizeof(app_buf), "execute-app-name: %s\n", app);
546 }
547
548 if (arg) {
549 snprintf(arg_buf, sizeof(arg_buf), "execute-app-arg: %s\n", arg);
550 }
551
552 snprintf(send_buf, sizeof(send_buf), "%s\ncall-command: execute\n%s%s%s%s\n",
553 cmd_buf, app_buf, arg_buf, handle->event_lock ? el_buf : "", handle->async_execute ? bl_buf : "");
554
555 return esl_send_recv(handle, send_buf)esl_send_recv_timed(handle, send_buf, 0);
556}
557
558
559ESL_DECLARE(esl_status_t)esl_status_t esl_sendmsg(esl_handle_t *handle, esl_event_t *event, const char *uuid)
560{
561 char *cmd_buf = NULL((void*)0);
562 char *txt;
563 size_t len = 0;
564 esl_status_t status = ESL_FAIL;
565
566 if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID-1) {
567 return ESL_FAIL;
568 }
569
570 esl_event_serialize(event, &txt, ESL_FALSE);
571 len = strlen(txt) + 100;
572 cmd_buf = malloc(len);
573 assert(cmd_buf)((cmd_buf) ? (void) (0) : __assert_fail ("cmd_buf", "libs/esl/src/esl.c"
, 573, __PRETTY_FUNCTION__))
;
574
575 if (!cmd_buf) {
576 return ESL_FAIL;
577 }
578
579 memset(cmd_buf, 0, len);
580
581 if (uuid) {
582 snprintf(cmd_buf, len, "sendmsg %s\n%s", uuid, txt);
583 } else {
584 snprintf(cmd_buf, len, "sendmsg\n%s", txt);
585 }
586
587 esl_log(ESL_LOG_DEBUG"libs/esl/src/esl.c", (const char *)__func__, 587, 7, "%s%s\n", cmd_buf, txt);
588
589 status = esl_send_recv(handle, cmd_buf)esl_send_recv_timed(handle, cmd_buf, 0);
590
591 free(txt);
592 free(cmd_buf);
593
594 return status;
595}
596
597
598ESL_DECLARE(esl_status_t)esl_status_t esl_filter(esl_handle_t *handle, const char *header, const char *value)
599{
600 char send_buf[1024] = "";
601
602 if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID-1) {
603 return ESL_FAIL;
604 }
605
606 snprintf(send_buf, sizeof(send_buf), "filter %s %s\n\n", header, value);
607
608 return esl_send_recv(handle, send_buf)esl_send_recv_timed(handle, send_buf, 0);
609}
610
611
612ESL_DECLARE(esl_status_t)esl_status_t esl_events(esl_handle_t *handle, esl_event_type_t etype, const char *value)
613{
614 char send_buf[1024] = "";
615 const char *type = "plain";
616
617 if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID-1) {
618 return ESL_FAIL;
619 }
620
621 if (etype == ESL_EVENT_TYPE_XML) {
622 type = "xml";
623 } else if (etype == ESL_EVENT_TYPE_JSON) {
624 type = "json";
625 }
626
627 snprintf(send_buf, sizeof(send_buf), "event %s %s\n\n", type, value);
628
629 return esl_send_recv(handle, send_buf)esl_send_recv_timed(handle, send_buf, 0);
630}
631
632static int esl_socket_reuseaddr(esl_socket_t socket)
633{
634#ifdef WIN32
635 BOOL reuse_addr = TRUE;
636 return setsockopt(socket, SOL_SOCKET1, SO_REUSEADDR2, (char *)&reuse_addr, sizeof(reuse_addr));
637#else
638 int reuse_addr = 1;
639 return setsockopt(socket, SOL_SOCKET1, SO_REUSEADDR2, &reuse_addr, sizeof(reuse_addr));
640#endif
641}
642
643struct thread_handler {
644 esl_listen_callback_t callback;
645 esl_socket_t server_sock;
646 esl_socket_t client_sock;
647 struct sockaddr_in addr;
648 void *user_data;
649};
650
651static void *client_thread(esl_thread_t *me, void *obj)
652{
653 struct thread_handler *handler = (struct thread_handler *) obj;
654
655 handler->callback(handler->server_sock, handler->client_sock, &handler->addr, handler->user_data);
656 free(handler);
657
658 return NULL((void*)0);
659
660}
661
662static int prepare_sock(esl_socket_t sock)
663{
664 int r = 0;
665
666#ifdef WIN32
667 u_long arg = 1;
668 if (ioctlsocket(sock, FIONBIO0x5421, &arg) == SOCKET_ERROR) {
669 r = -1;
670 }
671#else
672 int fd_flags = fcntl(sock, F_GETFL3, 0);
673 if (fcntl(sock, F_SETFL4, fd_flags | O_NONBLOCK04000)) {
674 r = -1;
675 }
676#endif
677
678 return r;
679
680}
681
682
683ESL_DECLARE(esl_status_t)esl_status_t esl_listen(const char *host, esl_port_t port, esl_listen_callback_t callback, void *user_data, esl_socket_t *server_sockP)
684{
685 esl_socket_t server_sock = ESL_SOCK_INVALID-1;
686 struct sockaddr_in addr;
687 esl_status_t status = ESL_SUCCESS;
688
689
690 if ((server_sock = socket(PF_INET2, SOCK_STREAMSOCK_STREAM, IPPROTO_TCPIPPROTO_TCP)) < 0) {
691 return ESL_FAIL;
692 }
693
694 if (server_sockP) {
695 *server_sockP = server_sock;
696 }
697
698
699 esl_socket_reuseaddr(server_sock);
700
701 memset(&addr, 0, sizeof(addr));
702 addr.sin_family = AF_INET2;
703 addr.sin_addr.s_addr = htonl(INADDR_ANY)(__extension__ ({ unsigned int __v, __x = (((in_addr_t) 0x00000000
)); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000
) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x
) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) <<
24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v
; }))
;
704 addr.sin_port = htons(port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (port); if (__builtin_constant_p (__x)) __v = ((unsigned
short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff
) << 8))); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0"
(__x) : "cc"); __v; }))
;
705
706 if (bind(server_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
707 status = ESL_FAIL;
708 goto end;
709 }
710
711 if (listen(server_sock, 10000) < 0) {
712 status = ESL_FAIL;
713 goto end;
714 }
715
716 for (;;) {
717 int client_sock;
718 struct sockaddr_in echoClntAddr;
719#ifdef WIN32
720 int clntLen;
721#else
722 unsigned int clntLen;
723#endif
724
725 clntLen = sizeof(echoClntAddr);
726
727 if ((client_sock = accept(server_sock, (struct sockaddr *) &echoClntAddr, &clntLen)) == ESL_SOCK_INVALID-1 && errno(*__errno_location ()) != EINTR4) {
728 status = ESL_FAIL;
729 goto end;
730 }
731 prepare_sock(client_sock);
732 callback(server_sock, client_sock, &echoClntAddr, user_data);
733 }
734
735 end:
736
737 if (server_sock != ESL_SOCK_INVALID-1) {
738 closesocket(server_sock)shutdown(server_sock, 2); close(server_sock);
739 }
740
741 return status;
742
743}
744
745ESL_DECLARE(esl_status_t)esl_status_t esl_listen_threaded(const char *host, esl_port_t port, esl_listen_callback_t callback, void *user_data, int max)
746{
747 esl_socket_t server_sock = ESL_SOCK_INVALID-1;
748 struct sockaddr_in addr;
749 esl_status_t status = ESL_SUCCESS;
750 struct thread_handler *handler = NULL((void*)0);
751
752 if ((server_sock = socket(PF_INET2, SOCK_STREAMSOCK_STREAM, IPPROTO_TCPIPPROTO_TCP)) < 0) {
753 return ESL_FAIL;
754 }
755
756 esl_socket_reuseaddr(server_sock);
757
758 memset(&addr, 0, sizeof(addr));
759 addr.sin_family = AF_INET2;
760 addr.sin_addr.s_addr = htonl(INADDR_ANY)(__extension__ ({ unsigned int __v, __x = (((in_addr_t) 0x00000000
)); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000
) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x
) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) <<
24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v
; }))
;
761 addr.sin_port = htons(port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (port); if (__builtin_constant_p (__x)) __v = ((unsigned
short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff
) << 8))); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0"
(__x) : "cc"); __v; }))
;
762
763 if (bind(server_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
764 status = ESL_FAIL;
765 goto end;
766 }
767
768 if (listen(server_sock, max) < 0) {
769 status = ESL_FAIL;
770 goto end;
771 }
772
773 for (;;) {
774 int client_sock;
775 struct sockaddr_in echoClntAddr;
776#ifdef WIN32
777 int clntLen;
778#else
779 unsigned int clntLen;
780#endif
781
782 clntLen = sizeof(echoClntAddr);
783
784 if ((client_sock = accept(server_sock, (struct sockaddr *) &echoClntAddr, &clntLen)) == ESL_SOCK_INVALID-1 && errno(*__errno_location ()) != EINTR4) {
785 status = ESL_FAIL;
786 goto end;
787 }
788
789 prepare_sock(client_sock);
790
791 handler = malloc(sizeof(*handler));
792 esl_assert(handler)((handler) ? (void) (0) : __assert_fail ("handler", "libs/esl/src/esl.c"
, 792, __PRETTY_FUNCTION__))
;
793
794 memset(handler, 0, sizeof(*handler));
795 handler->callback = callback;
796 handler->server_sock = server_sock;
797 handler->client_sock = client_sock;
798 handler->addr = echoClntAddr;
799 handler->user_data = user_data;
800 esl_thread_create_detached(client_thread, handler);
801 }
802
803 end:
804
805 if (server_sock != ESL_SOCK_INVALID-1) {
806 closesocket(server_sock)shutdown(server_sock, 2); close(server_sock);
807 }
808
809 return status;
810
811}
812
813
814/* USE WSAPoll on vista or higher */
815#ifdef ESL_USE_WSAPOLL
816ESL_DECLARE(int)int esl_wait_sock(esl_socket_t sock, uint32_t ms, esl_poll_t flags)
817{
818}
819#endif
820
821
822#ifdef ESL_USE_SELECT
823#ifdef WIN32
824#pragma warning( push )
825#pragma warning( disable : 6262 ) /* warning C6262: Function uses '98348' bytes of stack: exceeds /analyze:stacksize'16384'. Consider moving some data to heap */
826#endif
827ESL_DECLARE(int)int esl_wait_sock(esl_socket_t sock, uint32_t ms, esl_poll_t flags)
828{
829 int s = 0, r = 0;
830 fd_set rfds;
831 fd_set wfds;
832 fd_set efds;
833 struct timeval tv;
834
835 if (sock == ESL_SOCK_INVALID-1) {
836 return ESL_SOCK_INVALID-1;
837 }
838
839 FD_ZERO(&rfds)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq"
: "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) /
sizeof (__fd_mask)), "1" (&((&rfds)->fds_bits)[0]
) : "memory"); } while (0)
;
840 FD_ZERO(&wfds)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq"
: "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) /
sizeof (__fd_mask)), "1" (&((&wfds)->fds_bits)[0]
) : "memory"); } while (0)
;
841 FD_ZERO(&efds)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq"
: "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) /
sizeof (__fd_mask)), "1" (&((&efds)->fds_bits)[0]
) : "memory"); } while (0)
;
842
843#ifndef WIN32
844 /* Wouldn't you rather know?? */
845 assert(sock <= FD_SETSIZE)((sock <= 1024) ? (void) (0) : __assert_fail ("sock <= 1024"
, "libs/esl/src/esl.c", 845, __PRETTY_FUNCTION__))
;
846#endif
847
848 if ((flags & ESL_POLL_READ)) {
849
850#ifdef WIN32
851#pragma warning( push )
852#pragma warning( disable : 4127 )
853 FD_SET(sock, &rfds)((void) (((&rfds)->fds_bits)[((sock) / (8 * (int) sizeof
(__fd_mask)))] |= ((__fd_mask) 1 << ((sock) % (8 * (int
) sizeof (__fd_mask))))))
;
854#pragma warning( pop )
855#else
856 FD_SET(sock, &rfds)((void) (((&rfds)->fds_bits)[((sock) / (8 * (int) sizeof
(__fd_mask)))] |= ((__fd_mask) 1 << ((sock) % (8 * (int
) sizeof (__fd_mask))))))
;
857#endif
858 }
859
860 if ((flags & ESL_POLL_WRITE)) {
861
862#ifdef WIN32
863#pragma warning( push )
864#pragma warning( disable : 4127 )
865 FD_SET(sock, &wfds)((void) (((&wfds)->fds_bits)[((sock) / (8 * (int) sizeof
(__fd_mask)))] |= ((__fd_mask) 1 << ((sock) % (8 * (int
) sizeof (__fd_mask))))))
;
866#pragma warning( pop )
867#else
868 FD_SET(sock, &wfds)((void) (((&wfds)->fds_bits)[((sock) / (8 * (int) sizeof
(__fd_mask)))] |= ((__fd_mask) 1 << ((sock) % (8 * (int
) sizeof (__fd_mask))))))
;
869#endif
870 }
871
872 if ((flags & ESL_POLL_ERROR)) {
873
874#ifdef WIN32
875#pragma warning( push )
876#pragma warning( disable : 4127 )
877 FD_SET(sock, &efds)((void) (((&efds)->fds_bits)[((sock) / (8 * (int) sizeof
(__fd_mask)))] |= ((__fd_mask) 1 << ((sock) % (8 * (int
) sizeof (__fd_mask))))))
;
878#pragma warning( pop )
879#else
880 FD_SET(sock, &efds)((void) (((&efds)->fds_bits)[((sock) / (8 * (int) sizeof
(__fd_mask)))] |= ((__fd_mask) 1 << ((sock) % (8 * (int
) sizeof (__fd_mask))))))
;
881#endif
882 }
883
884 tv.tv_sec = ms / 1000;
885 tv.tv_usec = (ms % 1000) * ms;
886
887 s = select(sock + 1, (flags & ESL_POLL_READ) ? &rfds : NULL((void*)0), (flags & ESL_POLL_WRITE) ? &wfds : NULL((void*)0), (flags & ESL_POLL_ERROR) ? &efds : NULL((void*)0), &tv);
888
889 if (s < 0) {
890 r = s;
891 } else if (s > 0) {
892 if ((flags & ESL_POLL_READ) && FD_ISSET(sock, &rfds)((((&rfds)->fds_bits)[((sock) / (8 * (int) sizeof (__fd_mask
)))] & ((__fd_mask) 1 << ((sock) % (8 * (int) sizeof
(__fd_mask))))) != 0)
) {
893 r |= ESL_POLL_READ;
894 }
895
896 if ((flags & ESL_POLL_WRITE) && FD_ISSET(sock, &wfds)((((&wfds)->fds_bits)[((sock) / (8 * (int) sizeof (__fd_mask
)))] & ((__fd_mask) 1 << ((sock) % (8 * (int) sizeof
(__fd_mask))))) != 0)
) {
897 r |= ESL_POLL_WRITE;
898 }
899
900 if ((flags & ESL_POLL_ERROR) && FD_ISSET(sock, &efds)((((&efds)->fds_bits)[((sock) / (8 * (int) sizeof (__fd_mask
)))] & ((__fd_mask) 1 << ((sock) % (8 * (int) sizeof
(__fd_mask))))) != 0)
) {
901 r |= ESL_POLL_ERROR;
902 }
903 }
904
905 return r;
906
907}
908#ifdef WIN32
909#pragma warning( pop )
910#endif
911#endif
912
913#ifdef ESL_USE_POLL
914ESL_DECLARE(int)int esl_wait_sock(esl_socket_t sock, uint32_t ms, esl_poll_t flags)
915{
916 struct pollfd pfds[2] = { { 0 } };
917 int s = 0, r = 0;
918
919 if (sock == ESL_SOCK_INVALID-1) {
920 return ESL_SOCK_INVALID-1;
921 }
922
923 pfds[0].fd = sock;
924
925 if ((flags & ESL_POLL_READ)) {
926 pfds[0].events |= POLLIN0x001;
927 }
928
929 if ((flags & ESL_POLL_WRITE)) {
930 pfds[0].events |= POLLOUT0x004;
931 }
932
933 if ((flags & ESL_POLL_ERROR)) {
934 pfds[0].events |= POLLERR0x008;
935 }
936
937 s = poll(pfds, 1, ms);
938
939 if (s < 0) {
940 r = s;
941 } else if (s > 0) {
942 if ((pfds[0].revents & POLLIN0x001)) {
943 r |= ESL_POLL_READ;
944 }
945 if ((pfds[0].revents & POLLOUT0x004)) {
946 r |= ESL_POLL_WRITE;
947 }
948 if ((pfds[0].revents & POLLERR0x008)) {
949 r |= ESL_POLL_ERROR;
950 }
951 }
952
953 return r;
954
955}
956#endif
957
958
959ESL_DECLARE(esl_status_t)esl_status_t esl_connect_timeout(esl_handle_t *handle, const char *host, esl_port_t port, const char *user, const char *password, uint32_t timeout)
960{
961 char sendbuf[256];
962 int rval = 0;
963 const char *hval;
964 struct addrinfo hints = { 0 }, *result;
965 struct sockaddr_in *sockaddr_in;
966 struct sockaddr_in6 *sockaddr_in6;
967 socklen_t socklen;
968#ifndef WIN32
969 int fd_flags = 0;
970#else
971 WORD wVersionRequested = MAKEWORD(2, 0);
972 WSADATA wsaData;
973 int err = WSAStartup(wVersionRequested, &wsaData);
974 if (err != 0) {
975 snprintf(handle->err, sizeof(handle->err), "WSAStartup Error");
976 goto fail;
977 }
978
979#endif
980
981 if (!handle->mutex) {
982 esl_mutex_create(&handle->mutex);
983 }
984
985 if (!handle->packet_buf) {
986 esl_buffer_create(&handle->packet_buf, BUF_CHUNK65536 * 50, BUF_START65536 * 100, 0);
987 }
988
989 hints.ai_socktype = SOCK_STREAMSOCK_STREAM;
990
991 if (getaddrinfo(host, NULL((void*)0), &hints, &result)) {
992 strncpy(handle->err, "Cannot resolve host", sizeof(handle->err))__builtin_strncpy (handle->err, "Cannot resolve host", sizeof
(handle->err))
;
993 goto fail;
994 }
995
996 memcpy(&handle->sockaddr, result->ai_addr, result->ai_addrlen);
997 switch(handle->sockaddr.ss_family) {
998 case AF_INET2:
999 sockaddr_in = (struct sockaddr_in*)&(handle->sockaddr);
1000 sockaddr_in->sin_port = htons(port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (port); if (__builtin_constant_p (__x)) __v = ((unsigned
short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff
) << 8))); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0"
(__x) : "cc"); __v; }))
;
1001 socklen = sizeof(struct sockaddr_in);
1002 break;
1003 case AF_INET610:
1004 sockaddr_in6 = (struct sockaddr_in6*)&(handle->sockaddr);
1005 sockaddr_in6->sin6_port = htons(port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (port); if (__builtin_constant_p (__x)) __v = ((unsigned
short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff
) << 8))); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0"
(__x) : "cc"); __v; }))
;
1006 socklen = sizeof(struct sockaddr_in6);
1007 break;
1008 default:
1009 strncpy(handle->err, "Host resolves to unsupported address family", sizeof(handle->err))__builtin_strncpy (handle->err, "Host resolves to unsupported address family"
, sizeof(handle->err))
;
1010 goto fail;
1011 }
1012 freeaddrinfo(result);
1013
1014 handle->sock = socket(handle->sockaddr.ss_family, SOCK_STREAMSOCK_STREAM, IPPROTO_TCPIPPROTO_TCP);
1015
1016 if (handle->sock == ESL_SOCK_INVALID-1) {
1017 snprintf(handle->err, sizeof(handle->err), "Socket Error");
1018 goto fail;
1019 }
1020
1021 if (timeout) {
1022#ifdef WIN32
1023 u_long arg = 1;
1024 if (ioctlsocket(handle->sock, FIONBIO0x5421, &arg) == SOCKET_ERROR) {
1025 snprintf(handle->err, sizeof(handle->err), "Socket Connection Error");
1026 goto fail;
1027 }
1028#else
1029 fd_flags = fcntl(handle->sock, F_GETFL3, 0);
1030 if (fcntl(handle->sock, F_SETFL4, fd_flags | O_NONBLOCK04000)) {
1031 snprintf(handle->err, sizeof(handle->err), "Socket Connection Error");
1032 goto fail;
1033 }
1034#endif
1035 }
1036
1037 rval = connect(handle->sock, (struct sockaddr*)&handle->sockaddr, socklen);
1038
1039 if (timeout) {
1040 int r;
1041
1042
1043 r = esl_wait_sock(handle->sock, timeout, ESL_POLL_WRITE);
1044
1045 if (r <= 0) {
1046 snprintf(handle->err, sizeof(handle->err), "Connection timed out");
1047 goto fail;
1048 }
1049
1050 if (!(r & ESL_POLL_WRITE)) {
1051 snprintf(handle->err, sizeof(handle->err), "Connection timed out");
1052 goto fail;
1053 }
1054
1055#ifdef WIN32
1056 {
1057 u_long arg = 0;
1058 if (ioctlsocket(handle->sock, FIONBIO0x5421, &arg) == SOCKET_ERROR) {
1059 snprintf(handle->err, sizeof(handle->err), "Socket Connection Error");
1060 goto fail;
1061 }
1062 }
1063#else
1064 fcntl(handle->sock, F_SETFL4, fd_flags);
1065#endif
1066 rval = 0;
1067 }
1068
1069 result = NULL((void*)0);
1070
1071 if (rval) {
1072 snprintf(handle->err, sizeof(handle->err), "Socket Connection Error");
1073 goto fail;
1074 }
1075
1076 sock_setup(handle);
1077
1078 handle->connected = 1;
1079
1080 if (esl_recv_timed(handle, timeout)esl_recv_event_timed(handle, timeout, 0, ((void*)0))) {
1081 snprintf(handle->err, sizeof(handle->err), "Connection Error");
1082 goto fail;
1083 }
1084
1085 hval = esl_event_get_header(handle->last_event, "content-type")esl_event_get_header_idx(handle->last_event, "content-type"
, -1)
;
1086
1087 if (esl_safe_strcasecmp(hval, "auth/request")) {
1088 snprintf(handle->err, sizeof(handle->err), "Connection Error");
1089 goto fail;
1090 }
1091
1092 if (esl_strlen_zero(user)(!user || *(user) == '\0')) {
1093 snprintf(sendbuf, sizeof(sendbuf), "auth %s\n\n", password);
1094 } else {
1095 snprintf(sendbuf, sizeof(sendbuf), "userauth %s:%s\n\n", user, password);
1096 }
1097
1098 esl_send(handle, sendbuf);
1099
1100
1101 if (esl_recv_timed(handle, timeout)esl_recv_event_timed(handle, timeout, 0, ((void*)0))) {
1102 snprintf(handle->err, sizeof(handle->err), "Authentication Error");
1103 goto fail;
1104 }
1105
1106
1107 hval = esl_event_get_header(handle->last_event, "reply-text")esl_event_get_header_idx(handle->last_event, "reply-text",
-1)
;
1108
1109 if (esl_safe_strcasecmp(hval, "+OK accepted")) {
1110 snprintf(handle->err, sizeof(handle->err), "Authentication Error");
1111 goto fail;
1112 }
1113
1114 return ESL_SUCCESS;
1115
1116 fail:
1117
1118 handle->connected = 0;
1119
1120 return ESL_FAIL;
1121}
1122
1123ESL_DECLARE(esl_status_t)esl_status_t esl_disconnect(esl_handle_t *handle)
1124{
1125 esl_mutex_t *mutex = handle->mutex;
1126 esl_status_t status = ESL_FAIL;
1127 esl_event_t *ep;
1128
1129 if (handle->destroyed) {
1130 return ESL_FAIL;
1131 }
1132
1133 if (handle->sock != ESL_SOCK_INVALID-1) {
1134 closesocket(handle->sock)shutdown(handle->sock, 2); close(handle->sock);
1135 handle->sock = ESL_SOCK_INVALID-1;
1136 status = ESL_SUCCESS;
1137 }
1138
1139 if (mutex) {
1140 esl_mutex_lock(mutex);
1141 }
1142
1143
1144 handle->connected = 0;
1145
1146 ep = handle->race_event;
1147
1148 while(ep) {
1149 esl_event_t *e = ep;
1150 ep = ep->next;
1151 if (e) {
1152 esl_event_destroy(&e);
1153 }
1154 }
1155
1156 esl_event_safe_destroy(&handle->last_event)if (&handle->last_event) esl_event_destroy(&handle
->last_event)
;
1157 esl_event_safe_destroy(&handle->last_sr_event)if (&handle->last_sr_event) esl_event_destroy(&handle
->last_sr_event)
;
1158 esl_event_safe_destroy(&handle->last_ievent)if (&handle->last_ievent) esl_event_destroy(&handle
->last_ievent)
;
1159 esl_event_safe_destroy(&handle->info_event)if (&handle->info_event) esl_event_destroy(&handle
->info_event)
;
1160
1161 if (mutex) {
1162 esl_mutex_unlock(mutex);
1163 esl_mutex_lock(mutex);
1164 esl_mutex_unlock(mutex);
1165 esl_mutex_destroy(&mutex);
1166 }
1167
1168 if (handle->packet_buf) {
1169 esl_buffer_destroy(&handle->packet_buf);
1170 }
1171
1172 memset(handle, 0, sizeof(*handle));
1173 handle->destroyed = 1;
1174
1175 return status;
1176}
1177
1178ESL_DECLARE(esl_status_t)esl_status_t esl_recv_event_timed(esl_handle_t *handle, uint32_t ms, int check_q, esl_event_t **save_event)
1179{
1180 int activity;
1181 esl_status_t status = ESL_SUCCESS;
1182
1183 if (!ms) {
1184 return esl_recv_event(handle, check_q, save_event);
1185 }
1186
1187 if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID-1) {
1188 return ESL_FAIL;
1189 }
1190
1191 if (check_q) {
1192 esl_mutex_lock(handle->mutex);
1193 if (handle->race_event || esl_buffer_packet_count(handle->packet_buf)) {
1194 esl_mutex_unlock(handle->mutex);
1195 return esl_recv_event(handle, check_q, save_event);
1196 }
1197 esl_mutex_unlock(handle->mutex);
1198 }
1199
1200 if (handle->packet_buf && esl_buffer_inuse(handle->packet_buf)) {
1201 activity = ESL_POLL_READ;
1202 } else {
1203 activity = esl_wait_sock(handle->sock, ms, ESL_POLL_READ|ESL_POLL_ERROR);
1204 }
1205
1206 if (activity < 0) {
1207 handle->connected = 0;
1208 return ESL_FAIL;
1209 }
1210
1211 if (activity == 0 || !(activity & ESL_POLL_READ) || (esl_mutex_trylock(handle->mutex) != ESL_SUCCESS)) {
1212 return ESL_BREAK;
1213 }
1214
1215 if (activity < 0) {
1216 handle->connected = 0;
1217 status = ESL_FAIL;
1218 } else if (activity > 0 && (activity & ESL_POLL_READ)) {
1219 if (esl_recv_event(handle, check_q, save_event)) {
1220 status = ESL_FAIL;
1221 }
1222 } else {
1223 status = ESL_BREAK;
1224 }
1225
1226 if (handle->mutex) esl_mutex_unlock(handle->mutex);
1227
1228 return status;
1229
1230}
1231
1232static esl_ssize_t handle_recv(esl_handle_t *handle, void *data, esl_size_t datalen)
1233{
1234 esl_ssize_t activity = -1;
1235
1236 if (handle->connected) {
1237 if ((activity = esl_wait_sock(handle->sock, 1000, ESL_POLL_READ|ESL_POLL_ERROR)) > 0) {
1238 if (activity < 0) {
1239 activity = -1;
1240 } else if ((activity & ESL_POLL_ERROR)) {
1241 activity = -1;
1242 } else if ((activity & ESL_POLL_READ)) {
1243 if (!(activity = recv(handle->sock, data, datalen, 0))) {
1244 activity = -1;
1245 } else if (activity < 0 && (errno(*__errno_location ()) == EINTR4 || errno(*__errno_location ()) == EAGAIN11 || errno(*__errno_location ()) == EWOULDBLOCK11)) {
1246 activity = 0;
1247 }
1248 }
1249 }
1250
1251 }
1252
1253 return activity;
1254}
1255
1256ESL_DECLARE(esl_status_t)esl_status_t esl_recv_event(esl_handle_t *handle, int check_q, esl_event_t **save_event)
1257{
1258 char *c;
1259 esl_ssize_t rrval;
1260 esl_event_t *revent = NULL((void*)0);
1261 char *beg;
1262 char *hname, *hval;
1263 char *col;
1264 char *cl;
1265 esl_ssize_t len;
1266
1267 if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID-1) {
1
Assuming 'handle' is non-null
2
Taking false branch
1268 return ESL_FAIL;
1269 }
1270
1271 esl_mutex_lock(handle->mutex);
1272
1273 if (!handle->connected || handle->sock == ESL_SOCK_INVALID-1) {
3
Taking false branch
1274 goto fail;
1275 }
1276
1277 esl_event_safe_destroy(&handle->last_ievent)if (&handle->last_ievent) esl_event_destroy(&handle
->last_ievent)
;
1278
1279 if (check_q && handle->race_event) {
1280 revent = handle->race_event;
1281 handle->race_event = handle->race_event->next;
1282 revent->next = NULL((void*)0);
1283
1284 goto parse_event;
1285 }
1286
1287 while(!revent && handle->connected) {
4
Loop condition is true. Entering loop body
10
Loop condition is true. Entering loop body
16
Loop condition is true. Entering loop body
22
Loop condition is true. Entering loop body
1288 esl_size_t len1;
1289
1290 if ((len1 = esl_buffer_read_packet(handle->packet_buf, handle->socket_buf, sizeof(handle->socket_buf) - 1))) {
5
Assuming 'len1' is zero
6
Taking false branch
11
Assuming 'len1' is zero
12
Taking false branch
17
Assuming 'len1' is zero
18
Taking false branch
23
Assuming 'len1' is non-zero
24
Taking true branch
1291 char *data = (char *) handle->socket_buf;
1292 char *p, *e;
1293
1294 *(data + len1) = '\0';
1295
1296 esl_event_create(&revent, ESL_EVENT_CLONE)esl_event_create_subclass(&revent, ESL_EVENT_CLONE, ((void
*)0))
;
1297 revent->event_id = ESL_EVENT_SOCKET_DATA;
1298 esl_event_add_header_string(revent, ESL_STACK_BOTTOM, "Event-Name", "SOCKET_DATA");
1299
1300 p = data;
1301
1302 while(p) {
25
Loop condition is true. Entering loop body
28
Loop condition is false. Execution continues on line 1329
1303 hname = p;
1304 p = NULL((void*)0);
1305
1306 if ((hval = strchr(hname, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(hname) && (':') == '\0' ? (char *) __rawmemchr (hname
, ':') : __builtin_strchr (hname, ':')))
)) {
26
Assuming 'hval' is null
27
Taking false branch
1307 *hval++ = '\0';
1308 while(*hval == ' ' || *hval == '\t') hval++;
1309
1310 if ((e = strchr(hval, '\n')(__extension__ (__builtin_constant_p ('\n') && !__builtin_constant_p
(hval) && ('\n') == '\0' ? (char *) __rawmemchr (hval
, '\n') : __builtin_strchr (hval, '\n')))
)) {
1311 *e++ = '\0';
1312 while(*e == '\n' || *e == '\r') e++;
1313
1314 if (hname && hval) {
1315 esl_url_decode(hval);
1316 esl_log(ESL_LOG_DEBUG"libs/esl/src/esl.c", (const char *)__func__, 1316, 7, "RECV HEADER [%s] = [%s]\n", hname, hval);
1317 if (!strncmp(hval, "ARRAY::", 7)(__extension__ (__builtin_constant_p (7) && ((__builtin_constant_p
(hval) && strlen (hval) < ((size_t) (7))) || (__builtin_constant_p
("ARRAY::") && strlen ("ARRAY::") < ((size_t) (7)
))) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(hval) && __builtin_constant_p ("ARRAY::") &&
(__s1_len = __builtin_strlen (hval), __s2_len = __builtin_strlen
("ARRAY::"), (!((size_t)(const void *)((hval) + 1) - (size_t
)(const void *)(hval) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)(("ARRAY::") + 1) - (size_t)(const void
*)("ARRAY::") == 1) || __s2_len >= 4)) ? __builtin_strcmp
(hval, "ARRAY::") : (__builtin_constant_p (hval) && (
(size_t)(const void *)((hval) + 1) - (size_t)(const void *)(hval
) == 1) && (__s1_len = __builtin_strlen (hval), __s1_len
< 4) ? (__builtin_constant_p ("ARRAY::") && ((size_t
)(const void *)(("ARRAY::") + 1) - (size_t)(const void *)("ARRAY::"
) == 1) ? __builtin_strcmp (hval, "ARRAY::") : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ("ARRAY::"); int __result = (((const unsigned char *
) (const char *) (hval))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (hval))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (hval))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (hval))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
("ARRAY::") && ((size_t)(const void *)(("ARRAY::") +
1) - (size_t)(const void *)("ARRAY::") == 1) && (__s2_len
= __builtin_strlen ("ARRAY::"), __s2_len < 4) ? (__builtin_constant_p
(hval) && ((size_t)(const void *)((hval) + 1) - (size_t
)(const void *)(hval) == 1) ? __builtin_strcmp (hval, "ARRAY::"
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (hval); int __result = (((const unsigned
char *) (const char *) ("ARRAY::"))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) ("ARRAY::"))[1] - __s2[1]); if (__s2_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) ("ARRAY::"))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) ("ARRAY::"))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp (hval, "ARRAY::")))); }) : strncmp
(hval, "ARRAY::", 7)))
) {
1318 esl_event_add_array(revent, hname, hval);
1319 } else {
1320 esl_event_add_header_string(revent, ESL_STACK_BOTTOM, hname, hval);
1321 }
1322 }
1323
1324 p = e;
1325 }
1326 }
1327 }
1328
1329 break;
29
Execution continues on line 1347
1330 }
1331
1332 rrval = handle_recv(handle, handle->socket_buf, sizeof(handle->socket_buf) - 1);
1333
1334 if (rrval == 0) {
7
Assuming 'rrval' is equal to 0
8
Taking true branch
13
Assuming 'rrval' is equal to 0
14
Taking true branch
19
Assuming 'rrval' is equal to 0
20
Taking true branch
1335 continue;
9
Execution continues on line 1287
15
Execution continues on line 1287
21
Execution continues on line 1287
1336 } else if (rrval < 0) {
1337 if (!(strerror_r(handle->errnum, handle->err, sizeof(handle->err))))
1338 *(handle->err)=0;
1339 goto fail;
1340 }
1341
1342 *((char *)handle->socket_buf + ESL_CLAMP(0, sizeof(handle->socket_buf) - 1, rrval)(((sizeof(handle->socket_buf) - 1) < (((rrval) > (0)
? (rrval) : (0))) ? (sizeof(handle->socket_buf) - 1) : ((
(rrval) > (0) ? (rrval) : (0)))))
) = '\0';
1343
1344 esl_buffer_write(handle->packet_buf, handle->socket_buf, rrval);
1345 }
1346
1347 if (!revent) {
30
Taking false branch
1348 goto fail;
1349 }
1350
1351 if ((cl = esl_event_get_header(revent, "content-length")esl_event_get_header_idx(revent, "content-length", -1))) {
31
Assuming 'cl' is null
32
Taking false branch
1352 char *body;
1353 esl_ssize_t sofar = 0;
1354
1355 len = atol(cl);
1356 body = malloc(len+1);
1357 esl_assert(body)((body) ? (void) (0) : __assert_fail ("body", "libs/esl/src/esl.c"
, 1357, __PRETTY_FUNCTION__))
;
1358 *(body + len) = '\0';
1359
1360 do {
1361 esl_ssize_t r,s = esl_buffer_inuse(handle->packet_buf);
1362
1363 if (s >= len) {
1364 sofar = esl_buffer_read(handle->packet_buf, body, len);
1365 } else {
1366 r = handle_recv(handle, handle->socket_buf, sizeof(handle->socket_buf) - 1);
1367
1368 if (r < 0) {
1369 if (!(strerror_r(handle->errnum, handle->err, sizeof(handle->err))))
1370 *(handle->err)=0;
1371 free(body);
1372 goto fail;
1373 } else if (r == 0) {
1374 continue;
1375 }
1376
1377 *((char *)handle->socket_buf + ESL_CLAMP(0, sizeof(handle->socket_buf) - 1, r)(((sizeof(handle->socket_buf) - 1) < (((r) > (0) ? (
r) : (0))) ? (sizeof(handle->socket_buf) - 1) : (((r) >
(0) ? (r) : (0)))))
) = '\0';
1378 esl_buffer_write(handle->packet_buf, handle->socket_buf, r);
1379 }
1380
1381 } while (sofar < len);
1382
1383 revent->body = body;
1384 }
1385
1386 parse_event:
1387
1388 if (save_event) {
33
Assuming 'save_event' is null
34
Taking false branch
1389 *save_event = revent;
1390 revent = NULL((void*)0);
1391 } else {
1392 esl_event_safe_destroy(&handle->last_event)if (&handle->last_event) esl_event_destroy(&handle
->last_event)
;
1393 handle->last_event = revent;
1394 }
1395
1396 if (revent) {
35
Taking true branch
1397 hval = esl_event_get_header(revent, "reply-text")esl_event_get_header_idx(revent, "reply-text", -1);
1398
1399 if (!esl_strlen_zero(hval)(!hval || *(hval) == '\0')) {
36
Taking true branch
1400 strncpy(handle->last_reply, hval, sizeof(handle->last_reply))__builtin_strncpy (handle->last_reply, hval, sizeof(handle
->last_reply))
;
1401 }
1402
1403 hval = esl_event_get_header(revent, "content-type")esl_event_get_header_idx(revent, "content-type", -1);
1404
1405 if (!esl_safe_strcasecmp(hval, "text/disconnect-notice") && revent->body) {
1406 const char *dval = esl_event_get_header(revent, "content-disposition")esl_event_get_header_idx(revent, "content-disposition", -1);
1407 if (esl_strlen_zero(dval)(!dval || *(dval) == '\0') || strcasecmp(dval, "linger")) {
1408 goto fail;
1409 }
1410 }
1411
1412 if (revent->body) {
37
Taking true branch
1413 if (!esl_safe_strcasecmp(hval, "text/event-plain")) {
38
Taking true branch
1414 esl_event_types_t et = ESL_EVENT_CLONE;
1415 char *body = strdup(revent->body);
1416
1417 esl_event_create(&handle->last_ievent, et)esl_event_create_subclass(&handle->last_ievent, et, ((
void*)0))
;
1418
1419 beg = body;
39
Value assigned to 'beg'
1420
1421 while(beg) {
40
Assuming pointer value is null
41
Loop condition is false. Execution continues on line 1460
1422 if (!(c = strchr(beg, '\n')(__extension__ (__builtin_constant_p ('\n') && !__builtin_constant_p
(beg) && ('\n') == '\0' ? (char *) __rawmemchr (beg,
'\n') : __builtin_strchr (beg, '\n')))
)) {
1423 break;
1424 }
1425
1426 hname = beg;
1427 hval = col = NULL((void*)0);
1428
1429 if (hname && (col = strchr(hname, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(hname) && (':') == '\0' ? (char *) __rawmemchr (hname
, ':') : __builtin_strchr (hname, ':')))
)) {
1430 hval = col + 1;
1431 *col = '\0';
1432 while(*hval == ' ') hval++;
1433 }
1434
1435 *c = '\0';
1436
1437 if (hname && hval) {
1438 esl_url_decode(hval);
1439 esl_log(ESL_LOG_DEBUG"libs/esl/src/esl.c", (const char *)__func__, 1439, 7, "RECV INNER HEADER [%s] = [%s]\n", hname, hval);
1440 if (!strcasecmp(hname, "event-name")) {
1441 esl_event_del_header(handle->last_ievent, "event-name")esl_event_del_header_val(handle->last_ievent, "event-name"
, ((void*)0))
;
1442 esl_name_event(hval, &handle->last_ievent->event_id);
1443 }
1444
1445 if (!strncmp(hval, "ARRAY::", 7)(__extension__ (__builtin_constant_p (7) && ((__builtin_constant_p
(hval) && strlen (hval) < ((size_t) (7))) || (__builtin_constant_p
("ARRAY::") && strlen ("ARRAY::") < ((size_t) (7)
))) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(hval) && __builtin_constant_p ("ARRAY::") &&
(__s1_len = __builtin_strlen (hval), __s2_len = __builtin_strlen
("ARRAY::"), (!((size_t)(const void *)((hval) + 1) - (size_t
)(const void *)(hval) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)(("ARRAY::") + 1) - (size_t)(const void
*)("ARRAY::") == 1) || __s2_len >= 4)) ? __builtin_strcmp
(hval, "ARRAY::") : (__builtin_constant_p (hval) && (
(size_t)(const void *)((hval) + 1) - (size_t)(const void *)(hval
) == 1) && (__s1_len = __builtin_strlen (hval), __s1_len
< 4) ? (__builtin_constant_p ("ARRAY::") && ((size_t
)(const void *)(("ARRAY::") + 1) - (size_t)(const void *)("ARRAY::"
) == 1) ? __builtin_strcmp (hval, "ARRAY::") : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ("ARRAY::"); int __result = (((const unsigned char *
) (const char *) (hval))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (hval))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (hval))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (hval))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
("ARRAY::") && ((size_t)(const void *)(("ARRAY::") +
1) - (size_t)(const void *)("ARRAY::") == 1) && (__s2_len
= __builtin_strlen ("ARRAY::"), __s2_len < 4) ? (__builtin_constant_p
(hval) && ((size_t)(const void *)((hval) + 1) - (size_t
)(const void *)(hval) == 1) ? __builtin_strcmp (hval, "ARRAY::"
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (hval); int __result = (((const unsigned
char *) (const char *) ("ARRAY::"))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) ("ARRAY::"))[1] - __s2[1]); if (__s2_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) ("ARRAY::"))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) ("ARRAY::"))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp (hval, "ARRAY::")))); }) : strncmp
(hval, "ARRAY::", 7)))
) {
1446 esl_event_add_array(handle->last_ievent, hname, hval);
1447 } else {
1448 esl_event_add_header_string(handle->last_ievent, ESL_STACK_BOTTOM, hname, hval);
1449 }
1450 }
1451
1452 beg = c + 1;
1453
1454 if (*beg == '\n') {
1455 beg++;
1456 break;
1457 }
1458 }
1459
1460 if ((cl = esl_event_get_header(handle->last_ievent, "content-length")esl_event_get_header_idx(handle->last_ievent, "content-length"
, -1)
)) {
42
Assuming 'cl' is not null
43
Taking true branch
1461 handle->last_ievent->body = strdup(beg);
44
Null pointer passed as an argument to a 'nonnull' parameter
1462 }
1463
1464 free(body);
1465
1466 if (esl_log_level >= 7) {
1467 char *foo;
1468 esl_event_serialize(handle->last_ievent, &foo, ESL_FALSE);
1469 esl_log(ESL_LOG_DEBUG"libs/esl/src/esl.c", (const char *)__func__, 1469, 7, "RECV EVENT\n%s\n", foo);
1470 free(foo);
1471 }
1472 } else if (!esl_safe_strcasecmp(hval, "text/event-json")) {
1473 esl_event_create_json(&handle->last_ievent, revent->body);
1474 }
1475 }
1476
1477 if (esl_log_level >= 7) {
1478 char *foo;
1479 esl_event_serialize(revent, &foo, ESL_FALSE);
1480 esl_log(ESL_LOG_DEBUG"libs/esl/src/esl.c", (const char *)__func__, 1480, 7, "RECV MESSAGE\n%s\n", foo);
1481 free(foo);
1482 }
1483 }
1484
1485 esl_mutex_unlock(handle->mutex);
1486
1487 return ESL_SUCCESS;
1488
1489 fail:
1490
1491 esl_mutex_unlock(handle->mutex);
1492
1493 handle->connected = 0;
1494
1495 return ESL_FAIL;
1496
1497}
1498
1499ESL_DECLARE(esl_status_t)esl_status_t esl_send(esl_handle_t *handle, const char *cmd)
1500{
1501 const char *e = cmd + strlen(cmd) -1;
1502
1503
1504 if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID-1) {
1505 return ESL_FAIL;
1506 }
1507
1508 esl_log(ESL_LOG_DEBUG"libs/esl/src/esl.c", (const char *)__func__, 1508, 7, "SEND\n%s\n", cmd);
1509
1510 if (send(handle->sock, cmd, strlen(cmd), 0) != (int)strlen(cmd)) {
1511 handle->connected = 0;
1512 if (!(strerror_r(handle->errnum, handle->err, sizeof(handle->err))))
1513 *(handle->err)=0;
1514 return ESL_FAIL;
1515 }
1516
1517 if (!(*e == '\n' && *(e-1) == '\n')) {
1518 if (send(handle->sock, "\n\n", 2, 0) != 2) {
1519 handle->connected = 0;
1520 if (!(strerror_r(handle->errnum, handle->err, sizeof(handle->err))))
1521 *(handle->err)=0;
1522 return ESL_FAIL;
1523 }
1524 }
1525
1526 return ESL_SUCCESS;
1527
1528}
1529
1530
1531ESL_DECLARE(esl_status_t)esl_status_t esl_send_recv_timed(esl_handle_t *handle, const char *cmd, uint32_t ms)
1532{
1533 const char *hval;
1534 esl_status_t status;
1535
1536 if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID-1) {
1537 return ESL_FAIL;
1538 }
1539
1540 esl_mutex_lock(handle->mutex);
1541
1542
1543 if (!handle->connected || handle->sock == ESL_SOCK_INVALID-1) {
1544 handle->connected = 0;
1545 esl_mutex_unlock(handle->mutex);
1546 return ESL_FAIL;
1547 }
1548
1549 esl_event_safe_destroy(&handle->last_sr_event)if (&handle->last_sr_event) esl_event_destroy(&handle
->last_sr_event)
;
1550
1551 *handle->last_sr_reply = '\0';
1552
1553 if ((status = esl_send(handle, cmd))) {
1554 esl_mutex_unlock(handle->mutex);
1555 return status;
1556 }
1557
1558 recv:
1559
1560 esl_event_safe_destroy(&handle->last_sr_event)if (&handle->last_sr_event) esl_event_destroy(&handle
->last_sr_event)
;
1561
1562 *handle->last_sr_reply = '\0';
1563
1564 status = esl_recv_event_timed(handle, ms, 0, &handle->last_sr_event);
1565
1566 if (handle->last_sr_event) {
1567 char *ct = esl_event_get_header(handle->last_sr_event,"content-type")esl_event_get_header_idx(handle->last_sr_event, "content-type"
, -1)
;
1568
1569 if (ct && strcasecmp(ct, "api/response") && strcasecmp(ct, "command/reply")) {
1570 esl_event_t *ep;
1571
1572 for(ep = handle->race_event; ep && ep->next; ep = ep->next);
1573
1574 if (ep) {
1575 ep->next = handle->last_sr_event;
1576 } else {
1577 handle->race_event = handle->last_sr_event;
1578 }
1579
1580 handle->last_sr_event = NULL((void*)0);
1581
1582 esl_mutex_unlock(handle->mutex);
1583 esl_mutex_lock(handle->mutex);
1584
1585 if (!handle->connected || handle->sock == ESL_SOCK_INVALID-1) {
1586 handle->connected = 0;
1587 esl_mutex_unlock(handle->mutex);
1588 return ESL_FAIL;
1589 }
1590
1591 goto recv;
1592 }
1593
1594 if (handle->last_sr_event) {
1595 hval = esl_event_get_header(handle->last_sr_event, "reply-text")esl_event_get_header_idx(handle->last_sr_event, "reply-text"
, -1)
;
1596
1597 if (!esl_strlen_zero(hval)(!hval || *(hval) == '\0')) {
1598 strncpy(handle->last_sr_reply, hval, sizeof(handle->last_sr_reply))__builtin_strncpy (handle->last_sr_reply, hval, sizeof(handle
->last_sr_reply))
;
1599 }
1600 }
1601 }
1602
1603 esl_mutex_unlock(handle->mutex);
1604
1605 return status;
1606}
1607
1608
1609ESL_DECLARE(unsigned int)unsigned int esl_separate_string_string(char *buf, const char *delim, char **array, unsigned int arraylen)
1610{
1611 unsigned int count = 0;
1612 char *d;
1613 size_t dlen = strlen(delim);
1614
1615 array[count++] = buf;
1616
1617 while (count < arraylen && array[count - 1]) {
1618 if ((d = strstr(array[count - 1], delim))) {
1619 *d = '\0';
1620 d += dlen;
1621 array[count++] = d;
1622 } else
1623 break;
1624 }
1625
1626 return count;
1627}
1628
1629/* For Emacs:
1630 * Local Variables:
1631 * mode:c
1632 * indent-tabs-mode:t
1633 * tab-width:4
1634 * c-basic-offset:4
1635 * End:
1636 * For VIM:
1637 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
1638 */