Bug Summary

File:src/mod/endpoints/mod_verto/mod_verto.c
Location:line 1617, column 5
Description:Null pointer argument in call to string comparison function

Annotated Source Code

1/*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Anthony Minessale II <anthm@freeswitch.org>
27 * Seven Du <dujinfang@gmail.com>
28 *
29 * mod_verto.c -- HTML5 Verto interface
30 *
31 */
32#include <switch.h>
33#include <switch_json.h>
34
35
36/* Prototypes */
37SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_verto_shutdown)switch_status_t mod_verto_shutdown (void);
38SWITCH_MODULE_LOAD_FUNCTION(mod_verto_load)switch_status_t mod_verto_load (switch_loadable_module_interface_t
**module_interface, switch_memory_pool_t *pool)
;
39SWITCH_MODULE_RUNTIME_FUNCTION(mod_verto_runtime)switch_status_t mod_verto_runtime (void);
40
41SWITCH_MODULE_DEFINITION(mod_verto, mod_verto_load, mod_verto_shutdown, mod_verto_runtime)static const char modname[] = "mod_verto" ; __attribute__((visibility
("default"))) switch_loadable_module_function_table_t mod_verto_module_interface
= { 5, mod_verto_load, mod_verto_shutdown, mod_verto_runtime
, SMODF_NONE }
;
42
43#define EP_NAME"verto.rtc" "verto.rtc"
44#define WSS_STANDALONE1 1
45#include "ws.h"
46
47//////////////////////////
48#include <mod_verto.h>
49#ifndef WIN32
50#include <sys/param.h>
51#endif
52#include <sys/stat.h>
53#include <fcntl.h>
54#ifndef WIN32
55#include <sys/file.h>
56#endif
57#include <ctype.h>
58#include <sys/stat.h>
59
60
61
62#define die(...)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 62, ((void*)0), SWITCH_LOG_DEBUG, ...); goto
error
switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
62, ((void*)0)
, SWITCH_LOG_DEBUG, __VA_ARGS__); goto error
63
64struct globals_s globals;
65
66
67static struct {
68 switch_mutex_t *store_mutex;
69 switch_hash_t *store_hash;
70} json_GLOBALS;
71
72
73const char json_sql[] =
74 "create table json_store (\n"
75 " name varchar(255) not null,\n"
76 " data text\n"
77 ");\n";
78
79
80typedef enum {
81 CMD_ADD,
82 CMD_DEL,
83 CMD_DUMP,
84 CMD_COMMIT,
85 CMD_RETRIEVE
86} store_cmd_t;
87
88typedef struct {
89 switch_mutex_t *mutex;
90 cJSON *JSON_STORE;
91} json_store_t;
92
93static void json_cleanup(void)
94{
95 switch_hash_index_t *hi = NULL((void*)0);
96 void *val;
97 const void *var;
98 cJSON *json;
99
100 if (!json_GLOBALS.store_hash) {
101 return;
102 }
103
104 switch_mutex_lock(json_GLOBALS.store_mutex);
105 top:
106
107 for (hi = switch_core_hash_first_iter(json_GLOBALS.store_hash, hi); hi;) {
108 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
109 json = (cJSON *) val;
110 cJSON_Delete(json);
111 switch_core_hash_delete(json_GLOBALS.store_hash, var);
112 goto top;
113 }
114 switch_safe_free(hi)if (hi) {free(hi);hi=((void*)0);};
115
116 switch_mutex_unlock(json_GLOBALS.store_mutex);
117
118}
119
120static switch_bool_t check_name(const char *name)
121{
122 const char *p;
123
124 for(p = name; p && *p; p++) {
125 if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') || *p == '-' || *p == '_') continue;
126 return SWITCH_FALSE;
127 }
128
129 return SWITCH_TRUE;
130}
131
132
133static verto_profile_t *find_profile(const char *name);
134static jsock_t *get_jsock(const char *uuid);
135
136static void verto_deinit_ssl(verto_profile_t *profile)
137{
138 if (profile->ssl_ctx) {
139 SSL_CTX_free(profile->ssl_ctx);
140 profile->ssl_ctx = NULL((void*)0);
141 }
142}
143
144static void close_file(ws_socket_t *sock)
145{
146 if (*sock > -1) {
147#ifndef WIN32
148 close(*sock);
149#else
150 closesocket(*sock);
151#endif
152 *sock = ws_sock_invalid(ws_socket_t)-1;
153 }
154}
155
156static void close_socket(ws_socket_t *sock)
157{
158 if (*sock > -1) {
159 shutdown(*sock, 2);
160 close_file(sock);
161 }
162}
163
164
165static int ssl_init = 0;
166
167static int verto_init_ssl(verto_profile_t *profile)
168{
169 const char *err = "";
170 int i = 0;
171
172 if (!ssl_init) {
173 SSL_library_init();
174 ssl_init = 1;
175 }
176
177
178 profile->ssl_method = SSLv23_server_method(); /* create server instance */
179 profile->ssl_ctx = SSL_CTX_new(profile->ssl_method); /* create context */
180 profile->ssl_ready = 1;
181 assert(profile->ssl_ctx)((profile->ssl_ctx) ? (void) (0) : __assert_fail ("profile->ssl_ctx"
, "mod_verto.c", 181, __PRETTY_FUNCTION__))
;
182
183 /* Disable SSLv2 */
184 SSL_CTX_set_options(profile->ssl_ctx, SSL_OP_NO_SSLv2)SSL_CTX_ctrl((profile->ssl_ctx),32,(0x01000000L),((void*)0
))
;
185 /* Disable SSLv3 */
186 SSL_CTX_set_options(profile->ssl_ctx, SSL_OP_NO_SSLv3)SSL_CTX_ctrl((profile->ssl_ctx),32,(0x02000000L),((void*)0
))
;
187 /* Disable TLSv1 */
188 SSL_CTX_set_options(profile->ssl_ctx, SSL_OP_NO_TLSv1)SSL_CTX_ctrl((profile->ssl_ctx),32,(0x04000000L),((void*)0
))
;
189 /* Disable Compression CRIME (Compression Ratio Info-leak Made Easy) */
190 SSL_CTX_set_options(profile->ssl_ctx, SSL_OP_NO_COMPRESSION)SSL_CTX_ctrl((profile->ssl_ctx),32,(0x00020000L),((void*)0
))
;
191
192 /* set the local certificate from CertFile */
193 if (!zstr(profile->chain)_zstr(profile->chain)) {
194 if (switch_file_exists(profile->chain, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
195 err = "SUPPLIED CHAIN FILE NOT FOUND\n";
196 goto fail;
197 }
198
199 if (!SSL_CTX_use_certificate_chain_file(profile->ssl_ctx, profile->chain)) {
200 err = "CERT CHAIN FILE ERROR";
201 goto fail;
202 }
203 }
204
205 if (switch_file_exists(profile->cert, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
206 err = "SUPPLIED CERT FILE NOT FOUND\n";
207 goto fail;
208 }
209
210 if (!SSL_CTX_use_certificate_file(profile->ssl_ctx, profile->cert, SSL_FILETYPE_PEM1)) {
211 err = "CERT FILE ERROR";
212 goto fail;
213 }
214
215 /* set the private key from KeyFile */
216
217 if (switch_file_exists(profile->key, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
218 err = "SUPPLIED KEY FILE NOT FOUND\n";
219 goto fail;
220 }
221
222 if (!SSL_CTX_use_PrivateKey_file(profile->ssl_ctx, profile->key, SSL_FILETYPE_PEM1)) {
223 err = "PRIVATE KEY FILE ERROR";
224 goto fail;
225 }
226
227 /* verify private key */
228 if ( !SSL_CTX_check_private_key(profile->ssl_ctx) ) {
229 err = "PRIVATE KEY FILE ERROR";
230 goto fail;
231 }
232
233 SSL_CTX_set_cipher_list(profile->ssl_ctx, "HIGH:!DSS:!aNULL@STRENGTH");
234
235 return 1;
236
237 fail:
238 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
238, ((void*)0)
, SWITCH_LOG_ERROR, "SSL ERR: %s\n", err);
239
240 profile->ssl_ready = 0;
241 verto_deinit_ssl(profile);
242
243 for (i = 0; i < profile->i; i++) {
244 if (profile->ip[i].secure) {
245 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
245, ((void*)0)
, SWITCH_LOG_ERROR, "SSL NOT ENABLED FOR LISTENER %s:%d. REVERTING TO WS\n",
246 profile->ip[i].local_ip, profile->ip[i].local_port);
247 profile->ip[i].secure = 0;
248 }
249 }
250
251 return 0;
252
253}
254
255
256struct jsock_sub_node_head_s;
257
258typedef struct jsock_sub_node_s {
259 jsock_t *jsock;
260 uint32_t serno;
261 struct jsock_sub_node_head_s *head;
262 struct jsock_sub_node_s *next;
263} jsock_sub_node_t;
264
265typedef struct jsock_sub_node_head_s {
266 jsock_sub_node_t *node;
267 jsock_sub_node_t *tail;
268 char *event_channel;
269} jsock_sub_node_head_t;
270
271static uint32_t jsock_unsub_head(jsock_t *jsock, jsock_sub_node_head_t *head)
272{
273 uint32_t x = 0;
274
275 jsock_sub_node_t *thisnp = NULL((void*)0), *np, *last = NULL((void*)0);
276
277 np = head->tail = head->node;
278
279 while (np) {
280
281 thisnp = np;
282 np = np->next;
283
284 if (!jsock || thisnp->jsock == jsock) {
285 x++;
286
287 if (last) {
288 last->next = np;
289 } else {
290 head->node = np;
291 }
292
293 if (thisnp->jsock->profile->debug || globals.debug) {
294 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
294, ((void*)0)
, SWITCH_LOG_ALERT, "UNSUBBING %s [%s]\n", thisnp->jsock->name, thisnp->head->event_channel);
295 }
296
297 thisnp->jsock = NULL((void*)0);
298 free(thisnp);
299 } else {
300 last = thisnp;
301 head->tail = last;
302 }
303 }
304
305 return x;
306}
307
308static void unsub_all_jsock(void)
309{
310 switch_hash_index_t *hi;
311 void *val;
312 jsock_sub_node_head_t *head;
313
314 switch_thread_rwlock_wrlock(globals.event_channel_rwlock);
315 top:
316 head = NULL((void*)0);
317
318 for (hi = switch_core_hash_first(globals.event_channel_hash)switch_core_hash_first_iter(globals.event_channel_hash, ((void
*)0))
; hi;) {
319 switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val);
320 head = (jsock_sub_node_head_t *) val;
321 jsock_unsub_head(NULL((void*)0), head);
322 switch_core_hash_delete(globals.event_channel_hash, head->event_channel);
323 free(head->event_channel);
324 free(head);
325 switch_safe_free(hi)if (hi) {free(hi);hi=((void*)0);};
326 goto top;
327 }
328
329 switch_thread_rwlock_unlock(globals.event_channel_rwlock);
330}
331
332static uint32_t jsock_unsub_channel(jsock_t *jsock, const char *event_channel)
333{
334 jsock_sub_node_head_t *head;
335 uint32_t x = 0;
336
337 switch_thread_rwlock_wrlock(globals.event_channel_rwlock);
338
339 if (!event_channel) {
340 switch_hash_index_t *hi;
341 void *val;
342
343 for (hi = switch_core_hash_first(globals.event_channel_hash)switch_core_hash_first_iter(globals.event_channel_hash, ((void
*)0))
; hi; hi = switch_core_hash_next(&hi)) {
344 switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val);
345
346 if (val) {
347 head = (jsock_sub_node_head_t *) val;
348 x += jsock_unsub_head(jsock, head);
349 }
350 }
351
352 } else {
353 if ((head = switch_core_hash_find(globals.event_channel_hash, event_channel))) {
354 x += jsock_unsub_head(jsock, head);
355 }
356 }
357
358 switch_thread_rwlock_unlock(globals.event_channel_rwlock);
359
360 return x;
361}
362
363static void presence_ping(const char *event_channel)
364{
365 switch_console_callback_match_t *matches;
366 const char *val = event_channel;
367
368 if (val) {
369 if (!strcasecmp(val, "presence")) {
370 val = NULL((void*)0);
371 } else {
372 char *p;
373 if ((p = strchr(val, '.')(__extension__ (__builtin_constant_p ('.') && !__builtin_constant_p
(val) && ('.') == '\0' ? (char *) __rawmemchr (val, '.'
) : __builtin_strchr (val, '.')))
)) {
374 val = (p+1);
375 }
376 }
377 }
378
379 if ((matches = switch_core_session_findall_matching_var("presence_id", val))) {
380 switch_console_callback_match_node_t *m;
381 switch_core_session_t *session;
382
383 for (m = matches->head; m; m = m->next) {
384 if ((session = switch_core_session_locate(m->val)switch_core_session_perform_locate(m->val, "mod_verto.c", (
const char *)__func__, 384)
)) {
385 switch_channel_t *channel = switch_core_session_get_channel(session);
386 switch_event_t *event;
387
388 if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_CALLSTATE)switch_event_create_subclass_detailed("mod_verto.c", (const char
* )(const char *)__func__, 388, &event, SWITCH_EVENT_CHANNEL_CALLSTATE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
389 switch_channel_callstate_t callstate = switch_channel_get_callstate(channel);
390
391 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Original-Channel-Call-State", switch_channel_callstate2str(callstate));
392 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Call-State-Number", "%d", callstate);
393 switch_channel_event_set_data(channel, event);
394 switch_event_fire(&event)switch_event_fire_detailed("mod_verto.c", (const char * )(const
char *)__func__, 394, &event, ((void*)0))
;
395 }
396
397 switch_core_session_rwunlock(session);
398 }
399 }
400
401 switch_console_free_matches(&matches);
402 }
403}
404
405static switch_status_t jsock_sub_channel(jsock_t *jsock, const char *event_channel)
406{
407 jsock_sub_node_t *node, *np;
408 jsock_sub_node_head_t *head;
409 switch_status_t status = SWITCH_STATUS_FALSE;
410
411 switch_thread_rwlock_wrlock(globals.event_channel_rwlock);
412
413 if (!(head = switch_core_hash_find(globals.event_channel_hash, event_channel))) {
414 switch_zmalloc(head, sizeof(*head))(void)((((head = calloc(1, (sizeof(*head))))) ? (void) (0) : __assert_fail
("(head = calloc(1, (sizeof(*head))))", "mod_verto.c", 414, __PRETTY_FUNCTION__
)),head)
;
415 head->event_channel = strdup(event_channel)(__extension__ (__builtin_constant_p (event_channel) &&
((size_t)(const void *)((event_channel) + 1) - (size_t)(const
void *)(event_channel) == 1) ? (((const char *) (event_channel
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen (event_channel) + 1; char *__retval = (
char *) malloc (__len); if (__retval != ((void*)0)) __retval =
(char *) memcpy (__retval, event_channel, __len); __retval; }
)) : __strdup (event_channel)))
;
416 switch_core_hash_insert(globals.event_channel_hash, event_channel, head)switch_core_hash_insert_destructor(globals.event_channel_hash
, event_channel, head, ((void*)0))
;
417
418 switch_zmalloc(node, sizeof(*node))(void)((((node = calloc(1, (sizeof(*node))))) ? (void) (0) : __assert_fail
("(node = calloc(1, (sizeof(*node))))", "mod_verto.c", 418, __PRETTY_FUNCTION__
)),node)
;
419 node->jsock = jsock;
420 node->head = head;
421 head->node = node;
422 head->tail = node;
423 status = SWITCH_STATUS_SUCCESS;
424 } else {
425 int exist = 0;
426
427 for (np = head->node; np; np = np->next) {
428 if (np->jsock == jsock) {
429 exist = 1;
430 break;
431 }
432 }
433
434 if (!exist) {
435 switch_zmalloc(node, sizeof(*node))(void)((((node = calloc(1, (sizeof(*node))))) ? (void) (0) : __assert_fail
("(node = calloc(1, (sizeof(*node))))", "mod_verto.c", 435, __PRETTY_FUNCTION__
)),node)
;
436 node->jsock = jsock;
437 node->head = head;
438
439 if (!head->node) {
440 head->node = node;
441 head->tail = node;
442 } else {
443 head->tail->next = node;
444 head->tail = head->tail->next;
445 }
446 status = SWITCH_STATUS_SUCCESS;
447 }
448 }
449
450 switch_thread_rwlock_unlock(globals.event_channel_rwlock);
451
452 if (status == SWITCH_STATUS_SUCCESS && !strncasecmp(event_channel, "presence", 8)) {
453 presence_ping(event_channel);
454 }
455
456 return status;
457}
458
459static uint32_t ID = 1;
460
461static void del_jsock(jsock_t *jsock)
462{
463 jsock_t *p, *last = NULL((void*)0);
464
465 jsock_unsub_channel(jsock, NULL((void*)0));
466 switch_event_channel_permission_clear(jsock->uuid_str);
467
468 switch_mutex_lock(jsock->profile->mutex);
469 for(p = jsock->profile->jsock_head; p; p = p->next) {
470 if (p == jsock) {
471 if (last) {
472 last->next = p->next;
473 } else {
474 jsock->profile->jsock_head = p->next;
475 }
476 jsock->profile->jsock_count--;
477 break;
478 }
479
480 last = p;
481 }
482 switch_mutex_unlock(jsock->profile->mutex);
483
484}
485
486static void add_jsock(jsock_t *jsock)
487{
488
489 switch_mutex_lock(jsock->profile->mutex);
490 jsock->next = jsock->profile->jsock_head;
491 jsock->profile->jsock_head = jsock;
492 jsock->profile->jsock_count++;
493 switch_mutex_unlock(jsock->profile->mutex);
494
495}
496
497static uint32_t next_id(void)
498{
499 uint32_t id;
500
501 switch_mutex_lock(globals.mutex);
502 id = ID++;
503 switch_mutex_unlock(globals.mutex);
504
505 return id;
506}
507
508static cJSON *jrpc_new(uint32_t id)
509{
510 cJSON *obj = cJSON_CreateObject();
511 cJSON_AddItemToObject(obj, "jsonrpc", cJSON_CreateString("2.0"));
512
513 if (id) {
514 cJSON_AddItemToObject(obj, "id", cJSON_CreateNumber(id));
515 }
516
517 return obj;
518}
519
520static cJSON *jrpc_new_req(const char *method, const char *call_id, cJSON **paramsP)
521{
522 cJSON *msg, *params = NULL((void*)0);
523 uint32_t id = next_id();
524
525 msg = jrpc_new(id);
526
527 if (paramsP && *paramsP) {
528 params = *paramsP;
529 }
530
531 if (!params) {
532 params = cJSON_CreateObject();
533 }
534
535 cJSON_AddItemToObject(msg, "method", cJSON_CreateString(method));
536 cJSON_AddItemToObject(msg, "params", params);
537
538 if (call_id) {
539 cJSON_AddItemToObject(params, "callID", cJSON_CreateString(call_id));
540 }
541
542 if (paramsP) {
543 *paramsP = params;
544 }
545
546 return msg;
547}
548
549static void jrpc_add_id(cJSON *obj, cJSON *jid, const char *idstr, int id)
550{
551 if (jid) {
552 cJSON_AddItemToObject(obj, "id", cJSON_Duplicate(jid, 1));
553 } else if (idstr) {
554 cJSON_AddItemToObject(obj, "id", zstr(idstr)_zstr(idstr) ? cJSON_CreateNull() : cJSON_CreateString(idstr));
555 } else {
556 cJSON_AddItemToObject(obj, "id", cJSON_CreateNumber(id));
557 }
558}
559
560static void jrpc_add_error(cJSON *obj, int code, const char *message, cJSON *jid)
561{
562 cJSON *error = cJSON_CreateObject();
563
564 cJSON_AddItemToObject(obj, "error", error);
565 cJSON_AddItemToObject(error, "code", cJSON_CreateNumber(code));
566 cJSON_AddItemToObject(error, "message", cJSON_CreateString(message));
567 if (!cJSON_GetObjectItem(obj, "id")) {
568 jrpc_add_id(obj, jid, "", 0);
569 }
570}
571
572static void jrpc_add_result(cJSON *obj, cJSON *result)
573{
574 if (result) {
575 cJSON_AddItemToObject(obj, "result", result);
576 }
577}
578
579static switch_ssize_t ws_write_json(jsock_t *jsock, cJSON **json, switch_bool_t destroy)
580{
581 char *json_text;
582 switch_ssize_t r = -1;
583
584 switch_assert(json)((json) ? (void) (0) : __assert_fail ("json", "mod_verto.c", 584
, __PRETTY_FUNCTION__))
;
585
586 if (!*json) {
587 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
587, ((void*)0)
, SWITCH_LOG_ALERT, "WRITE NULL JS ERROR %" SWITCH_SIZE_T_FMT"ld" "\n", r);
588 return r;
589 }
590
591 if (!zstr(jsock->uuid_str)_zstr(jsock->uuid_str)) {
592 cJSON *result = cJSON_GetObjectItem(*json, "result");
593
594 if (result) {
595 cJSON_AddItemToObject(result, "sessid", cJSON_CreateString(jsock->uuid_str));
596 }
597 }
598
599 if ((json_text = cJSON_PrintUnformatted(*json))) {
600 if (jsock->profile->debug || globals.debug) {
601 char *log_text = cJSON_Print(*json);
602 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
602, ((void*)0)
, SWITCH_LOG_ALERT, "WRITE %s [%s]\n", jsock->name, log_text);
603 free(log_text);
604 }
605 switch_mutex_lock(jsock->write_mutex);
606 r = ws_write_frame(&jsock->ws, WSOC_TEXT, json_text, strlen(json_text));
607 switch_mutex_unlock(jsock->write_mutex);
608 switch_safe_free(json_text)if (json_text) {free(json_text);json_text=((void*)0);};
609 }
610
611 if (destroy) {
612 cJSON_Delete(*json);
613 *json = NULL((void*)0);
614 }
615
616 if (r <= 0) {
617 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
617, ((void*)0)
, SWITCH_LOG_ALERT, "WRITE RETURNED ERROR %" SWITCH_SIZE_T_FMT"ld" " \n", r);
618 jsock->drop = 1;
619 jsock->ready = 0;
620 }
621
622 return r;
623}
624
625static switch_status_t jsock_queue_event(jsock_t *jsock, cJSON **json, switch_bool_t destroy)
626{
627 switch_status_t status = SWITCH_STATUS_FALSE;
628 cJSON *jp;
629
630 if (destroy) {
631 jp = *json;
632 } else {
633 jp = cJSON_Duplicate(*json, 1);
634 }
635
636 if (switch_queue_trypush(jsock->event_queue, jp) == SWITCH_STATUS_SUCCESS) {
637 status = SWITCH_STATUS_SUCCESS;
638
639 if (jsock->lost_events) {
640 int le = jsock->lost_events;
641 jsock->lost_events = 0;
642 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
642, ((void*)0)
, SWITCH_LOG_CRIT, "Lost %d json events!\n", le);
643 }
644 } else {
645 if (++jsock->lost_events > MAX_MISSED500) {
646 jsock->drop++;
647 }
648
649 if (!destroy) {
650 cJSON_Delete(jp);
651 jp = NULL((void*)0);
652 }
653 }
654
655 if (destroy) {
656 *json = NULL((void*)0);
657 }
658
659 return status;
660}
661
662static void write_event(const char *event_channel, jsock_t *use_jsock, cJSON *event)
663{
664 jsock_sub_node_head_t *head;
665
666 if ((head = switch_core_hash_find(globals.event_channel_hash, event_channel))) {
667 jsock_sub_node_t *np;
668
669 for(np = head->node; np; np = np->next) {
670 cJSON *msg = NULL((void*)0), *params;
671
672 if (!use_jsock || use_jsock == np->jsock) {
673 params = cJSON_Duplicate(event, 1);
674 cJSON_AddItemToObject(params, "eventSerno", cJSON_CreateNumber(np->serno++));
675 msg = jrpc_new_req("verto.event", NULL((void*)0), &params);
676 jsock_queue_event(np->jsock, &msg, SWITCH_TRUE);
677 }
678 }
679 }
680}
681
682static void jsock_send_event(cJSON *event)
683{
684
685 const char *event_channel, *session_uuid = NULL((void*)0);
686 jsock_t *use_jsock = NULL((void*)0);
687 switch_core_session_t *session = NULL((void*)0);
688
689 if (!(event_channel = cJSON_GetObjectCstr(event, "eventChannel"))) {
690 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
690, ((void*)0)
, SWITCH_LOG_ERROR, "NO EVENT CHANNEL SPECIFIED\n");
691 return;
692 }
693
694
695 if ((session = switch_core_session_locate(event_channel)switch_core_session_perform_locate(event_channel, "mod_verto.c"
, (const char *)__func__, 695)
)) {
696 switch_channel_t *channel = switch_core_session_get_channel(session);
697 const char *jsock_uuid_str = switch_channel_get_variable(channel, "jsock_uuid_str")switch_channel_get_variable_dup(channel, "jsock_uuid_str", SWITCH_TRUE
, -1)
;
698 if (jsock_uuid_str) {
699 use_jsock = get_jsock(jsock_uuid_str);
700 }
701 switch_core_session_rwunlock(session);
702 }
703
704 if (use_jsock || (use_jsock = get_jsock(event_channel))) { /* implicit subscription to channel identical to the connection uuid or session uuid */
705 cJSON *msg = NULL((void*)0), *params;
706 params = cJSON_Duplicate(event, 1);
707 msg = jrpc_new_req("verto.event", NULL((void*)0), &params);
708 jsock_queue_event(use_jsock, &msg, SWITCH_TRUE);
709 switch_thread_rwlock_unlock(use_jsock->rwlock);
710 use_jsock = NULL((void*)0);
711 return;
712 }
713
714
715 if ((session_uuid = cJSON_GetObjectCstr(event, "sessid"))) {
716 if (!(use_jsock = get_jsock(session_uuid))) {
717 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
717, ((void*)0)
, SWITCH_LOG_WARNING, "Socket %s not connected\n", session_uuid);
718 return;
719 }
720 }
721
722 switch_thread_rwlock_rdlock(globals.event_channel_rwlock);
723 write_event(event_channel, use_jsock, event);
724 if (strchr(event_channel, '.')(__extension__ (__builtin_constant_p ('.') && !__builtin_constant_p
(event_channel) && ('.') == '\0' ? (char *) __rawmemchr
(event_channel, '.') : __builtin_strchr (event_channel, '.')
))
) {
725 char *main_channel = strdup(event_channel)(__extension__ (__builtin_constant_p (event_channel) &&
((size_t)(const void *)((event_channel) + 1) - (size_t)(const
void *)(event_channel) == 1) ? (((const char *) (event_channel
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen (event_channel) + 1; char *__retval = (
char *) malloc (__len); if (__retval != ((void*)0)) __retval =
(char *) memcpy (__retval, event_channel, __len); __retval; }
)) : __strdup (event_channel)))
;
726 char *p = strchr(main_channel, '.')(__extension__ (__builtin_constant_p ('.') && !__builtin_constant_p
(main_channel) && ('.') == '\0' ? (char *) __rawmemchr
(main_channel, '.') : __builtin_strchr (main_channel, '.')))
;
727 if (p) *p = '\0';
728 write_event(main_channel, use_jsock, event);
729 free(main_channel);
730 }
731 switch_thread_rwlock_unlock(globals.event_channel_rwlock);
732
733 if (use_jsock) {
734 switch_thread_rwlock_unlock(use_jsock->rwlock);
735 use_jsock = NULL((void*)0);
736 }
737}
738
739static jrpc_func_t jrpc_get_func(jsock_t *jsock, const char *method)
740{
741 jrpc_func_t func = NULL((void*)0);
742 char *main_method = NULL((void*)0);
743
744 switch_assert(method)((method) ? (void) (0) : __assert_fail ("method", "mod_verto.c"
, 744, __PRETTY_FUNCTION__))
;
745
746 if (jsock->allowed_methods) {
747 if (strchr(method, '.')(__extension__ (__builtin_constant_p ('.') && !__builtin_constant_p
(method) && ('.') == '\0' ? (char *) __rawmemchr (method
, '.') : __builtin_strchr (method, '.')))
) {
748 char *p;
749 main_method = strdup(method)(__extension__ (__builtin_constant_p (method) && ((size_t
)(const void *)((method) + 1) - (size_t)(const void *)(method
) == 1) ? (((const char *) (method))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (method)
+ 1; char *__retval = (char *) malloc (__len); if (__retval !=
((void*)0)) __retval = (char *) memcpy (__retval, method, __len
); __retval; })) : __strdup (method)))
;
750 if ((p = strchr(main_method, '.')(__extension__ (__builtin_constant_p ('.') && !__builtin_constant_p
(main_method) && ('.') == '\0' ? (char *) __rawmemchr
(main_method, '.') : __builtin_strchr (main_method, '.')))
)) {
751 *p = '\0';
752 }
753 }
754
755 if (!(switch_event_get_header(jsock->allowed_methods, method)switch_event_get_header_idx(jsock->allowed_methods, method
, -1)
|| (main_method && switch_event_get_header(jsock->allowed_methods, main_method)switch_event_get_header_idx(jsock->allowed_methods, main_method
, -1)
))) {
756 goto end;
757 }
758 }
759
760 switch_mutex_lock(globals.method_mutex);
761 func = (jrpc_func_t) (intptr_t) switch_core_hash_find(globals.method_hash, method);
762 switch_mutex_unlock(globals.method_mutex);
763
764 end:
765
766 switch_safe_free(main_method)if (main_method) {free(main_method);main_method=((void*)0);};
767
768 return func;
769}
770
771
772static void jrpc_add_func(const char *method, jrpc_func_t func)
773{
774 switch_assert(method)((method) ? (void) (0) : __assert_fail ("method", "mod_verto.c"
, 774, __PRETTY_FUNCTION__))
;
775 switch_assert(func)((func) ? (void) (0) : __assert_fail ("func", "mod_verto.c", 775
, __PRETTY_FUNCTION__))
;
776
777 switch_mutex_lock(globals.method_mutex);
778 switch_core_hash_insert(globals.method_hash, method, (void *) (intptr_t) func)switch_core_hash_insert_destructor(globals.method_hash, method
, (void *) (intptr_t) func, ((void*)0))
;
779 switch_mutex_unlock(globals.method_mutex);
780}
781
782static char *MARKER = "X";
783
784static void set_perm(const char *str, switch_event_t **event)
785{
786 char delim = ',';
787 char *cur, *next;
788 int count = 0;
789 char *edup;
790
791 if (!zstr(str)_zstr(str)) {
792 if (!strcasecmp(str, "__ANY__")) {
793 return;
794 }
795 }
796
797 switch_event_create(event, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("mod_verto.c", (const char
* )(const char *)__func__, 797, event, SWITCH_EVENT_REQUEST_PARAMS
, ((void*)0))
;
798
799 if (!zstr(str)_zstr(str)) {
800 edup = strdup(str)(__extension__ (__builtin_constant_p (str) && ((size_t
)(const void *)((str) + 1) - (size_t)(const void *)(str) == 1
) ? (((const char *) (str))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (str) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, str, __len); __retval
; })) : __strdup (str)))
;
801 cur = edup;
802
803 if (strchr(edup, ' ')(__extension__ (__builtin_constant_p (' ') && !__builtin_constant_p
(edup) && (' ') == '\0' ? (char *) __rawmemchr (edup
, ' ') : __builtin_strchr (edup, ' ')))
) {
804 delim = ' ';
805 }
806
807 for (cur = edup; cur; count++) {
808 if ((next = strchr(cur, delim)(__extension__ (__builtin_constant_p (delim) && !__builtin_constant_p
(cur) && (delim) == '\0' ? (char *) __rawmemchr (cur
, delim) : __builtin_strchr (cur, delim)))
)) {
809 *next++ = '\0';
810 }
811
812 switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, cur, MARKER);
813
814 cur = next;
815 }
816
817 switch_safe_free(edup)if (edup) {free(edup);edup=((void*)0);};
818
819 }
820}
821
822static void check_permissions(jsock_t *jsock, switch_xml_t x_user, cJSON *params)
823{
824 switch_xml_t x_param, x_params;
825 const char *allowed_methods = NULL((void*)0), *allowed_jsapi = NULL((void*)0), *allowed_fsapi = NULL((void*)0), *allowed_event_channels = NULL((void*)0);
826
827 if ((x_params = switch_xml_child(x_user, "params"))) {
828 for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
829 const char *var = switch_xml_attr(x_param, "name");
830 const char *val = switch_xml_attr(x_param, "value");
831
832 if (zstr(val)_zstr(val) || zstr(var)_zstr(var)) {
833 continue;
834 }
835
836 if (!strcasecmp(var, "jsonrpc-allowed-methods")) {
837 allowed_methods = val;
838 }
839
840 if (!strcasecmp(var, "jsonrpc-allowed-jsapi")) {
841 allowed_jsapi = val;
842 }
843
844 if (!strcasecmp(var, "jsonrpc-allowed-fsapi")) {
845 allowed_fsapi = val;
846 }
847
848 if (!strcasecmp(var, "jsonrpc-allowed-event-channels")) {
849 allowed_event_channels = val;
850 }
851 }
852 }
853
854
855 set_perm(allowed_methods, &jsock->allowed_methods);
856 set_perm(allowed_jsapi, &jsock->allowed_jsapi);
857 set_perm(allowed_fsapi, &jsock->allowed_fsapi);
858 set_perm(allowed_event_channels, &jsock->allowed_event_channels);
859
860 switch_event_add_header_string(jsock->allowed_methods, SWITCH_STACK_BOTTOM, "login", MARKER);
861
862}
863
864static void login_fire_custom_event(jsock_t *jsock, cJSON *params, int success, const char *result_txt)
865{
866 switch_event_t *s_event;
867
868 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_LOGIN)switch_event_create_subclass_detailed("mod_verto.c", (const char
* )(const char *)__func__, 868, &s_event, SWITCH_EVENT_CUSTOM
, "verto::login")
== SWITCH_STATUS_SUCCESS) {
869 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "verto_profile_name", jsock->profile->name);
870 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "verto_client_address", jsock->name);
871 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "verto_login", cJSON_GetObjectCstr(params, "login"));
872 if (success) {
873 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "verto_sessid", cJSON_GetObjectCstr(params, "sessid"));
874 }
875 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "verto_success", "%d", success);
876 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "verto_result_txt", result_txt);
877 switch_event_fire(&s_event)switch_event_fire_detailed("mod_verto.c", (const char * )(const
char *)__func__, 877, &s_event, ((void*)0))
;
878 }
879}
880
881static switch_bool_t check_auth(jsock_t *jsock, cJSON *params, int *code, char *message, switch_size_t mlen)
882{
883 switch_bool_t r = SWITCH_FALSE;
884 const char *passwd = NULL((void*)0);
885 const char *login = NULL((void*)0);
886
887 if (!params) {
888 *code = CODE_AUTH_FAILED-32001;
889 switch_snprintf(message, mlen, "Missing params");
890 goto end;
891 }
892
893 login = cJSON_GetObjectCstr(params, "login");
894 passwd = cJSON_GetObjectCstr(params, "passwd");
895
896 if (zstr(login)_zstr(login)) {
897 goto end;
898 }
899
900 if (zstr(passwd)_zstr(passwd)) {
901 *code = CODE_AUTH_FAILED-32001;
902 switch_snprintf(message, mlen, "Missing passwd");
903 login_fire_custom_event(jsock, params, 0, "Missing passwd");
904 goto end;
905 }
906
907
908 if (!strcmp(login, "root")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(login) && __builtin_constant_p ("root") && (
__s1_len = __builtin_strlen (login), __s2_len = __builtin_strlen
("root"), (!((size_t)(const void *)((login) + 1) - (size_t)(
const void *)(login) == 1) || __s1_len >= 4) && (!
((size_t)(const void *)(("root") + 1) - (size_t)(const void *
)("root") == 1) || __s2_len >= 4)) ? __builtin_strcmp (login
, "root") : (__builtin_constant_p (login) && ((size_t
)(const void *)((login) + 1) - (size_t)(const void *)(login) ==
1) && (__s1_len = __builtin_strlen (login), __s1_len
< 4) ? (__builtin_constant_p ("root") && ((size_t
)(const void *)(("root") + 1) - (size_t)(const void *)("root"
) == 1) ? __builtin_strcmp (login, "root") : (__extension__ (
{ const unsigned char *__s2 = (const unsigned char *) (const char
*) ("root"); int __result = (((const unsigned char *) (const
char *) (login))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (login))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (login))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (login))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
("root") && ((size_t)(const void *)(("root") + 1) - (
size_t)(const void *)("root") == 1) && (__s2_len = __builtin_strlen
("root"), __s2_len < 4) ? (__builtin_constant_p (login) &&
((size_t)(const void *)((login) + 1) - (size_t)(const void *
)(login) == 1) ? __builtin_strcmp (login, "root") : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (login); int __result = (((const unsigned char *) (const
char *) ("root"))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("root"))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("root"))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ("root"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(login, "root")))); })
) {
909 if (!(r = !strcmp(passwd, jsock->profile->root_passwd)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(passwd) && __builtin_constant_p (jsock->profile->
root_passwd) && (__s1_len = __builtin_strlen (passwd)
, __s2_len = __builtin_strlen (jsock->profile->root_passwd
), (!((size_t)(const void *)((passwd) + 1) - (size_t)(const void
*)(passwd) == 1) || __s1_len >= 4) && (!((size_t)
(const void *)((jsock->profile->root_passwd) + 1) - (size_t
)(const void *)(jsock->profile->root_passwd) == 1) || __s2_len
>= 4)) ? __builtin_strcmp (passwd, jsock->profile->
root_passwd) : (__builtin_constant_p (passwd) && ((size_t
)(const void *)((passwd) + 1) - (size_t)(const void *)(passwd
) == 1) && (__s1_len = __builtin_strlen (passwd), __s1_len
< 4) ? (__builtin_constant_p (jsock->profile->root_passwd
) && ((size_t)(const void *)((jsock->profile->root_passwd
) + 1) - (size_t)(const void *)(jsock->profile->root_passwd
) == 1) ? __builtin_strcmp (passwd, jsock->profile->root_passwd
) : (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (jsock->profile->root_passwd); int
__result = (((const unsigned char *) (const char *) (passwd)
)[0] - __s2[0]); if (__s1_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (passwd
))[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (passwd
))[2] - __s2[2]); if (__s1_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (passwd
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
jsock->profile->root_passwd) && ((size_t)(const
void *)((jsock->profile->root_passwd) + 1) - (size_t)(
const void *)(jsock->profile->root_passwd) == 1) &&
(__s2_len = __builtin_strlen (jsock->profile->root_passwd
), __s2_len < 4) ? (__builtin_constant_p (passwd) &&
((size_t)(const void *)((passwd) + 1) - (size_t)(const void *
)(passwd) == 1) ? __builtin_strcmp (passwd, jsock->profile
->root_passwd) : (- (__extension__ ({ const unsigned char *
__s2 = (const unsigned char *) (const char *) (passwd); int __result
= (((const unsigned char *) (const char *) (jsock->profile
->root_passwd))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (jsock->profile->root_passwd))[1] - __s2[1]); if
(__s2_len > 1 && __result == 0) { __result = (((const
unsigned char *) (const char *) (jsock->profile->root_passwd
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (jsock->
profile->root_passwd))[3] - __s2[3]); } } __result; })))) :
__builtin_strcmp (passwd, jsock->profile->root_passwd)
))); })
)) {
910 *code = CODE_AUTH_FAILED-32001;
911 switch_snprintf(message, mlen, "Authentication Failure");
912 login_fire_custom_event(jsock, params, 0, "Authentication Failure");
913 }
914
915 } else if (!zstr(jsock->profile->userauth)_zstr(jsock->profile->userauth)) {
916 switch_xml_t x_user = NULL((void*)0);
917 char *id = NULL((void*)0), *domain = NULL((void*)0);
918 switch_event_t *req_params;
919
920 if (*jsock->profile->userauth == '@') {
921 domain = jsock->profile->userauth + 1;
922 id = (char *) login;
923 } else if (switch_true(jsock->profile->userauth)) {
924 id = switch_core_strdup(jsock->pool, login)switch_core_perform_strdup(jsock->pool, login, "mod_verto.c"
, (const char *)__func__, 924)
;
925
926 if ((domain = strchr(id, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(id) && ('@') == '\0' ? (char *) __rawmemchr (id, '@'
) : __builtin_strchr (id, '@')))
)) {
927 *domain++ = '\0';
928 }
929
930 }
931
932 if (!(id && domain)) {
933 *code = CODE_AUTH_FAILED-32001;
934 switch_snprintf(message, mlen, "Missing or improper credentials");
935 goto end;
936 }
937
938 switch_event_create(&req_params, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("mod_verto.c", (const char
* )(const char *)__func__, 938, &req_params, SWITCH_EVENT_REQUEST_PARAMS
, ((void*)0))
;
939 switch_assert(req_params)((req_params) ? (void) (0) : __assert_fail ("req_params", "mod_verto.c"
, 939, __PRETTY_FUNCTION__))
;
940
941 switch_event_add_header_string(req_params, SWITCH_STACK_BOTTOM, "action", "jsonrpc-authenticate");
942
943 if (switch_xml_locate_user_merged("id", id, domain, NULL((void*)0), &x_user, req_params) != SWITCH_STATUS_SUCCESS && !jsock->profile->blind_reg) {
944 *code = CODE_AUTH_FAILED-32001;
945 switch_snprintf(message, mlen, "Login Incorrect");
946 login_fire_custom_event(jsock, params, 0, "Login Incorrect");
947 } else {
948 switch_xml_t x_param, x_params;
949 const char *use_passwd = NULL((void*)0), *verto_context = NULL((void*)0), *verto_dialplan = NULL((void*)0);
950
951 jsock->id = switch_core_strdup(jsock->pool, id)switch_core_perform_strdup(jsock->pool, id, "mod_verto.c",
(const char *)__func__, 951)
;
952 jsock->domain = switch_core_strdup(jsock->pool, domain)switch_core_perform_strdup(jsock->pool, domain, "mod_verto.c"
, (const char *)__func__, 952)
;
953 jsock->uid = switch_core_sprintf(jsock->pool, "%s@%s", id, domain);
954 jsock->ready = 1;
955
956 if (!x_user) {
957 switch_event_destroy(&req_params);
958 r = SWITCH_TRUE;
959 goto end;
960 }
961
962 if ((x_params = switch_xml_child(x_user, "params"))) {
963 for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
964 const char *var = switch_xml_attr_soft(x_param, "name");
965 const char *val = switch_xml_attr_soft(x_param, "value");
966
967 if (!use_passwd && !strcasecmp(var, "password")) {
968 use_passwd = val;
969 } else if (!strcasecmp(var, "jsonrpc-password")) {
970 use_passwd = val;
971 } else if (!strcasecmp(var, "verto-context")) {
972 verto_context = val;
973 } else if (!strcasecmp(var, "verto-dialplan")) {
974 verto_dialplan = val;
975 }
976
977 switch_event_add_header_string(jsock->params, SWITCH_STACK_BOTTOM, var, val);
978 }
979 }
980
981 if ((x_params = switch_xml_child(x_user, "variables"))) {
982 for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
983 const char *var = switch_xml_attr_soft(x_param, "name");
984 const char *val = switch_xml_attr_soft(x_param, "value");
985
986 switch_event_add_header_string(jsock->vars, SWITCH_STACK_BOTTOM, var, val);
987 }
988 }
989
990 if (!zstr(verto_dialplan)_zstr(verto_dialplan)) {
991 jsock->dialplan = switch_core_strdup(jsock->pool, verto_dialplan)switch_core_perform_strdup(jsock->pool, verto_dialplan, "mod_verto.c"
, (const char *)__func__, 991)
;
992 }
993
994 if (!zstr(verto_context)_zstr(verto_context)) {
995 jsock->context = switch_core_strdup(jsock->pool, verto_context)switch_core_perform_strdup(jsock->pool, verto_context, "mod_verto.c"
, (const char *)__func__, 995)
;
996 }
997
998 if (zstr(use_passwd)_zstr(use_passwd) || strcmp(passwd, use_passwd)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(passwd) && __builtin_constant_p (use_passwd) &&
(__s1_len = __builtin_strlen (passwd), __s2_len = __builtin_strlen
(use_passwd), (!((size_t)(const void *)((passwd) + 1) - (size_t
)(const void *)(passwd) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((use_passwd) + 1) - (size_t)(const
void *)(use_passwd) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(passwd, use_passwd) : (__builtin_constant_p (passwd) &&
((size_t)(const void *)((passwd) + 1) - (size_t)(const void *
)(passwd) == 1) && (__s1_len = __builtin_strlen (passwd
), __s1_len < 4) ? (__builtin_constant_p (use_passwd) &&
((size_t)(const void *)((use_passwd) + 1) - (size_t)(const void
*)(use_passwd) == 1) ? __builtin_strcmp (passwd, use_passwd)
: (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (use_passwd); int __result = (((const
unsigned char *) (const char *) (passwd))[0] - __s2[0]); if (
__s1_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) (passwd))[1] - __s2[1]); if (
__s1_len > 1 && __result == 0) { __result = (((const
unsigned char *) (const char *) (passwd))[2] - __s2[2]); if (
__s1_len > 2 && __result == 0) __result = (((const
unsigned char *) (const char *) (passwd))[3] - __s2[3]); } }
__result; }))) : (__builtin_constant_p (use_passwd) &&
((size_t)(const void *)((use_passwd) + 1) - (size_t)(const void
*)(use_passwd) == 1) && (__s2_len = __builtin_strlen
(use_passwd), __s2_len < 4) ? (__builtin_constant_p (passwd
) && ((size_t)(const void *)((passwd) + 1) - (size_t)
(const void *)(passwd) == 1) ? __builtin_strcmp (passwd, use_passwd
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (passwd); int __result = (((const unsigned
char *) (const char *) (use_passwd))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (use_passwd))[1] - __s2[1]); if (__s2_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (use_passwd))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (use_passwd))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp (passwd, use_passwd)))); })
) {
999 r = SWITCH_FALSE;
1000 *code = CODE_AUTH_FAILED-32001;
1001 switch_snprintf(message, mlen, "Authentication Failure");
1002 jsock->uid = NULL((void*)0);
1003 login_fire_custom_event(jsock, params, 0, "Authentication Failure");
1004 } else {
1005 r = SWITCH_TRUE;
1006 check_permissions(jsock, x_user, params);
1007 }
1008
1009 switch_xml_free(x_user);
1010 }
1011
1012 switch_event_destroy(&req_params);
1013 }
1014
1015 end:
1016
1017 return r;
1018
1019}
1020
1021static void set_call_params(cJSON *params, verto_pvt_t *tech_pvt) {
1022 const char *caller_id_name = NULL((void*)0);
1023 const char *caller_id_number = NULL((void*)0);
1024 const char *callee_id_name = NULL((void*)0);
1025 const char *callee_id_number = NULL((void*)0);
1026
1027 caller_id_name = switch_channel_get_variable(tech_pvt->channel, "caller_id_name")switch_channel_get_variable_dup(tech_pvt->channel, "caller_id_name"
, SWITCH_TRUE, -1)
;
1028 caller_id_number = switch_channel_get_variable(tech_pvt->channel, "caller_id_number")switch_channel_get_variable_dup(tech_pvt->channel, "caller_id_number"
, SWITCH_TRUE, -1)
;
1029 callee_id_name = switch_channel_get_variable(tech_pvt->channel, "callee_id_name")switch_channel_get_variable_dup(tech_pvt->channel, "callee_id_name"
, SWITCH_TRUE, -1)
;
1030 callee_id_number = switch_channel_get_variable(tech_pvt->channel, "callee_id_number")switch_channel_get_variable_dup(tech_pvt->channel, "callee_id_number"
, SWITCH_TRUE, -1)
;
1031
1032 if (caller_id_name) cJSON_AddItemToObject(params, "caller_id_name", cJSON_CreateString(caller_id_name));
1033 if (caller_id_number) cJSON_AddItemToObject(params, "caller_id_number", cJSON_CreateString(caller_id_number));
1034
1035 if (callee_id_name) cJSON_AddItemToObject(params, "callee_id_name", cJSON_CreateString(callee_id_name));
1036 if (callee_id_number) cJSON_AddItemToObject(params, "callee_id_number", cJSON_CreateString(callee_id_number));
1037
1038 cJSON_AddItemToObject(params, "display_direction",
1039 cJSON_CreateString(switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"));
1040
1041
1042
1043}
1044
1045static jsock_t *get_jsock(const char *uuid)
1046{
1047 jsock_t *jsock = NULL((void*)0);
1048
1049 switch_mutex_lock(globals.jsock_mutex);
1050 if ((jsock = switch_core_hash_find(globals.jsock_hash, uuid))) {
1051 if (switch_thread_rwlock_tryrdlock(jsock->rwlock) != SWITCH_STATUS_SUCCESS) {
1052 jsock = NULL((void*)0);
1053 }
1054 }
1055 switch_mutex_unlock(globals.jsock_mutex);
1056
1057 return jsock;
1058}
1059
1060static void attach_jsock(jsock_t *jsock)
1061{
1062 switch_mutex_lock(globals.jsock_mutex);
1063 switch_core_hash_insert(globals.jsock_hash, jsock->uuid_str, jsock)switch_core_hash_insert_destructor(globals.jsock_hash, jsock->
uuid_str, jsock, ((void*)0))
;
1064 switch_mutex_unlock(globals.jsock_mutex);
1065}
1066
1067static void detach_jsock(jsock_t *jsock)
1068{
1069 switch_mutex_lock(globals.jsock_mutex);
1070 switch_core_hash_delete(globals.jsock_hash, jsock->uuid_str);
1071 switch_mutex_unlock(globals.jsock_mutex);
1072}
1073
1074static int attach_wake(void)
1075{
1076 switch_status_t status;
1077 int tries = 0;
1078
1079 top:
1080
1081 status = switch_mutex_trylock(globals.detach_mutex);
1082
1083 if (status == SWITCH_STATUS_SUCCESS) {
1084 switch_thread_cond_signal(globals.detach_cond);
1085 switch_mutex_unlock(globals.detach_mutex);
1086 return 1;
1087 } else {
1088 if (switch_mutex_trylock(globals.detach2_mutex) == SWITCH_STATUS_SUCCESS) {
1089 switch_mutex_unlock(globals.detach2_mutex);
1090 } else {
1091 if (++tries < 10) {
1092 switch_cond_next();
1093 goto top;
1094 }
1095 }
1096 }
1097
1098 return 0;
1099}
1100
1101static void tech_reattach(verto_pvt_t *tech_pvt, jsock_t *jsock)
1102{
1103 cJSON *params = NULL((void*)0);
1104 cJSON *msg = NULL((void*)0);
1105
1106 tech_pvt->detach_time = 0;
1107 globals.detached--;
1108 attach_wake();
1109 switch_set_flag(tech_pvt, TFLAG_ATTACH_REQ)(tech_pvt)->flags |= (TFLAG_ATTACH_REQ);
1110 msg = jrpc_new_req("verto.attach", tech_pvt->call_id, &params);
1111
1112 cJSON_AddItemToObject(params, "sdp", cJSON_CreateString(tech_pvt->mparams->local_sdp_str));
1113 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session)SWITCH_CHANNEL_ID_SESSION, "mod_verto.c", (const char *)__func__
, 1113, (const char*)(tech_pvt->session)
, SWITCH_LOG_DEBUG, "Local attach SDP %s:\n%s\n",
1114 switch_channel_get_name(tech_pvt->channel),
1115 tech_pvt->mparams->local_sdp_str);
1116 set_call_params(params, tech_pvt);
1117 jsock_queue_event(jsock, &msg, SWITCH_TRUE);
1118}
1119
1120static void drop_detached(void)
1121{
1122 verto_pvt_t *tech_pvt;
1123 switch_time_t now = switch_epoch_time_now(NULL((void*)0));
1124
1125 switch_thread_rwlock_rdlock(globals.tech_rwlock);
1126 for(tech_pvt = globals.tech_head; tech_pvt; tech_pvt = tech_pvt->next) {
1127 if (!switch_channel_up_nosig(tech_pvt->channel)(switch_channel_get_state(tech_pvt->channel) < CS_HANGUP
)
) {
1128 continue;
1129 }
1130
1131 if (tech_pvt->detach_time && (now - tech_pvt->detach_time) > globals.detach_timeout) {
1132 switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE)switch_channel_perform_hangup(tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 1132, SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE
)
;
1133 }
1134 }
1135 switch_thread_rwlock_unlock(globals.tech_rwlock);
1136}
1137
1138static void attach_calls(jsock_t *jsock)
1139{
1140 verto_pvt_t *tech_pvt;
1141
1142 switch_thread_rwlock_rdlock(globals.tech_rwlock);
1143 for(tech_pvt = globals.tech_head; tech_pvt; tech_pvt = tech_pvt->next) {
1144 if (tech_pvt->detach_time && !strcmp(tech_pvt->jsock_uuid, jsock->uuid_str)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(tech_pvt->jsock_uuid) && __builtin_constant_p (jsock
->uuid_str) && (__s1_len = __builtin_strlen (tech_pvt
->jsock_uuid), __s2_len = __builtin_strlen (jsock->uuid_str
), (!((size_t)(const void *)((tech_pvt->jsock_uuid) + 1) -
(size_t)(const void *)(tech_pvt->jsock_uuid) == 1) || __s1_len
>= 4) && (!((size_t)(const void *)((jsock->uuid_str
) + 1) - (size_t)(const void *)(jsock->uuid_str) == 1) || __s2_len
>= 4)) ? __builtin_strcmp (tech_pvt->jsock_uuid, jsock
->uuid_str) : (__builtin_constant_p (tech_pvt->jsock_uuid
) && ((size_t)(const void *)((tech_pvt->jsock_uuid
) + 1) - (size_t)(const void *)(tech_pvt->jsock_uuid) == 1
) && (__s1_len = __builtin_strlen (tech_pvt->jsock_uuid
), __s1_len < 4) ? (__builtin_constant_p (jsock->uuid_str
) && ((size_t)(const void *)((jsock->uuid_str) + 1
) - (size_t)(const void *)(jsock->uuid_str) == 1) ? __builtin_strcmp
(tech_pvt->jsock_uuid, jsock->uuid_str) : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (jsock->uuid_str); int __result = (((const unsigned
char *) (const char *) (tech_pvt->jsock_uuid))[0] - __s2[
0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (tech_pvt->jsock_uuid
))[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (tech_pvt
->jsock_uuid))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (tech_pvt->jsock_uuid))[3] - __s2[3]); } } __result; }
))) : (__builtin_constant_p (jsock->uuid_str) && (
(size_t)(const void *)((jsock->uuid_str) + 1) - (size_t)(const
void *)(jsock->uuid_str) == 1) && (__s2_len = __builtin_strlen
(jsock->uuid_str), __s2_len < 4) ? (__builtin_constant_p
(tech_pvt->jsock_uuid) && ((size_t)(const void *)
((tech_pvt->jsock_uuid) + 1) - (size_t)(const void *)(tech_pvt
->jsock_uuid) == 1) ? __builtin_strcmp (tech_pvt->jsock_uuid
, jsock->uuid_str) : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (tech_pvt->
jsock_uuid); int __result = (((const unsigned char *) (const char
*) (jsock->uuid_str))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (jsock->uuid_str))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (jsock->uuid_str))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (jsock->uuid_str))[3] - __s2[3]); }
} __result; })))) : __builtin_strcmp (tech_pvt->jsock_uuid
, jsock->uuid_str)))); })
) {
1145 if (!switch_channel_up_nosig(tech_pvt->channel)(switch_channel_get_state(tech_pvt->channel) < CS_HANGUP
)
) {
1146 continue;
1147 }
1148
1149 tech_reattach(tech_pvt, jsock);
1150 }
1151 }
1152 switch_thread_rwlock_unlock(globals.tech_rwlock);
1153}
1154
1155static void detach_calls(jsock_t *jsock)
1156{
1157 verto_pvt_t *tech_pvt;
1158
1159 switch_thread_rwlock_rdlock(globals.tech_rwlock);
1160 for(tech_pvt = globals.tech_head; tech_pvt; tech_pvt = tech_pvt->next) {
1161 if (!strcmp(tech_pvt->jsock_uuid, jsock->uuid_str)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(tech_pvt->jsock_uuid) && __builtin_constant_p (jsock
->uuid_str) && (__s1_len = __builtin_strlen (tech_pvt
->jsock_uuid), __s2_len = __builtin_strlen (jsock->uuid_str
), (!((size_t)(const void *)((tech_pvt->jsock_uuid) + 1) -
(size_t)(const void *)(tech_pvt->jsock_uuid) == 1) || __s1_len
>= 4) && (!((size_t)(const void *)((jsock->uuid_str
) + 1) - (size_t)(const void *)(jsock->uuid_str) == 1) || __s2_len
>= 4)) ? __builtin_strcmp (tech_pvt->jsock_uuid, jsock
->uuid_str) : (__builtin_constant_p (tech_pvt->jsock_uuid
) && ((size_t)(const void *)((tech_pvt->jsock_uuid
) + 1) - (size_t)(const void *)(tech_pvt->jsock_uuid) == 1
) && (__s1_len = __builtin_strlen (tech_pvt->jsock_uuid
), __s1_len < 4) ? (__builtin_constant_p (jsock->uuid_str
) && ((size_t)(const void *)((jsock->uuid_str) + 1
) - (size_t)(const void *)(jsock->uuid_str) == 1) ? __builtin_strcmp
(tech_pvt->jsock_uuid, jsock->uuid_str) : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (jsock->uuid_str); int __result = (((const unsigned
char *) (const char *) (tech_pvt->jsock_uuid))[0] - __s2[
0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (tech_pvt->jsock_uuid
))[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (tech_pvt
->jsock_uuid))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (tech_pvt->jsock_uuid))[3] - __s2[3]); } } __result; }
))) : (__builtin_constant_p (jsock->uuid_str) && (
(size_t)(const void *)((jsock->uuid_str) + 1) - (size_t)(const
void *)(jsock->uuid_str) == 1) && (__s2_len = __builtin_strlen
(jsock->uuid_str), __s2_len < 4) ? (__builtin_constant_p
(tech_pvt->jsock_uuid) && ((size_t)(const void *)
((tech_pvt->jsock_uuid) + 1) - (size_t)(const void *)(tech_pvt
->jsock_uuid) == 1) ? __builtin_strcmp (tech_pvt->jsock_uuid
, jsock->uuid_str) : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (tech_pvt->
jsock_uuid); int __result = (((const unsigned char *) (const char
*) (jsock->uuid_str))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (jsock->uuid_str))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (jsock->uuid_str))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (jsock->uuid_str))[3] - __s2[3]); }
} __result; })))) : __builtin_strcmp (tech_pvt->jsock_uuid
, jsock->uuid_str)))); })
) {
1162 if (!switch_channel_up_nosig(tech_pvt->channel)(switch_channel_get_state(tech_pvt->channel) < CS_HANGUP
)
) {
1163 continue;
1164 }
1165
1166 if (!switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED)) {
1167 switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 1167, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
1168 continue;
1169 }
1170
1171 tech_pvt->detach_time = switch_epoch_time_now(NULL((void*)0));
1172 globals.detached++;
1173 attach_wake();
1174 }
1175 }
1176 switch_thread_rwlock_unlock(globals.tech_rwlock);
1177}
1178
1179static void process_jrpc_response(jsock_t *jsock, cJSON *json)
1180{
1181}
1182
1183static void set_session_id(jsock_t *jsock, const char *uuid)
1184{
1185 //cJSON *params, *msg = jrpc_new(0);
1186
1187 if (!zstr(uuid)_zstr(uuid)) {
1188 switch_set_string(jsock->uuid_str, uuid)switch_copy_string(jsock->uuid_str, uuid, sizeof(jsock->
uuid_str))
;
1189 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
1189, ((void*)0)
, SWITCH_LOG_INFO, "%s re-connecting session %s\n", jsock->name, jsock->uuid_str);
1190 } else {
1191 switch_uuid_str(jsock->uuid_str, sizeof(jsock->uuid_str));
1192 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
1192, ((void*)0)
, SWITCH_LOG_INFO, "%s new RPC session %s\n", jsock->name, jsock->uuid_str);
1193 }
1194
1195 attach_jsock(jsock);
1196
1197}
1198
1199static cJSON *process_jrpc(jsock_t *jsock, cJSON *json)
1200{
1201 cJSON *reply = NULL((void*)0), *echo = NULL((void*)0), *id = NULL((void*)0), *params = NULL((void*)0), *response = NULL((void*)0), *result;
1202 const char *method = NULL((void*)0), *version = NULL((void*)0), *sessid = NULL((void*)0);
1203 jrpc_func_t func = NULL((void*)0);
1204
1205 switch_assert(json)((json) ? (void) (0) : __assert_fail ("json", "mod_verto.c", 1205
, __PRETTY_FUNCTION__))
;
1206
1207 method = cJSON_GetObjectCstr(json, "method");
1208 result = cJSON_GetObjectItem(json, "result");
1209 version = cJSON_GetObjectCstr(json, "jsonrpc");
1210 id = cJSON_GetObjectItem(json, "id");
1211
1212 if ((params = cJSON_GetObjectItem(json, "params"))) {
1213 sessid = cJSON_GetObjectCstr(params, "sessid");
1214 }
1215
1216 if (!switch_test_flag(jsock, JPFLAG_INIT)((jsock)->flags & JPFLAG_INIT)) {
1217 set_session_id(jsock, sessid);
1218 switch_set_flag(jsock, JPFLAG_INIT)(jsock)->flags |= (JPFLAG_INIT);
1219 }
1220
1221 if (zstr(version)_zstr(version) || strcmp(version, "2.0")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(version) && __builtin_constant_p ("2.0") &&
(__s1_len = __builtin_strlen (version), __s2_len = __builtin_strlen
("2.0"), (!((size_t)(const void *)((version) + 1) - (size_t)
(const void *)(version) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)(("2.0") + 1) - (size_t)(const void
*)("2.0") == 1) || __s2_len >= 4)) ? __builtin_strcmp (version
, "2.0") : (__builtin_constant_p (version) && ((size_t
)(const void *)((version) + 1) - (size_t)(const void *)(version
) == 1) && (__s1_len = __builtin_strlen (version), __s1_len
< 4) ? (__builtin_constant_p ("2.0") && ((size_t)
(const void *)(("2.0") + 1) - (size_t)(const void *)("2.0") ==
1) ? __builtin_strcmp (version, "2.0") : (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
("2.0"); int __result = (((const unsigned char *) (const char
*) (version))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
version))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
version))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (version
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
"2.0") && ((size_t)(const void *)(("2.0") + 1) - (size_t
)(const void *)("2.0") == 1) && (__s2_len = __builtin_strlen
("2.0"), __s2_len < 4) ? (__builtin_constant_p (version) &&
((size_t)(const void *)((version) + 1) - (size_t)(const void
*)(version) == 1) ? __builtin_strcmp (version, "2.0") : (- (
__extension__ ({ const unsigned char *__s2 = (const unsigned char
*) (const char *) (version); int __result = (((const unsigned
char *) (const char *) ("2.0"))[0] - __s2[0]); if (__s2_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) ("2.0"))[1] - __s2[1]); if (__s2_len > 1
&& __result == 0) { __result = (((const unsigned char
*) (const char *) ("2.0"))[2] - __s2[2]); if (__s2_len > 2
&& __result == 0) __result = (((const unsigned char *
) (const char *) ("2.0"))[3] - __s2[3]); } } __result; })))) :
__builtin_strcmp (version, "2.0")))); })
) {
1222 reply = jrpc_new(0);
1223 jrpc_add_error(reply, CODE_INVALID-32600, "Invalid message", id);
1224 goto end;
1225 }
1226
1227 if (result) {
1228 process_jrpc_response(jsock, json);
1229 return NULL((void*)0);
1230 }
1231
1232 reply = jrpc_new(0);
1233
1234 jrpc_add_id(reply, id, "", 0);
1235
1236 if (!switch_test_flag(jsock, JPFLAG_AUTHED)((jsock)->flags & JPFLAG_AUTHED) && (jsock->profile->userauth || jsock->profile->root_passwd)) {
1237 int code = CODE_AUTH_REQUIRED-32000;
1238 char message[128] = "Authentication Required";
1239
1240 if (!check_auth(jsock, params, &code, message, sizeof(message))) {
1241 jrpc_add_error(reply, code, message, id);
1242 goto end;
1243 }
1244 switch_set_flag(jsock, JPFLAG_AUTHED)(jsock)->flags |= (JPFLAG_AUTHED);
1245 }
1246
1247 if (!method || !(func = jrpc_get_func(jsock, method))) {
1248 jrpc_add_error(reply, -32601, "Invalid Method, Missing Method or Permission Denied", id);
1249 } else {
1250 if (func(method, params, jsock, &response) == SWITCH_TRUE) {
1251
1252 if (params) {
1253 echo = cJSON_GetObjectItem(params, "echoParams");
1254 }
1255 if (echo) {
1256 if ((echo->type == cJSON_True1 || (echo->type == cJSON_String4 && switch_true(echo->valuestring)))) {
1257 cJSON_AddItemToObject(response, "requestParams", cJSON_Duplicate(params, 1));
1258 } else {
1259 cJSON_AddItemToObject(response, "requestParams", cJSON_Duplicate(echo, 1));
1260 }
1261 }
1262
1263 jrpc_add_result(reply, response);
1264 } else {
1265 if (response) {
1266 cJSON_AddItemToObject(reply, "error", response);
1267 } else {
1268 jrpc_add_error(reply, -32602, "Permission Denied", id);
1269 }
1270 }
1271 }
1272
1273 end:
1274
1275 return reply;
1276}
1277
1278static switch_status_t process_input(jsock_t *jsock, uint8_t *data, switch_ssize_t bytes)
1279{
1280 cJSON *json = NULL((void*)0), *reply = NULL((void*)0);
1281 char *ascii = (char *) data;
1282 switch_status_t status = SWITCH_STATUS_SUCCESS;
1283
1284 if (ascii) {
1285 json = cJSON_Parse(ascii);
1286 }
1287
1288 if (json) {
1289
1290 if (jsock->profile->debug || globals.debug) {
1291 char *log_text = cJSON_Print(json);
1292 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
1292, ((void*)0)
, SWITCH_LOG_ALERT, "READ %s [%s]\n", jsock->name, log_text);
1293 free(log_text);
1294 }
1295
1296 if (json->type == cJSON_Array5) { /* batch mode */
1297 int i, len = cJSON_GetArraySize(json);
1298
1299 reply = cJSON_CreateArray();
1300
1301 for(i = 0; i < len; i++) {
1302 cJSON *obj, *item = cJSON_GetArrayItem(json, i);
1303
1304 if ((obj = process_jrpc(jsock, item))) {
1305 cJSON_AddItemToArray(reply, obj);
1306 }
1307 }
1308 } else {
1309 reply = process_jrpc(jsock, json);
1310 }
1311 } else {
1312 reply = jrpc_new(0);
1313 jrpc_add_error(reply, -32600, "Invalid Request", NULL((void*)0));
1314 }
1315
1316 if (reply) {
1317 ws_write_json(jsock, &reply, SWITCH_TRUE);
1318 }
1319
1320 if (json) {
1321 cJSON_Delete(json);
1322 }
1323
1324 return status;
1325}
1326
1327static void jsock_check_event_queue(jsock_t *jsock)
1328{
1329 void *pop;
1330 int this_pass = switch_queue_size(jsock->event_queue);
1331
1332 switch_mutex_lock(jsock->write_mutex);
1333 while(this_pass-- > 0 && switch_queue_trypop(jsock->event_queue, &pop) == SWITCH_STATUS_SUCCESS) {
1334 cJSON *json = (cJSON *) pop;
1335 ws_write_json(jsock, &json, SWITCH_TRUE);
1336 }
1337 switch_mutex_unlock(jsock->write_mutex);
1338}
1339
1340/* DO NOT use this unless you know what you are doing, you are WARNNED!!! */
1341static uint8_t *http_stream_read(switch_stream_handle_t *handle, int *len)
1342{
1343 switch_http_request_t *r = (switch_http_request_t *) handle->data;
1344 jsock_t *jsock = r->user_data;
1345 wsh_t *wsh = &jsock->ws;
1346
1347 if (!jsock->profile->running) {
1348 *len = 0;
1349 return NULL((void*)0);
1350 }
1351
1352 *len = r->bytes_buffered - r->bytes_read;
1353
1354 if (*len > 0) { // we already read part of the body
1355 uint8_t *data = (uint8_t *)wsh->buffer + r->bytes_read;
1356 r->bytes_read = r->bytes_buffered;
1357 return data;
1358 }
1359
1360 if (r->content_length && (r->bytes_read - r->bytes_header) >= r->content_length) {
1361 *len = 0;
1362 return NULL((void*)0);
1363 }
1364
1365 *len = r->content_length - (r->bytes_read - r->bytes_header);
1366 *len = *len > sizeof(wsh->buffer) ? sizeof(wsh->buffer) : *len;
1367
1368 if ((*len = ws_raw_read(wsh, wsh->buffer, *len, wsh->block)) < 0) {
1369 *len = 0;
1370 return NULL((void*)0);
1371 }
1372
1373 r->bytes_read += *len;
1374
1375 return (uint8_t *)wsh->buffer;
1376}
1377
1378static switch_status_t http_stream_raw_write(switch_stream_handle_t *handle, uint8_t *data, switch_size_t datalen)
1379{
1380 switch_http_request_t *r = (switch_http_request_t *) handle->data;
1381 jsock_t *jsock = r->user_data;
1382
1383 return ws_raw_write(&jsock->ws, data, (uint32_t)datalen) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
1384}
1385
1386static switch_status_t http_stream_write(switch_stream_handle_t *handle, const char *fmt, ...)
1387{
1388 switch_http_request_t *r = (switch_http_request_t *) handle->data;
1389 jsock_t *jsock = r->user_data;
1390 int ret = 1;
1391 char *data;
1392 va_list ap;
1393
1394 va_start(ap, fmt)__builtin_va_start(ap, fmt);
1395 ret = switch_vasprintf(&data, fmt, ap);
1396 va_end(ap)__builtin_va_end(ap);
1397
1398 if (data) {
1399 if (ret) {
1400 ret = ws_raw_write(&jsock->ws, data, (uint32_t)strlen(data));
1401 }
1402 switch_safe_free(data)if (data) {free(data);data=((void*)0);};
1403 }
1404
1405 return ret ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
1406}
1407
1408static void http_static_handler(switch_http_request_t *request, verto_vhost_t *vhost)
1409{
1410 jsock_t *jsock = request->user_data;
1411 char path[512];
1412 switch_file_t *fd;
1413 char *ext;
1414 uint8_t chunk[4096];
1415 const char *mime_type = "text/html", *new_type;
1416
1417 if (strncmp(request->method, "GET", 3)(__extension__ (__builtin_constant_p (3) && ((__builtin_constant_p
(request->method) && strlen (request->method) <
((size_t) (3))) || (__builtin_constant_p ("GET") && strlen
("GET") < ((size_t) (3)))) ? __extension__ ({ size_t __s1_len
, __s2_len; (__builtin_constant_p (request->method) &&
__builtin_constant_p ("GET") && (__s1_len = __builtin_strlen
(request->method), __s2_len = __builtin_strlen ("GET"), (
!((size_t)(const void *)((request->method) + 1) - (size_t)
(const void *)(request->method) == 1) || __s1_len >= 4)
&& (!((size_t)(const void *)(("GET") + 1) - (size_t)
(const void *)("GET") == 1) || __s2_len >= 4)) ? __builtin_strcmp
(request->method, "GET") : (__builtin_constant_p (request
->method) && ((size_t)(const void *)((request->
method) + 1) - (size_t)(const void *)(request->method) == 1
) && (__s1_len = __builtin_strlen (request->method
), __s1_len < 4) ? (__builtin_constant_p ("GET") &&
((size_t)(const void *)(("GET") + 1) - (size_t)(const void *
)("GET") == 1) ? __builtin_strcmp (request->method, "GET")
: (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) ("GET"); int __result = (((const unsigned
char *) (const char *) (request->method))[0] - __s2[0]); if
(__s1_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) (request->method))[1] - __s2
[1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (request->method
))[2] - __s2[2]); if (__s1_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (request
->method))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
("GET") && ((size_t)(const void *)(("GET") + 1) - (size_t
)(const void *)("GET") == 1) && (__s2_len = __builtin_strlen
("GET"), __s2_len < 4) ? (__builtin_constant_p (request->
method) && ((size_t)(const void *)((request->method
) + 1) - (size_t)(const void *)(request->method) == 1) ? __builtin_strcmp
(request->method, "GET") : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (request
->method); int __result = (((const unsigned char *) (const
char *) ("GET"))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("GET"))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("GET"))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ("GET"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(request->method, "GET")))); }) : strncmp (request->method
, "GET", 3)))
&& strncmp(request->method, "HEAD", 4)(__extension__ (__builtin_constant_p (4) && ((__builtin_constant_p
(request->method) && strlen (request->method) <
((size_t) (4))) || (__builtin_constant_p ("HEAD") &&
strlen ("HEAD") < ((size_t) (4)))) ? __extension__ ({ size_t
__s1_len, __s2_len; (__builtin_constant_p (request->method
) && __builtin_constant_p ("HEAD") && (__s1_len
= __builtin_strlen (request->method), __s2_len = __builtin_strlen
("HEAD"), (!((size_t)(const void *)((request->method) + 1
) - (size_t)(const void *)(request->method) == 1) || __s1_len
>= 4) && (!((size_t)(const void *)(("HEAD") + 1) -
(size_t)(const void *)("HEAD") == 1) || __s2_len >= 4)) ?
__builtin_strcmp (request->method, "HEAD") : (__builtin_constant_p
(request->method) && ((size_t)(const void *)((request
->method) + 1) - (size_t)(const void *)(request->method
) == 1) && (__s1_len = __builtin_strlen (request->
method), __s1_len < 4) ? (__builtin_constant_p ("HEAD") &&
((size_t)(const void *)(("HEAD") + 1) - (size_t)(const void *
)("HEAD") == 1) ? __builtin_strcmp (request->method, "HEAD"
) : (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) ("HEAD"); int __result = (((const unsigned
char *) (const char *) (request->method))[0] - __s2[0]); if
(__s1_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) (request->method))[1] - __s2
[1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (request->method
))[2] - __s2[2]); if (__s1_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (request
->method))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
("HEAD") && ((size_t)(const void *)(("HEAD") + 1) - (
size_t)(const void *)("HEAD") == 1) && (__s2_len = __builtin_strlen
("HEAD"), __s2_len < 4) ? (__builtin_constant_p (request->
method) && ((size_t)(const void *)((request->method
) + 1) - (size_t)(const void *)(request->method) == 1) ? __builtin_strcmp
(request->method, "HEAD") : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (request
->method); int __result = (((const unsigned char *) (const
char *) ("HEAD"))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("HEAD"))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("HEAD"))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ("HEAD"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(request->method, "HEAD")))); }) : strncmp (request->method
, "HEAD", 4)))
) {
1418 char *data = "HTTP/1.1 415 Method Not Allowed\r\n"
1419 "Content-Length: 0\r\n\r\n";
1420 ws_raw_write(&jsock->ws, data, strlen(data));
1421 return;
1422 }
1423
1424 switch_snprintf(path, sizeof(path), "%s%s", vhost->root, request->uri);
1425
1426 if (switch_directory_exists(path, NULL((void*)0)) == SWITCH_STATUS_SUCCESS) {
1427 switch_snprintf(path, sizeof(path), "%s%s%s%s",
1428 vhost->root, request->uri, end_of(path)*(*path == '\0' ? path : path + strlen(path) - 1) == '/' ? "" : SWITCH_PATH_SEPARATOR"/", vhost->index);
1429 // printf("local path: %s\n", path);
1430 }
1431
1432 if ((ext = strrchr(path, '.'))) {
1433 ext++;
1434 if ((new_type = switch_core_mime_ext2type(ext))) {
1435 mime_type = new_type;
1436 }
1437 }
1438
1439 if (switch_file_exists(path, NULL((void*)0)) == SWITCH_STATUS_SUCCESS &&
1440 switch_file_open(&fd, path, SWITCH_FOPEN_READ0x00001, SWITCH_FPROT_UREAD0x0400, jsock->pool) == SWITCH_STATUS_SUCCESS) {
1441
1442 switch_size_t flen = switch_file_get_size(fd);
1443
1444 switch_snprintf((char *)chunk, sizeof(chunk),
1445 "HTTP/1.1 200 OK\r\n"
1446 "Date: %s\r\n"
1447 "Server: FreeSWITCH-%s-mod_verto\r\n"
1448 "Content-Type: %s\r\n"
1449 "Content-Length: %" SWITCH_SIZE_T_FMT"ld" "\r\n\r\n",
1450 switch_event_get_header(request->headers, "Event-Date-GMT")switch_event_get_header_idx(request->headers, "Event-Date-GMT"
, -1)
,
1451 switch_version_full(),
1452 mime_type,
1453 flen);
1454
1455 ws_raw_write(&jsock->ws, chunk, strlen((char *)chunk));
1456
1457 for (;;) {
1458 switch_status_t status;
1459 ssize_t written = 0;
1460 ssize_t ret = 0;
1461 int sanity = 3;
1462
1463 flen = sizeof(chunk);
1464 status = switch_file_read(fd, chunk, &flen);
1465
1466 if (status != SWITCH_STATUS_SUCCESS || flen == 0) {
1467 break;
1468 }
1469
1470again:
1471 ret = ws_raw_write(&jsock->ws, chunk + written, flen);
1472 if (ret == -1) {
1473 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
1473, ((void*)0)
, SWITCH_LOG_ERROR, "error write %" SWITCH_SIZE_T_FMT"ld" " bytes!\n", flen);
1474 ws_close(&jsock->ws, WS_NONE);
1475 } else if (ret > 0 && ret < flen && sanity > 0) {
1476 switch_yield(1000)switch_sleep(1000);;
1477 flen -= ret;
1478 written += ret;
1479 goto again;
1480 }
1481 }
1482 switch_file_close(fd);
1483 } else {
1484 char *data = "HTTP/1.1 404 Not Found\r\n"
1485 "Content-Length: 0\r\n\r\n";
1486 ws_raw_write(&jsock->ws, data, strlen(data));
1487 }
1488}
1489
1490static void http_run(jsock_t *jsock)
1491{
1492 switch_http_request_t request = { 0 };
1493 switch_stream_handle_t stream = { 0 };
1494 char *data = NULL((void*)0);
1495 char *ext;
1496 verto_vhost_t *vhost;
1497 switch_bool_t keepalive;
1498
1499new_req:
1500
1501 request.user_data = jsock;
1502
1503 if (switch_event_create(&stream.param_event, SWITCH_EVENT_CHANNEL_DATA)switch_event_create_subclass_detailed("mod_verto.c", (const char
* )(const char *)__func__, 1503, &stream.param_event, SWITCH_EVENT_CHANNEL_DATA
, ((void*)0))
!= SWITCH_STATUS_SUCCESS) {
1
Taking false branch
51
Taking false branch
1504 goto err;
1505 }
1506
1507 request.headers = stream.param_event;
1508 if (switch_http_parse_header(jsock->ws.buffer, jsock->ws.datalen, &request) != SWITCH_STATUS_SUCCESS) {
2
Taking false branch
52
Taking false branch
1509 switch_event_destroy(&stream.param_event);
1510 goto err;
1511 }
1512
1513 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
1513, ((void*)0)
, SWITCH_LOG_DEBUG, "%s [%4" SWITCH_SIZE_T_FMT"ld" "] %s\n", jsock->name, jsock->ws.datalen, request.uri);
1514
1515 if (!strncmp(request.method, "OPTIONS", 7)(__extension__ (__builtin_constant_p (7) && ((__builtin_constant_p
(request.method) && strlen (request.method) < ((size_t
) (7))) || (__builtin_constant_p ("OPTIONS") && strlen
("OPTIONS") < ((size_t) (7)))) ? __extension__ ({ size_t __s1_len
, __s2_len; (__builtin_constant_p (request.method) &&
__builtin_constant_p ("OPTIONS") && (__s1_len = __builtin_strlen
(request.method), __s2_len = __builtin_strlen ("OPTIONS"), (
!((size_t)(const void *)((request.method) + 1) - (size_t)(const
void *)(request.method) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)(("OPTIONS") + 1) - (size_t)(const void
*)("OPTIONS") == 1) || __s2_len >= 4)) ? __builtin_strcmp
(request.method, "OPTIONS") : (__builtin_constant_p (request
.method) && ((size_t)(const void *)((request.method) +
1) - (size_t)(const void *)(request.method) == 1) &&
(__s1_len = __builtin_strlen (request.method), __s1_len <
4) ? (__builtin_constant_p ("OPTIONS") && ((size_t)(
const void *)(("OPTIONS") + 1) - (size_t)(const void *)("OPTIONS"
) == 1) ? __builtin_strcmp (request.method, "OPTIONS") : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ("OPTIONS"); int __result = (((const unsigned char *
) (const char *) (request.method))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (request.method))[1] - __s2[1]); if (
__s1_len > 1 && __result == 0) { __result = (((const
unsigned char *) (const char *) (request.method))[2] - __s2[
2]); if (__s1_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) (request.method))[3
] - __s2[3]); } } __result; }))) : (__builtin_constant_p ("OPTIONS"
) && ((size_t)(const void *)(("OPTIONS") + 1) - (size_t
)(const void *)("OPTIONS") == 1) && (__s2_len = __builtin_strlen
("OPTIONS"), __s2_len < 4) ? (__builtin_constant_p (request
.method) && ((size_t)(const void *)((request.method) +
1) - (size_t)(const void *)(request.method) == 1) ? __builtin_strcmp
(request.method, "OPTIONS") : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (request
.method); int __result = (((const unsigned char *) (const char
*) ("OPTIONS"))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("OPTIONS"))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("OPTIONS"))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ("OPTIONS"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(request.method, "OPTIONS")))); }) : strncmp (request.method
, "OPTIONS", 7)))
) {
3
Taking false branch
53
Taking false branch
1516 char data[512];
1517 switch_snprintf(data, sizeof(data),
1518 "HTTP/1.1 200 OK\r\n"
1519 "Content-Length: 0\r\n"
1520 "Date: %s\r\n"
1521 "Allow: HEAD,GET,POST,PUT,DELETE,PATCH,OPTIONS\r\n"
1522 "Server: FreeSWITCH-%s-mod_verto\r\n\r\n",
1523 switch_event_get_header(request.headers, "Event-Date-GMT")switch_event_get_header_idx(request.headers, "Event-Date-GMT"
, -1)
,
1524 switch_version_full());
1525
1526 ws_raw_write(&jsock->ws, data, strlen(data));
1527 goto done;
1528 }
1529
1530 if (!strncmp(request.method, "POST", 4)(__extension__ (__builtin_constant_p (4) && ((__builtin_constant_p
(request.method) && strlen (request.method) < ((size_t
) (4))) || (__builtin_constant_p ("POST") && strlen (
"POST") < ((size_t) (4)))) ? __extension__ ({ size_t __s1_len
, __s2_len; (__builtin_constant_p (request.method) &&
__builtin_constant_p ("POST") && (__s1_len = __builtin_strlen
(request.method), __s2_len = __builtin_strlen ("POST"), (!((
size_t)(const void *)((request.method) + 1) - (size_t)(const void
*)(request.method) == 1) || __s1_len >= 4) && (!(
(size_t)(const void *)(("POST") + 1) - (size_t)(const void *)
("POST") == 1) || __s2_len >= 4)) ? __builtin_strcmp (request
.method, "POST") : (__builtin_constant_p (request.method) &&
((size_t)(const void *)((request.method) + 1) - (size_t)(const
void *)(request.method) == 1) && (__s1_len = __builtin_strlen
(request.method), __s1_len < 4) ? (__builtin_constant_p (
"POST") && ((size_t)(const void *)(("POST") + 1) - (size_t
)(const void *)("POST") == 1) ? __builtin_strcmp (request.method
, "POST") : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) ("POST"); int __result = (((
const unsigned char *) (const char *) (request.method))[0] - __s2
[0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (request.method))
[1] - __s2[1]); if (__s1_len > 1 && __result == 0)
{ __result = (((const unsigned char *) (const char *) (request
.method))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (request
.method))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
("POST") && ((size_t)(const void *)(("POST") + 1) - (
size_t)(const void *)("POST") == 1) && (__s2_len = __builtin_strlen
("POST"), __s2_len < 4) ? (__builtin_constant_p (request.
method) && ((size_t)(const void *)((request.method) +
1) - (size_t)(const void *)(request.method) == 1) ? __builtin_strcmp
(request.method, "POST") : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (request
.method); int __result = (((const unsigned char *) (const char
*) ("POST"))[0] - __s2[0]); if (__s2_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
"POST"))[1] - __s2[1]); if (__s2_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
"POST"))[2] - __s2[2]); if (__s2_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) ("POST"
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (request
.method, "POST")))); }) : strncmp (request.method, "POST", 4)
))
&& request.content_length &&
1531 !strncmp(request.content_type, "application/x-www-form-urlencoded", 33)(__extension__ (__builtin_constant_p (33) && ((__builtin_constant_p
(request.content_type) && strlen (request.content_type
) < ((size_t) (33))) || (__builtin_constant_p ("application/x-www-form-urlencoded"
) && strlen ("application/x-www-form-urlencoded") <
((size_t) (33)))) ? __extension__ ({ size_t __s1_len, __s2_len
; (__builtin_constant_p (request.content_type) && __builtin_constant_p
("application/x-www-form-urlencoded") && (__s1_len =
__builtin_strlen (request.content_type), __s2_len = __builtin_strlen
("application/x-www-form-urlencoded"), (!((size_t)(const void
*)((request.content_type) + 1) - (size_t)(const void *)(request
.content_type) == 1) || __s1_len >= 4) && (!((size_t
)(const void *)(("application/x-www-form-urlencoded") + 1) - (
size_t)(const void *)("application/x-www-form-urlencoded") ==
1) || __s2_len >= 4)) ? __builtin_strcmp (request.content_type
, "application/x-www-form-urlencoded") : (__builtin_constant_p
(request.content_type) && ((size_t)(const void *)((request
.content_type) + 1) - (size_t)(const void *)(request.content_type
) == 1) && (__s1_len = __builtin_strlen (request.content_type
), __s1_len < 4) ? (__builtin_constant_p ("application/x-www-form-urlencoded"
) && ((size_t)(const void *)(("application/x-www-form-urlencoded"
) + 1) - (size_t)(const void *)("application/x-www-form-urlencoded"
) == 1) ? __builtin_strcmp (request.content_type, "application/x-www-form-urlencoded"
) : (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) ("application/x-www-form-urlencoded")
; int __result = (((const unsigned char *) (const char *) (request
.content_type))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (request.content_type))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (request.content_type))[2] - __s2[2]); if (
__s1_len > 2 && __result == 0) __result = (((const
unsigned char *) (const char *) (request.content_type))[3] -
__s2[3]); } } __result; }))) : (__builtin_constant_p ("application/x-www-form-urlencoded"
) && ((size_t)(const void *)(("application/x-www-form-urlencoded"
) + 1) - (size_t)(const void *)("application/x-www-form-urlencoded"
) == 1) && (__s2_len = __builtin_strlen ("application/x-www-form-urlencoded"
), __s2_len < 4) ? (__builtin_constant_p (request.content_type
) && ((size_t)(const void *)((request.content_type) +
1) - (size_t)(const void *)(request.content_type) == 1) ? __builtin_strcmp
(request.content_type, "application/x-www-form-urlencoded") :
(- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (request.content_type); int __result =
(((const unsigned char *) (const char *) ("application/x-www-form-urlencoded"
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) ("application/x-www-form-urlencoded"
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) ("application/x-www-form-urlencoded"
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) ("application/x-www-form-urlencoded"
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (request
.content_type, "application/x-www-form-urlencoded")))); }) : strncmp
(request.content_type, "application/x-www-form-urlencoded", 33
)))
) {
1532
1533 char *buffer = NULL((void*)0);
1534 switch_ssize_t len = 0, bytes = 0;
1535
1536 if (request.content_length > 2 * 1024 * 1024 - 1) {
1537 char *data = "HTTP/1.1 413 Request Entity Too Large\r\n"
1538 "Content-Length: 0\r\n\r\n";
1539 ws_raw_write(&jsock->ws, data, strlen(data));
1540 goto done;
1541 }
1542
1543 if (!(buffer = malloc(2 * 1024 * 1024))) {
1544 goto request_err;
1545 }
1546
1547 if ((bytes = request.bytes_buffered - (request.bytes_read - request.bytes_header)) > 0) {
1548 memcpy(buffer, jsock->ws.buffer + request.bytes_read, bytes);
1549 }
1550
1551 while(bytes < request.content_length) {
1552 len = request.content_length - bytes;
1553
1554 if ((len = ws_raw_read(&jsock->ws, buffer + bytes, len, jsock->ws.block)) < 0) {
1555 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
1555, ((void*)0)
, SWITCH_LOG_ERROR, "Read error %" SWITCH_SSIZE_T_FMT"ld""\n", len);
1556 goto done;
1557 }
1558
1559 bytes += len;
1560 }
1561
1562 *(buffer + bytes) = '\0';
1563
1564 switch_http_parse_qs(&request, buffer);
1565 free(buffer);
1566 }
1567
1568 // switch_http_dump_request(&request);
1569
1570 stream.data = &request;
1571 stream.read_function = http_stream_read;
1572 stream.write_function = http_stream_write;
1573 stream.raw_write_function = http_stream_raw_write;
1574
1575 switch_event_add_header_string(request.headers, SWITCH_STACK_BOTTOM, "Request-Method", request.method);
1576 switch_event_add_header_string(request.headers, SWITCH_STACK_BOTTOM, "HTTP-Request-URI", request.uri);
1577
1578 if (!jsock->profile->vhosts) goto err;
4
Taking false branch
54
Taking false branch
1579
1580 /* only one vhost supported for now */
1581 vhost = jsock->profile->vhosts;
1582
1583 if (!switch_test_flag(jsock, JPFLAG_AUTHED)((jsock)->flags & JPFLAG_AUTHED) && vhost->auth_realm) {
55
Taking true branch
1584 int code = CODE_AUTH_REQUIRED-32000;
1585 char message[128] = "Authentication Required";
1586 cJSON *params = NULL((void*)0);
1587 char *www_auth;
1588 char auth_buffer[512];
1589 char *auth_user = NULL((void*)0), *auth_pass = NULL((void*)0);
1590
1591 www_auth = switch_event_get_header(request.headers, "Authorization")switch_event_get_header_idx(request.headers, "Authorization",
-1)
;
1592
1593 if (zstr(www_auth)_zstr(www_auth)) {
56
Taking false branch
1594 switch_snprintf(auth_buffer, sizeof(auth_buffer),
1595 "HTTP/1.1 401 Authentication Required\r\n"
1596 "WWW-Authenticate: Basic realm=\"%s\"\r\n"
1597 "Content-Length: 0\r\n\r\n",
1598 vhost->auth_realm);
1599 ws_raw_write(&jsock->ws, auth_buffer, strlen(auth_buffer));
1600 goto done;
1601 }
1602
1603 if (strncasecmp(www_auth, "Basic ", 6)) goto err;
57
Taking false branch
1604
1605 www_auth += 6;
1606
1607 switch_b64_decode(www_auth, auth_buffer, sizeof(auth_buffer));
1608
1609 auth_user = auth_buffer;
1610
1611 if ((auth_pass = strchr(auth_user, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(auth_user) && (':') == '\0' ? (char *) __rawmemchr (
auth_user, ':') : __builtin_strchr (auth_user, ':')))
)) {
58
Value assigned to 'auth_pass'
59
Assuming 'auth_pass' is null
60
Assuming pointer value is null
61
Taking false branch
1612 *auth_pass++ = '\0';
1613 }
1614
1615 if (vhost->auth_user && vhost->auth_pass &&
1616 !strcmp(vhost->auth_user, auth_user)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(vhost->auth_user) && __builtin_constant_p (auth_user
) && (__s1_len = __builtin_strlen (vhost->auth_user
), __s2_len = __builtin_strlen (auth_user), (!((size_t)(const
void *)((vhost->auth_user) + 1) - (size_t)(const void *)(
vhost->auth_user) == 1) || __s1_len >= 4) && (!
((size_t)(const void *)((auth_user) + 1) - (size_t)(const void
*)(auth_user) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(vhost->auth_user, auth_user) : (__builtin_constant_p (vhost
->auth_user) && ((size_t)(const void *)((vhost->
auth_user) + 1) - (size_t)(const void *)(vhost->auth_user)
== 1) && (__s1_len = __builtin_strlen (vhost->auth_user
), __s1_len < 4) ? (__builtin_constant_p (auth_user) &&
((size_t)(const void *)((auth_user) + 1) - (size_t)(const void
*)(auth_user) == 1) ? __builtin_strcmp (vhost->auth_user,
auth_user) : (__extension__ ({ const unsigned char *__s2 = (
const unsigned char *) (const char *) (auth_user); int __result
= (((const unsigned char *) (const char *) (vhost->auth_user
))[0] - __s2[0]); if (__s1_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (vhost
->auth_user))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (vhost->auth_user))[2] - __s2[2]); if (__s1_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (vhost->auth_user))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (auth_user) && ((size_t
)(const void *)((auth_user) + 1) - (size_t)(const void *)(auth_user
) == 1) && (__s2_len = __builtin_strlen (auth_user), __s2_len
< 4) ? (__builtin_constant_p (vhost->auth_user) &&
((size_t)(const void *)((vhost->auth_user) + 1) - (size_t
)(const void *)(vhost->auth_user) == 1) ? __builtin_strcmp
(vhost->auth_user, auth_user) : (- (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
(vhost->auth_user); int __result = (((const unsigned char
*) (const char *) (auth_user))[0] - __s2[0]); if (__s2_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) (auth_user))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (auth_user))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (auth_user))[3] - __s2[3]); } } __result; }
)))) : __builtin_strcmp (vhost->auth_user, auth_user)))); }
)
&&
1617 !strcmp(vhost->auth_pass, auth_pass)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(vhost->auth_pass) && __builtin_constant_p (auth_pass
) && (__s1_len = __builtin_strlen (vhost->auth_pass
), __s2_len = __builtin_strlen (auth_pass), (!((size_t)(const
void *)((vhost->auth_pass) + 1) - (size_t)(const void *)(
vhost->auth_pass) == 1) || __s1_len >= 4) && (!
((size_t)(const void *)((auth_pass) + 1) - (size_t)(const void
*)(auth_pass) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(vhost->auth_pass, auth_pass) : (__builtin_constant_p (vhost
->auth_pass) && ((size_t)(const void *)((vhost->
auth_pass) + 1) - (size_t)(const void *)(vhost->auth_pass)
== 1) && (__s1_len = __builtin_strlen (vhost->auth_pass
), __s1_len < 4) ? (__builtin_constant_p (auth_pass) &&
((size_t)(const void *)((auth_pass) + 1) - (size_t)(const void
*)(auth_pass) == 1) ? __builtin_strcmp (vhost->auth_pass,
auth_pass) : (__extension__ ({ const unsigned char *__s2 = (
const unsigned char *) (const char *) (auth_pass); int __result
= (((const unsigned char *) (const char *) (vhost->auth_pass
))[0] - __s2[0]); if (__s1_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (vhost
->auth_pass))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (vhost->auth_pass))[2] - __s2[2]); if (__s1_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (vhost->auth_pass))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (auth_pass) && ((size_t
)(const void *)((auth_pass) + 1) - (size_t)(const void *)(auth_pass
) == 1) && (__s2_len = __builtin_strlen (auth_pass), __s2_len
< 4) ? (__builtin_constant_p (vhost->auth_pass) &&
((size_t)(const void *)((vhost->auth_pass) + 1) - (size_t
)(const void *)(vhost->auth_pass) == 1) ? __builtin_strcmp
(vhost->auth_pass, auth_pass) : (- (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
(vhost->auth_pass); int __result = (((const unsigned char
*) (const char *) (auth_pass))[0] - __s2[0]); if (__s2_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) (auth_pass))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (auth_pass))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (auth_pass))[3] - __s2[3]); } } __result; }
)))) : __builtin_strcmp (vhost->auth_pass, auth_pass)))); }
)
) {
62
Within the expansion of the macro 'strcmp':
a
Null pointer argument in call to string comparison function
1618 goto authed;
1619 }
1620
1621 if (!(params = cJSON_CreateObject())) {
1622 goto request_err;
1623 }
1624
1625 cJSON_AddItemToObject(params, "login", cJSON_CreateString(auth_user));
1626 cJSON_AddItemToObject(params, "passwd", cJSON_CreateString(auth_pass));
1627
1628 if (!check_auth(jsock, params, &code, message, sizeof(message))) {
1629 switch_snprintf(auth_buffer, sizeof(auth_buffer),
1630 "HTTP/1.1 401 Authentication Required\r\n"
1631 "WWW-Authenticate: Basic realm=\"%s\"\r\n"
1632 "Content-Length: 0\r\n\r\n",
1633 vhost->auth_realm);
1634 ws_raw_write(&jsock->ws, auth_buffer, strlen(auth_buffer));
1635 cJSON_Delete(params);
1636 goto done;
1637 } else {
1638 cJSON_Delete(params);
1639 }
1640
1641authed:
1642 switch_set_flag(jsock, JPFLAG_AUTHED)(jsock)->flags |= (JPFLAG_AUTHED);
1643 switch_event_add_header_string(request.headers, SWITCH_STACK_BOTTOM, "HTTP-USER", auth_user);
1644 }
1645
1646 if (vhost->rewrites) {
5
Taking false branch
1647 switch_event_header_t *rule = vhost->rewrites->headers;
1648 switch_regex_t *re = NULL((void*)0);
1649 int ovector[30];
1650 int proceed;
1651
1652 while(rule) {
1653 char *expression = rule->name;
1654
1655 if ((proceed = switch_regex_perform(request.uri, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
1656 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
1656, ((void*)0)
, SWITCH_LOG_ERROR,
1657 "%d request [%s] matched expr [%s]\n", proceed, request.uri, expression);
1658 request.uri = rule->value;
1659 break;
1660 }
1661
1662 rule = rule->next;
1663 }
1664 }
1665
1666 switch_event_add_header_string(request.headers, SWITCH_STACK_BOTTOM, "HTTP-URI", request.uri);
1667
1668 if ((ext = strrchr(request.uri, '.'))) {
6
Assuming 'ext' is null
7
Taking false branch
1669 char path[1024];
1670
1671 if (!strncmp(ext, ".lua", 4)(__extension__ (__builtin_constant_p (4) && ((__builtin_constant_p
(ext) && strlen (ext) < ((size_t) (4))) || (__builtin_constant_p
(".lua") && strlen (".lua") < ((size_t) (4)))) ? __extension__
({ size_t __s1_len, __s2_len; (__builtin_constant_p (ext) &&
__builtin_constant_p (".lua") && (__s1_len = __builtin_strlen
(ext), __s2_len = __builtin_strlen (".lua"), (!((size_t)(const
void *)((ext) + 1) - (size_t)(const void *)(ext) == 1) || __s1_len
>= 4) && (!((size_t)(const void *)((".lua") + 1) -
(size_t)(const void *)(".lua") == 1) || __s2_len >= 4)) ?
__builtin_strcmp (ext, ".lua") : (__builtin_constant_p (ext)
&& ((size_t)(const void *)((ext) + 1) - (size_t)(const
void *)(ext) == 1) && (__s1_len = __builtin_strlen (
ext), __s1_len < 4) ? (__builtin_constant_p (".lua") &&
((size_t)(const void *)((".lua") + 1) - (size_t)(const void *
)(".lua") == 1) ? __builtin_strcmp (ext, ".lua") : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (".lua"); int __result = (((const unsigned char *) (
const char *) (ext))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (ext))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (ext))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (ext))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(".lua") && ((size_t)(const void *)((".lua") + 1) - (
size_t)(const void *)(".lua") == 1) && (__s2_len = __builtin_strlen
(".lua"), __s2_len < 4) ? (__builtin_constant_p (ext) &&
((size_t)(const void *)((ext) + 1) - (size_t)(const void *)(
ext) == 1) ? __builtin_strcmp (ext, ".lua") : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (ext); int __result = (((const unsigned char *) (const
char *) (".lua"))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (".lua"))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (".lua"))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (".lua"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(ext, ".lua")))); }) : strncmp (ext, ".lua", 4)))
) {
1672 switch_snprintf(path, sizeof(path), "%s%s", vhost->script_root, request.uri);
1673 switch_api_execute("lua", path, NULL((void*)0), &stream);
1674 } else {
1675 http_static_handler(&request, vhost);
1676 }
1677
1678 } else {
1679 http_static_handler(&request, vhost);
1680 }
1681
1682done:
1683
1684 keepalive = request.keepalive;
1685 switch_http_free_request(&request);
1686
1687 if (keepalive) {
8
Assuming 'keepalive' is not equal to 0
9
Taking true branch
1688 wsh_t *wsh = &jsock->ws;
1689
1690 memset(&request, 0, sizeof(request));
1691 wsh->datalen = 0;
1692 *wsh->buffer = '\0';
1693
1694 while(jsock->profile->running) {
10
Loop condition is true. Entering loop body
20
Loop condition is true. Entering loop body
30
Loop condition is true. Entering loop body
40
Loop condition is true. Entering loop body
1695 int pflags = switch_wait_sock(jsock->client_socket, 3000, SWITCH_POLL_READ | SWITCH_POLL_ERROR | SWITCH_POLL_HUP);
1696
1697 if (jsock->drop) { die("%s Dropping Connection\n", jsock->name)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 1697, ((void*)0), SWITCH_LOG_DEBUG, "%s Dropping Connection\n"
, jsock->name); goto error
; }
11
Taking false branch
21
Taking false branch
31
Taking false branch
41
Taking false branch
1698 if (pflags < 0 && (errno(*__errno_location ()) != EINTR4)) { die("%s POLL FAILED\n", jsock->name)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 1698, ((void*)0), SWITCH_LOG_DEBUG, "%s POLL FAILED\n"
, jsock->name); goto error
; }
12
Assuming 'pflags' is >= 0
22
Assuming 'pflags' is >= 0
32
Assuming 'pflags' is >= 0
42
Assuming 'pflags' is >= 0
1699 if (pflags & SWITCH_POLL_ERROR) { die("%s POLL ERROR\n", jsock->name)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 1699, ((void*)0), SWITCH_LOG_DEBUG, "%s POLL ERROR\n"
, jsock->name); goto error
; }
13
Taking false branch
23
Taking false branch
33
Taking false branch
43
Taking false branch
1700 if (pflags & SWITCH_POLL_HUP) { die("%s POLL HANGUP DETECTED\n", jsock->name)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 1700, ((void*)0), SWITCH_LOG_DEBUG, "%s POLL HANGUP DETECTED\n"
, jsock->name); goto error
; }
14
Taking false branch
24
Taking false branch
34
Taking false branch
44
Taking false branch
1701 if (pflags & SWITCH_POLL_INVALID) { die("%s POLL INVALID SOCKET\n", jsock->name)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 1701, ((void*)0), SWITCH_LOG_DEBUG, "%s POLL INVALID SOCKET\n"
, jsock->name); goto error
; }
15
Taking false branch
25
Taking false branch
35
Taking false branch
45
Taking false branch
1702 if (pflags & SWITCH_POLL_READ) {
16
Taking true branch
26
Taking true branch
36
Taking true branch
46
Taking true branch
1703 ssize_t bytes;
1704
1705 bytes = ws_raw_read(wsh, wsh->buffer + wsh->datalen, wsh->buflen - wsh->datalen, wsh->block);
1706
1707 if (bytes < 0) {
17
Assuming 'bytes' is >= 0
18
Taking false branch
27
Assuming 'bytes' is >= 0
28
Taking false branch
37
Assuming 'bytes' is >= 0
38
Taking false branch
47
Assuming 'bytes' is >= 0
48
Taking false branch
1708 die("BAD READ %" SWITCH_SIZE_T_FMT "\n", bytes)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 1708, ((void*)0), SWITCH_LOG_DEBUG, "BAD READ %"
"ld" "\n", bytes); goto error
;
1709 break;
1710 }
1711
1712 wsh->datalen += bytes;
1713
1714 if (strstr(wsh->buffer, "\r\n\r\n") || strstr(wsh->buffer, "\n\n")) {
19
Taking false branch
29
Taking false branch
39
Taking false branch
49
Taking true branch
1715 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
1715, ((void*)0)
, SWITCH_LOG_DEBUG, "socket %s is going to handle a new request\n", jsock->name);
1716 goto new_req;
50
Control jumps to line 1501
1717 }
1718 } else {
1719 break;
1720 }
1721 }
1722 }
1723
1724 return;
1725
1726request_err:
1727 switch_http_free_request(&request);
1728
1729err:
1730 data = "HTTP/1.1 500 Internal Server Error\r\n"
1731 "Content-Length: 0\r\n\r\n";
1732 ws_raw_write(&jsock->ws, data, strlen(data));
1733
1734error:
1735 return;
1736}
1737
1738static void client_run(jsock_t *jsock)
1739{
1740
1741 jsock->local_addr.sin_family = AF_INET2;
1742 jsock->local_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
; }))
;
1743 jsock->local_addr.sin_port = 0;
1744
1745
1746 if (ws_init(&jsock->ws, jsock->client_socket, (jsock->ptype & PTYPE_CLIENT_SSL) ? jsock->profile->ssl_ctx : NULL((void*)0), 0, 1, !!jsock->profile->vhosts) < 0) {
1747 if (jsock->profile->vhosts) {
1748 http_run(jsock);
1749 ws_close(&jsock->ws, WS_NONE);
1750 goto error;
1751 } else {
1752 die("%s WS SETUP FAILED [%s]", jsock->name, jsock->ws.buffer)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 1752, ((void*)0), SWITCH_LOG_DEBUG, "%s WS SETUP FAILED [%s]"
, jsock->name, jsock->ws.buffer); goto error
;
1753 }
1754 }
1755
1756 while(jsock->profile->running) {
1757 int pflags = switch_wait_sock(jsock->client_socket, 50, SWITCH_POLL_READ | SWITCH_POLL_ERROR | SWITCH_POLL_HUP);
1758
1759 if (jsock->drop) {
1760 die("%s Dropping Connection\n", jsock->name)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 1760, ((void*)0), SWITCH_LOG_DEBUG, "%s Dropping Connection\n"
, jsock->name); goto error
;
1761 }
1762
1763 if (pflags < 0) {
1764 if (errno(*__errno_location ()) != EINTR4) {
1765 die("%s POLL FAILED\n", jsock->name)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 1765, ((void*)0), SWITCH_LOG_DEBUG, "%s POLL FAILED\n"
, jsock->name); goto error
;
1766 }
1767 }
1768
1769 if (pflags & SWITCH_POLL_ERROR) {
1770 die("%s POLL ERROR\n", jsock->name)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 1770, ((void*)0), SWITCH_LOG_DEBUG, "%s POLL ERROR\n"
, jsock->name); goto error
;
1771 }
1772
1773 if (pflags & SWITCH_POLL_HUP) {
1774 die("%s POLL HANGUP DETECTED\n", jsock->name)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 1774, ((void*)0), SWITCH_LOG_DEBUG, "%s POLL HANGUP DETECTED\n"
, jsock->name); goto error
;
1775 }
1776
1777 if (pflags & SWITCH_POLL_INVALID) {
1778 die("%s POLL INVALID SOCKET\n", jsock->name)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 1778, ((void*)0), SWITCH_LOG_DEBUG, "%s POLL INVALID SOCKET\n"
, jsock->name); goto error
;
1779 }
1780
1781 if (pflags & SWITCH_POLL_READ) {
1782 switch_ssize_t bytes;
1783 ws_opcode_t oc;
1784 uint8_t *data;
1785
1786 bytes = ws_read_frame(&jsock->ws, &oc, &data);
1787
1788 if (bytes < 0) {
1789 die("BAD READ %" SWITCH_SSIZE_T_FMT "\n", bytes)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 1789, ((void*)0), SWITCH_LOG_DEBUG, "BAD READ %"
"ld" "\n", bytes); goto error
;
1790 break;
1791 }
1792
1793 if (bytes) {
1794 if (process_input(jsock, data, bytes) != SWITCH_STATUS_SUCCESS) {
1795 die("Input Error\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 1795, ((void*)0), SWITCH_LOG_DEBUG, "Input Error\n"
); goto error
;
1796 }
1797
1798 if (!switch_test_flag(jsock, JPFLAG_CHECK_ATTACH)((jsock)->flags & JPFLAG_CHECK_ATTACH) && switch_test_flag(jsock, JPFLAG_AUTHED)((jsock)->flags & JPFLAG_AUTHED)) {
1799 attach_calls(jsock);
1800 switch_set_flag(jsock, JPFLAG_CHECK_ATTACH)(jsock)->flags |= (JPFLAG_CHECK_ATTACH);
1801 }
1802 }
1803 } else {
1804 jsock_check_event_queue(jsock);
1805 }
1806 }
1807
1808 error:
1809
1810 detach_jsock(jsock);
1811 ws_destroy(&jsock->ws);
1812
1813 return;
1814}
1815
1816static void jsock_flush(jsock_t *jsock)
1817{
1818 void *pop;
1819
1820 switch_mutex_lock(jsock->write_mutex);
1821 while(switch_queue_trypop(jsock->event_queue, &pop) == SWITCH_STATUS_SUCCESS) {
1822 cJSON *json = (cJSON *) pop;
1823 cJSON_Delete(json);
1824 }
1825 switch_mutex_unlock(jsock->write_mutex);
1826}
1827
1828static void *SWITCH_THREAD_FUNC client_thread(switch_thread_t *thread, void *obj)
1829{
1830 switch_event_t *s_event;
1831
1832 jsock_t *jsock = (jsock_t *) obj;
1833
1834 switch_event_create(&jsock->params, SWITCH_EVENT_CHANNEL_DATA)switch_event_create_subclass_detailed("mod_verto.c", (const char
* )(const char *)__func__, 1834, &jsock->params, SWITCH_EVENT_CHANNEL_DATA
, ((void*)0))
;
1835 switch_event_create(&jsock->vars, SWITCH_EVENT_CHANNEL_DATA)switch_event_create_subclass_detailed("mod_verto.c", (const char
* )(const char *)__func__, 1835, &jsock->vars, SWITCH_EVENT_CHANNEL_DATA
, ((void*)0))
;
1836
1837
1838 add_jsock(jsock);
1839
1840 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
1840, ((void*)0)
, SWITCH_LOG_INFO, "%s Starting client thread.\n", jsock->name);
1841
1842 if ((jsock->ptype & PTYPE_CLIENT) || (jsock->ptype & PTYPE_CLIENT_SSL)) {
1843 client_run(jsock);
1844 } else {
1845 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
1845, ((void*)0)
, SWITCH_LOG_ERROR, "%s Ending client thread.\n", jsock->name);
1846 }
1847
1848 detach_calls(jsock);
1849
1850 del_jsock(jsock);
1851
1852 switch_event_destroy(&jsock->params);
1853 switch_event_destroy(&jsock->vars);
1854
1855 if (jsock->client_socket > -1) {
1856 close_socket(&jsock->client_socket);
1857 }
1858
1859 switch_event_destroy(&jsock->allowed_methods);
1860 switch_event_destroy(&jsock->allowed_fsapi);
1861 switch_event_destroy(&jsock->allowed_jsapi);
1862 switch_event_destroy(&jsock->allowed_event_channels);
1863
1864 jsock_flush(jsock);
1865
1866 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
1866, ((void*)0)
, SWITCH_LOG_INFO, "%s Ending client thread.\n", jsock->name);
1867 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_CLIENT_DISCONNECT)switch_event_create_subclass_detailed("mod_verto.c", (const char
* )(const char *)__func__, 1867, &s_event, SWITCH_EVENT_CUSTOM
, "verto::client_disconnect")
== SWITCH_STATUS_SUCCESS) {
1868 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "verto_profile_name", jsock->profile->name);
1869 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "verto_client_address", jsock->name);
1870 switch_event_fire(&s_event)switch_event_fire_detailed("mod_verto.c", (const char * )(const
char *)__func__, 1870, &s_event, ((void*)0))
;
1871 }
1872 switch_thread_rwlock_wrlock(jsock->rwlock);
1873 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
1873, ((void*)0)
, SWITCH_LOG_INFO, "%s Thread ended\n", jsock->name);
1874 switch_thread_rwlock_unlock(jsock->rwlock);
1875
1876 return NULL((void*)0);
1877}
1878
1879
1880static switch_bool_t auth_api_command(jsock_t *jsock, const char *api_cmd, const char *arg)
1881{
1882 const char *check_cmd = api_cmd;
1883 char *sneaky_commands[] = { "bgapi", "sched_api", "eval", "expand", "xml_wrap", NULL((void*)0) };
1884 int x = 0;
1885 char *dup_arg = NULL((void*)0);
1886 char *next = NULL((void*)0);
1887 switch_bool_t ok = SWITCH_TRUE;
1888
1889 top:
1890
1891 if (!jsock->allowed_fsapi) {
1892 ok = SWITCH_FALSE;
1893 goto end;
1894 }
1895
1896 if (!switch_event_get_header(jsock->allowed_fsapi, check_cmd)switch_event_get_header_idx(jsock->allowed_fsapi, check_cmd
, -1)
) {
1897 ok = SWITCH_FALSE;
1898 goto end;
1899 }
1900
1901 while (check_cmd) {
1902 for (x = 0; sneaky_commands[x]; x++) {
1903 if (!strcasecmp(sneaky_commands[x], check_cmd)) {
1904 if (check_cmd == api_cmd) {
1905 if (arg) {
1906 switch_safe_free(dup_arg)if (dup_arg) {free(dup_arg);dup_arg=((void*)0);};
1907 dup_arg = strdup(arg)(__extension__ (__builtin_constant_p (arg) && ((size_t
)(const void *)((arg) + 1) - (size_t)(const void *)(arg) == 1
) ? (((const char *) (arg))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (arg) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, arg, __len); __retval
; })) : __strdup (arg)))
;
1908 check_cmd = dup_arg;
1909 if ((next = strchr(check_cmd, ' ')(__extension__ (__builtin_constant_p (' ') && !__builtin_constant_p
(check_cmd) && (' ') == '\0' ? (char *) __rawmemchr (
check_cmd, ' ') : __builtin_strchr (check_cmd, ' ')))
)) {
1910 *next++ = '\0';
1911 }
1912 } else {
1913 break;
1914 }
1915 } else {
1916 if (next) {
1917 check_cmd = next;
1918 } else {
1919 check_cmd = dup_arg;
1920 }
1921
1922 if ((next = strchr(check_cmd, ' ')(__extension__ (__builtin_constant_p (' ') && !__builtin_constant_p
(check_cmd) && (' ') == '\0' ? (char *) __rawmemchr (
check_cmd, ' ') : __builtin_strchr (check_cmd, ' ')))
)) {
1923 *next++ = '\0';
1924 }
1925 }
1926 goto top;
1927 }
1928 }
1929 break;
1930 }
1931
1932 end:
1933
1934 switch_safe_free(dup_arg)if (dup_arg) {free(dup_arg);dup_arg=((void*)0);};
1935 return ok;
1936
1937}
1938
1939//// VERTO
1940
1941static void track_pvt(verto_pvt_t *tech_pvt)
1942{
1943 switch_thread_rwlock_wrlock(globals.tech_rwlock);
1944 tech_pvt->next = globals.tech_head;
1945 globals.tech_head = tech_pvt;
1946 switch_thread_rwlock_unlock(globals.tech_rwlock);
1947}
1948
1949static void untrack_pvt(verto_pvt_t *tech_pvt)
1950{
1951 verto_pvt_t *p, *last = NULL((void*)0);
1952
1953 switch_thread_rwlock_wrlock(globals.tech_rwlock);
1954 if (tech_pvt->detach_time) {
1955 globals.detached--;
1956 tech_pvt->detach_time = 0;
1957 attach_wake();
1958 }
1959
1960 for(p = globals.tech_head; p; p = p->next) {
1961 if (p == tech_pvt) {
1962 if (last) {
1963 last->next = p->next;
1964 } else {
1965 globals.tech_head = p->next;
1966 }
1967 break;
1968 }
1969
1970 last = p;
1971 }
1972 switch_thread_rwlock_unlock(globals.tech_rwlock);
1973}
1974
1975
1976static switch_status_t verto_on_hangup(switch_core_session_t *session)
1977{
1978 jsock_t *jsock = NULL((void*)0);
1979 verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
1980
1981 untrack_pvt(tech_pvt);
1982
1983 // get the jsock and send hangup notice
1984 if (!tech_pvt->remote_hangup_cause && (jsock = get_jsock(tech_pvt->jsock_uuid))) {
1985 cJSON *params = NULL((void*)0);
1986 cJSON *msg = jrpc_new_req("verto.bye", tech_pvt->call_id, &params);
1987 switch_call_cause_t cause = switch_channel_get_cause(tech_pvt->channel);
1988
1989 cJSON_AddItemToObject(params, "causeCode", cJSON_CreateNumber(cause));
1990 cJSON_AddItemToObject(params, "cause", cJSON_CreateString(switch_channel_cause2str(cause)));
1991 jsock_queue_event(jsock, &msg, SWITCH_TRUE);
1992
1993 switch_thread_rwlock_unlock(jsock->rwlock);
1994 }
1995
1996 return SWITCH_STATUS_SUCCESS;
1997}
1998
1999static void verto_set_media_options(verto_pvt_t *tech_pvt, verto_profile_t *profile);
2000
2001static switch_status_t verto_connect(switch_core_session_t *session, const char *method)
2002{
2003 switch_status_t status = SWITCH_STATUS_SUCCESS;
2004 jsock_t *jsock = NULL((void*)0);
2005 verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
2006
2007 if (!(jsock = get_jsock(tech_pvt->jsock_uuid))) {
2008 status = SWITCH_STATUS_BREAK;
2009 } else {
2010 cJSON *params = NULL((void*)0);
2011 cJSON *msg = NULL((void*)0);
2012 const char *var = NULL((void*)0);
2013 switch_caller_profile_t *caller_profile = switch_channel_get_caller_profile(tech_pvt->channel);
2014
2015 DUMP_EVENT(jsock->params){char *event_str;switch_event_serialize(jsock->params, &
event_str, SWITCH_FALSE);switch_log_printf(SWITCH_CHANNEL_ID_LOG
, "mod_verto.c", (const char *)__func__, 2015, ((void*)0), SWITCH_LOG_CRIT
, "DUMP\n%s\n", event_str);free(event_str);}
;
2016
2017 switch_channel_set_variable(tech_pvt->channel, "verto_user", jsock->uid)switch_channel_set_variable_var_check(tech_pvt->channel, "verto_user"
, jsock->uid, SWITCH_TRUE)
;
2018 switch_channel_set_variable(tech_pvt->channel, "presence_id", jsock->uid)switch_channel_set_variable_var_check(tech_pvt->channel, "presence_id"
, jsock->uid, SWITCH_TRUE)
;
2019 switch_channel_set_variable(tech_pvt->channel, "chat_proto", VERTO_CHAT_PROTO)switch_channel_set_variable_var_check(tech_pvt->channel, "chat_proto"
, "verto", SWITCH_TRUE)
;
2020 switch_channel_set_variable(tech_pvt->channel, "verto_host", jsock->domain)switch_channel_set_variable_var_check(tech_pvt->channel, "verto_host"
, jsock->domain, SWITCH_TRUE)
;
2021
2022 if ((var = switch_event_get_header(jsock->params, "caller-id-name")switch_event_get_header_idx(jsock->params, "caller-id-name"
, -1)
)) {
2023 caller_profile->callee_id_name = switch_core_strdup(caller_profile->pool, var)switch_core_perform_strdup(caller_profile->pool, var, "mod_verto.c"
, (const char *)__func__, 2023)
;
2024 }
2025
2026 if ((var = switch_event_get_header(jsock->params, "caller-id-number")switch_event_get_header_idx(jsock->params, "caller-id-number"
, -1)
)) {
2027 caller_profile->callee_id_number = switch_core_strdup(caller_profile->pool, var)switch_core_perform_strdup(caller_profile->pool, var, "mod_verto.c"
, (const char *)__func__, 2027)
;
2028 }
2029
2030 if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE)) {
2031 switch_core_media_absorb_sdp(session);
2032 } else {
2033 switch_channel_set_variable(tech_pvt->channel, "media_webrtc", "true")switch_channel_set_variable_var_check(tech_pvt->channel, "media_webrtc"
, "true", SWITCH_TRUE)
;
2034 switch_core_session_set_ice(tech_pvt->session);
2035
2036 verto_set_media_options(tech_pvt, jsock->profile);
2037
2038
2039 switch_channel_set_variable(tech_pvt->channel, "verto_profile_name", jsock->profile->name)switch_channel_set_variable_var_check(tech_pvt->channel, "verto_profile_name"
, jsock->profile->name, SWITCH_TRUE)
;
2040
2041 if (!switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING)) {
2042 switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
2043
2044 if ((status = switch_core_media_choose_ports(tech_pvt->session, SWITCH_TRUE, SWITCH_TRUE)) != SWITCH_STATUS_SUCCESS) {
2045 //if ((status = switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0)) != SWITCH_STATUS_SUCCESS) {
2046 switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 2046, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
2047 switch_thread_rwlock_unlock(jsock->rwlock);
2048 return status;
2049 }
2050 }
2051
2052 switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL((void*)0), 0, NULL((void*)0), 0);
2053 }
2054
2055 msg = jrpc_new_req(method, tech_pvt->call_id, &params);
2056
2057 if (tech_pvt->mparams->local_sdp_str) {
2058 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_verto.c", (const char *)__func__
, 2058, (const char*)(session)
, SWITCH_LOG_DEBUG, "Local %s SDP %s:\n%s\n",
2059 method,
2060 switch_channel_get_name(tech_pvt->channel),
2061 tech_pvt->mparams->local_sdp_str);
2062
2063 cJSON_AddItemToObject(params, "sdp", cJSON_CreateString(tech_pvt->mparams->local_sdp_str));
2064 set_call_params(params, tech_pvt);
2065
2066 jsock_queue_event(jsock, &msg, SWITCH_TRUE);
2067 } else {
2068 status = SWITCH_STATUS_FALSE;
2069 }
2070
2071 switch_thread_rwlock_unlock(jsock->rwlock);
2072 }
2073
2074 return status;
2075}
2076
2077switch_status_t verto_tech_media(verto_pvt_t *tech_pvt, const char *r_sdp, switch_sdp_type_t sdp_type)
2078{
2079 uint8_t match = 0, p = 0;
2080
2081 switch_assert(tech_pvt != NULL)((tech_pvt != ((void*)0)) ? (void) (0) : __assert_fail ("tech_pvt != ((void*)0)"
, "mod_verto.c", 2081, __PRETTY_FUNCTION__))
;
2082 switch_assert(r_sdp != NULL)((r_sdp != ((void*)0)) ? (void) (0) : __assert_fail ("r_sdp != ((void*)0)"
, "mod_verto.c", 2082, __PRETTY_FUNCTION__))
;
2083
2084 if (zstr(r_sdp)_zstr(r_sdp)) {
2085 return SWITCH_STATUS_FALSE;
2086 }
2087
2088 if ((match = switch_core_media_negotiate_sdp(tech_pvt->session, r_sdp, &p, sdp_type))) {
2089 if (switch_core_media_choose_ports(tech_pvt->session, SWITCH_TRUE, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) {
2090 //if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) {
2091 return SWITCH_STATUS_FALSE;
2092 }
2093
2094 if (switch_core_media_activate_rtp(tech_pvt->session) != SWITCH_STATUS_SUCCESS) {
2095 return SWITCH_STATUS_FALSE;
2096 }
2097 //if (!switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED)) {
2098 // switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "EARLY MEDIA");
2099 // switch_channel_mark_pre_answered(tech_pvt->channel);
2100 //}
2101 return SWITCH_STATUS_SUCCESS;
2102 }
2103
2104
2105 return SWITCH_STATUS_FALSE;
2106}
2107
2108static switch_status_t verto_on_init(switch_core_session_t *session)
2109{
2110 switch_status_t status = SWITCH_STATUS_SUCCESS;
2111 verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
2112
2113 if (switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING_BRIDGE) || switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING)) {
2114 int tries = 120;
2115
2116 switch_core_session_clear_crypto(session);
2117
2118 while(--tries > 0) {
2119
2120 status = verto_connect(session, "verto.attach");
2121
2122 if (status == SWITCH_STATUS_SUCCESS) {
2123 switch_set_flag(tech_pvt, TFLAG_ATTACH_REQ)(tech_pvt)->flags |= (TFLAG_ATTACH_REQ);
2124 break;
2125 } else if (status == SWITCH_STATUS_BREAK) {
2126 switch_yield(1000000)switch_sleep(1000000);;
2127 continue;
2128 } else {
2129 tries = 0;
2130 break;
2131 }
2132 }
2133
2134 if (!tries) {
2135 switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 2135, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
2136 status = SWITCH_STATUS_FALSE;
2137 }
2138
2139 switch_channel_set_flag(tech_pvt->channel, CF_VIDEO_BREAK)switch_channel_set_flag_value(tech_pvt->channel, CF_VIDEO_BREAK
, 1)
;
2140 switch_core_session_kill_channel(tech_pvt->session, SWITCH_SIG_BREAK)switch_core_session_perform_kill_channel(tech_pvt->session
, "mod_verto.c", (const char *)__func__, 2140, SWITCH_SIG_BREAK
)
;
2141
2142 tries = 500;
2143 while(--tries > 0 && switch_test_flag(tech_pvt, TFLAG_ATTACH_REQ)((tech_pvt)->flags & TFLAG_ATTACH_REQ)) {
2144 switch_yield(10000)switch_sleep(10000);;
2145 }
2146
2147 switch_core_session_refresh_video(session);
2148 switch_channel_set_flag(tech_pvt->channel, CF_VIDEO_BREAK)switch_channel_set_flag_value(tech_pvt->channel, CF_VIDEO_BREAK
, 1)
;
2149 switch_core_session_kill_channel(tech_pvt->session, SWITCH_SIG_BREAK)switch_core_session_perform_kill_channel(tech_pvt->session
, "mod_verto.c", (const char *)__func__, 2149, SWITCH_SIG_BREAK
)
;
2150
2151 return status;
2152 }
2153
2154 if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
2155 if ((status = verto_connect(tech_pvt->session, "verto.invite")) != SWITCH_STATUS_SUCCESS) {
2156 switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 2156, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
2157 } else {
2158 switch_channel_mark_ring_ready(tech_pvt->channel)switch_channel_perform_mark_ring_ready_value(tech_pvt->channel
, SWITCH_RING_READY_RINGING, "mod_verto.c", (const char *)__func__
, 2158)
;
2159 }
2160 }
2161
2162 return status;
2163}
2164
2165
2166static switch_state_handler_table_t verto_state_handlers = {
2167 /*.on_init */ verto_on_init,
2168 /*.on_routing */ NULL((void*)0),
2169 /*.on_execute */ NULL((void*)0),
2170 /*.on_hangup */ verto_on_hangup,
2171 /*.on_exchange_media */ NULL((void*)0),
2172 /*.on_soft_execute */ NULL((void*)0),
2173 /*.on_consume_media */ NULL((void*)0),
2174 /*.on_hibernate */ NULL((void*)0),
2175 /*.on_reset */ NULL((void*)0),
2176 /*.on_park */ NULL((void*)0),
2177 /*.on_reporting */ NULL((void*)0),
2178 /*.on_destroy */ NULL((void*)0),
2179 SSH_FLAG_STICKY
2180};
2181
2182
2183
2184
2185static void verto_set_media_options(verto_pvt_t *tech_pvt, verto_profile_t *profile)
2186{
2187 uint32_t i;
2188
2189 tech_pvt->mparams->rtpip = switch_core_session_strdup(tech_pvt->session, profile->rtpip[profile->rtpip_cur++])switch_core_perform_session_strdup(tech_pvt->session, profile
->rtpip[profile->rtpip_cur++], "mod_verto.c", (const char
*)__func__, 2189)
;
2190
2191 if (profile->rtpip_cur == profile->rtpip_index) {
2192 profile->rtpip_cur = 0;
2193 }
2194
2195 tech_pvt->mparams->extrtpip = profile->extrtpip;
2196
2197 //tech_pvt->mparams->dtmf_type = tech_pvt->profile->dtmf_type;
2198 switch_channel_set_flag(tech_pvt->channel, CF_TRACKABLE)switch_channel_set_flag_value(tech_pvt->channel, CF_TRACKABLE
, 1)
;
2199 switch_channel_set_variable(tech_pvt->channel, "secondary_recovery_module", modname)switch_channel_set_variable_var_check(tech_pvt->channel, "secondary_recovery_module"
, modname, SWITCH_TRUE)
;
2200
2201 switch_core_media_check_dtmf_type(tech_pvt->session);
2202
2203 //switch_channel_set_cap(tech_pvt->channel, CC_MEDIA_ACK);
2204 switch_channel_set_cap(tech_pvt->channel, CC_BYPASS_MEDIA)switch_channel_set_cap_value(tech_pvt->channel, CC_BYPASS_MEDIA
, 1)
;
2205 //switch_channel_set_cap(tech_pvt->channel, CC_PROXY_MEDIA);
2206 switch_channel_set_cap(tech_pvt->channel, CC_JITTERBUFFER)switch_channel_set_cap_value(tech_pvt->channel, CC_JITTERBUFFER
, 1)
;
2207 switch_channel_set_cap(tech_pvt->channel, CC_FS_RTP)switch_channel_set_cap_value(tech_pvt->channel, CC_FS_RTP,
1)
;
2208
2209 //switch_channel_set_cap(tech_pvt->channel, CC_QUEUEABLE_DTMF_DELAY);
2210 //tech_pvt->mparams->ndlb = tech_pvt->profile->mndlb;
2211
2212 tech_pvt->mparams->inbound_codec_string = switch_core_session_strdup(tech_pvt->session, profile->inbound_codec_string)switch_core_perform_session_strdup(tech_pvt->session, profile
->inbound_codec_string, "mod_verto.c", (const char *)__func__
, 2212)
;
2213 tech_pvt->mparams->outbound_codec_string = switch_core_session_strdup(tech_pvt->session, profile->outbound_codec_string)switch_core_perform_session_strdup(tech_pvt->session, profile
->outbound_codec_string, "mod_verto.c", (const char *)__func__
, 2213)
;
2214
2215 tech_pvt->mparams->jb_msec = "-1";
2216 switch_media_handle_set_media_flag(tech_pvt->smh, SCMF_SUPPRESS_CNG);
2217
2218 switch_media_handle_set_media_flag(tech_pvt->smh, SCMF_RENEG_ON_REINVITE);
2219
2220 //tech_pvt->mparams->auto_rtp_bugs = profile->auto_rtp_bugs;
2221 tech_pvt->mparams->timer_name = profile->timer_name;
2222 //tech_pvt->mparams->vflags = profile->vflags;
2223 //tech_pvt->mparams->manual_rtp_bugs = profile->manual_rtp_bugs;
2224 //tech_pvt->mparams->manual_video_rtp_bugs = profile->manual_video_rtp_bugs;
2225
2226 tech_pvt->mparams->local_network = switch_core_session_strdup(tech_pvt->session, profile->local_network)switch_core_perform_session_strdup(tech_pvt->session, profile
->local_network, "mod_verto.c", (const char *)__func__, 2226
)
;
2227
2228
2229 //tech_pvt->mparams->rtcp_audio_interval_msec = profile->rtpp_audio_interval_msec;
2230 //tech_pvt->mparams->rtcp_video_interval_msec = profile->rtpp_video_interval_msec;
2231 //tech_pvt->mparams->sdp_username = profile->sdp_username;
2232 //tech_pvt->mparams->cng_pt = tech_pvt->cng_pt;
2233 //tech_pvt->mparams->rtc_timeout_sec = profile->rtp_timeout_sec;
2234 //tech_pvt->mparams->rtc_hold_timeout_sec = profile->rtp_hold_timeout_sec;
2235 //switch_media_handle_set_media_flags(tech_pvt->media_handle, tech_pvt->profile->media_flags);
2236
2237
2238 for(i = 0; i < profile->cand_acl_count; i++) {
2239 switch_core_media_add_ice_acl(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, profile->cand_acl[i]);
2240 switch_core_media_add_ice_acl(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO, profile->cand_acl[i]);
2241 }
2242}
2243
2244static switch_status_t verto_media(switch_core_session_t *session)
2245{
2246 verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
2247 switch_status_t status = SWITCH_STATUS_SUCCESS;
2248
2249 switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
2250
2251 if (tech_pvt->r_sdp) {
2252 if (verto_tech_media(tech_pvt, tech_pvt->r_sdp, SDP_TYPE_REQUEST) != SWITCH_STATUS_SUCCESS) {
2253 switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR")switch_channel_set_variable_var_check(tech_pvt->channel, "endpoint_disposition"
, "CODEC NEGOTIATION ERROR", SWITCH_TRUE)
;
2254 return SWITCH_STATUS_FALSE;
2255 }
2256 }
2257
2258 if ((status = switch_core_media_choose_ports(tech_pvt->session, SWITCH_TRUE, SWITCH_FALSE)) != SWITCH_STATUS_SUCCESS) {
2259 //if ((status = switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0)) != SWITCH_STATUS_SUCCESS) {
2260 switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 2260, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
2261 return status;
2262 }
2263
2264 switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL((void*)0), 0, NULL((void*)0), 0);
2265
2266 if (switch_core_media_activate_rtp(tech_pvt->session) != SWITCH_STATUS_SUCCESS) {
2267 switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 2267, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
2268 }
2269
2270 if (tech_pvt->mparams->local_sdp_str) {
2271 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_verto.c", (const char *)__func__
, 2271, (const char*)(session)
, SWITCH_LOG_DEBUG, "Local SDP %s:\n%s\n", switch_channel_get_name(tech_pvt->channel),
2272 tech_pvt->mparams->local_sdp_str);
2273 } else {
2274 status = SWITCH_STATUS_FALSE;
2275 }
2276
2277 return status;
2278}
2279
2280
2281static switch_status_t verto_send_media_indication(switch_core_session_t *session, const char *method)
2282{
2283 switch_status_t status = SWITCH_STATUS_FALSE;
2284 verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
2285 const char *proxy_sdp = NULL((void*)0);
2286
2287 if (switch_test_flag(tech_pvt, TFLAG_SENT_MEDIA)((tech_pvt)->flags & TFLAG_SENT_MEDIA)) {
2288 status = SWITCH_STATUS_SUCCESS;
2289 }
2290
2291 if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE)) {
2292 if ((proxy_sdp = switch_channel_get_variable(tech_pvt->channel, SWITCH_B_SDP_VARIABLE)switch_channel_get_variable_dup(tech_pvt->channel, "switch_m_sdp"
, SWITCH_TRUE, -1)
)) {
2293 status = SWITCH_STATUS_SUCCESS;
2294 switch_core_media_set_local_sdp(session, proxy_sdp, SWITCH_TRUE);
2295 }
2296 }
2297
2298
2299 if (status == SWITCH_STATUS_SUCCESS || (status = verto_media(session)) == SWITCH_STATUS_SUCCESS) {
2300 jsock_t *jsock = NULL((void*)0);
2301
2302 if (!(jsock = get_jsock(tech_pvt->jsock_uuid))) {
2303 status = SWITCH_STATUS_FALSE;
2304 } else {
2305 cJSON *params = NULL((void*)0);
2306 cJSON *msg = jrpc_new_req(method, tech_pvt->call_id, &params);
2307 if (!switch_test_flag(tech_pvt, TFLAG_SENT_MEDIA)((tech_pvt)->flags & TFLAG_SENT_MEDIA)) {
2308 cJSON_AddItemToObject(params, "sdp", cJSON_CreateString(tech_pvt->mparams->local_sdp_str));
2309 }
2310
2311 switch_set_flag(tech_pvt, TFLAG_SENT_MEDIA)(tech_pvt)->flags |= (TFLAG_SENT_MEDIA);
2312
2313 if (jsock_queue_event(jsock, &msg, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
2314 switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 2314, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
2315 }
2316
2317 switch_thread_rwlock_unlock(jsock->rwlock);
2318 }
2319 }
2320
2321 return status;
2322}
2323
2324static switch_status_t messagehook (switch_core_session_t *session, switch_core_session_message_t *msg)
2325{
2326 switch_status_t r = SWITCH_STATUS_SUCCESS;
2327 verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
2328
2329 switch(msg->message_id) {
2330 case SWITCH_MESSAGE_INDICATE_DISPLAY:
2331 {
2332 const char *name, *number;
2333 cJSON *jmsg = NULL((void*)0), *params = NULL((void*)0);
2334 jsock_t *jsock = NULL((void*)0);
2335
2336 if ((jsock = get_jsock(tech_pvt->jsock_uuid))) {
2337 name = msg->string_array_arg[0];
2338 number = msg->string_array_arg[1];
2339
2340 if (name || number) {
2341 jmsg = jrpc_new_req("verto.display", tech_pvt->call_id, &params);
2342 switch_ivr_eavesdrop_update_display(session, name, number);
2343 switch_channel_set_variable(tech_pvt->channel, "last_sent_display_name", name)switch_channel_set_variable_var_check(tech_pvt->channel, "last_sent_display_name"
, name, SWITCH_TRUE)
;
2344 switch_channel_set_variable(tech_pvt->channel, "last_sent_display_number", number)switch_channel_set_variable_var_check(tech_pvt->channel, "last_sent_display_number"
, number, SWITCH_TRUE)
;
2345 cJSON_AddItemToObject(params, "display_name", cJSON_CreateString(name));
2346 cJSON_AddItemToObject(params, "display_number", cJSON_CreateString(number));
2347 set_call_params(params, tech_pvt);
2348 jsock_queue_event(jsock, &jmsg, SWITCH_TRUE);
2349 }
2350
2351 switch_thread_rwlock_unlock(jsock->rwlock);
2352 }
2353
2354 }
2355 break;
2356 case SWITCH_MESSAGE_INDICATE_ANSWER:
2357 r = verto_send_media_indication(session, "verto.answer");
2358 break;
2359 case SWITCH_MESSAGE_INDICATE_PROGRESS:
2360 r = verto_send_media_indication(session, "verto.media");
2361 break;
2362 default:
2363 break;
2364 }
2365
2366 return r;
2367}
2368
2369
2370
2371static int verto_recover_callback(switch_core_session_t *session)
2372{
2373 int r = 0;
2374 char name[512];
2375 verto_pvt_t *tech_pvt = NULL((void*)0);
2376 verto_profile_t *profile = NULL((void*)0);
2377 const char *profile_name = NULL((void*)0), *jsock_uuid_str = NULL((void*)0);
2378 switch_channel_t *channel = switch_core_session_get_channel(session);
2379
2380
2381 profile_name = switch_channel_get_variable(channel, "verto_profile_name")switch_channel_get_variable_dup(channel, "verto_profile_name"
, SWITCH_TRUE, -1)
;
2382 jsock_uuid_str = switch_channel_get_variable(channel, "jsock_uuid_str")switch_channel_get_variable_dup(channel, "jsock_uuid_str", SWITCH_TRUE
, -1)
;
2383
2384 if (!(profile_name && jsock_uuid_str && (profile = find_profile(profile_name)))) {
2385 return 0;
2386 }
2387
2388 tech_pvt = switch_core_session_alloc(session, sizeof(*tech_pvt))switch_core_perform_session_alloc(session, sizeof(*tech_pvt),
"mod_verto.c", (const char *)__func__, 2388)
;
2389 tech_pvt->session = session;
2390 tech_pvt->channel = channel;
2391 tech_pvt->jsock_uuid = (char *) jsock_uuid_str;
2392 switch_core_session_set_private_class(session, tech_pvt, SWITCH_PVT_SECONDARY);
2393
2394
2395 tech_pvt->call_id = switch_core_session_strdup(session, switch_core_session_get_uuid(session))switch_core_perform_session_strdup(session, switch_core_session_get_uuid
(session), "mod_verto.c", (const char *)__func__, 2395)
;
2396 if ((tech_pvt->smh = switch_core_session_get_media_handle(session))) {
2397 tech_pvt->mparams = switch_core_media_get_mparams(tech_pvt->smh);
2398 verto_set_media_options(tech_pvt, profile);
2399 }
2400
2401 switch_snprintf(name, sizeof(name), "verto.rtc/%s", tech_pvt->jsock_uuid);
2402 switch_channel_set_name(channel, name);
2403
2404 switch_channel_add_state_handler(channel, &verto_state_handlers);
2405 switch_core_event_hook_add_receive_message(session, messagehook);
2406
2407 track_pvt(tech_pvt);
2408
2409 //switch_channel_clear_flag(tech_pvt->channel, CF_ANSWERED);
2410 //switch_channel_clear_flag(tech_pvt->channel, CF_EARLY_MEDIA);
2411
2412 switch_thread_rwlock_unlock(profile->rwlock);
2413
2414 r++;
2415
2416 return r;
2417}
2418
2419
2420static void pass_sdp(verto_pvt_t *tech_pvt)
2421{
2422 switch_core_session_t *other_session = NULL((void*)0);
2423 switch_channel_t *other_channel = NULL((void*)0);
2424
2425 if (switch_core_session_get_partner(tech_pvt->session, &other_session)switch_core_session_perform_get_partner(tech_pvt->session,
&other_session, "mod_verto.c", (const char *)__func__, 2425
)
== SWITCH_STATUS_SUCCESS) {
2426 other_channel = switch_core_session_get_channel(other_session);
2427 switch_channel_pass_sdp(tech_pvt->channel, other_channel, tech_pvt->r_sdp);
2428
2429 switch_channel_set_flag(other_channel, CF_PROXY_MODE)switch_channel_set_flag_value(other_channel, CF_PROXY_MODE, 1
)
;
2430 switch_core_session_queue_indication(other_session, SWITCH_MESSAGE_INDICATE_ANSWER);
2431 switch_core_session_rwunlock(other_session);
2432 }
2433}
2434
2435
2436//// METHODS
2437
2438#define switch_either(_A, _B)_zstr(_A) ? _B : _A zstr(_A)_zstr(_A) ? _B : _A
2439
2440static switch_bool_t verto__answer_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
2441{
2442 cJSON *obj = cJSON_CreateObject();
2443 switch_core_session_t *session;
2444 cJSON *dialog = NULL((void*)0);
2445 const char *call_id = NULL((void*)0), *sdp = NULL((void*)0);
2446 int err = 0;
2447 const char *callee_id_name = NULL((void*)0), *callee_id_number = NULL((void*)0);
2448
2449 *response = obj;
2450
2451 if (!(dialog = cJSON_GetObjectItem(params, "dialogParams"))) {
2452 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("Dialog data missing"));
2453 err = 1; goto cleanup;
2454 }
2455
2456 if (!(call_id = cJSON_GetObjectCstr(dialog, "callID"))) {
2457 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CallID missing"));
2458 err = 1; goto cleanup;
2459 }
2460
2461 if (!(sdp = cJSON_GetObjectCstr(params, "sdp"))) {
2462 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("SDP missing"));
2463 err = 1; goto cleanup;
2464 }
2465
2466 callee_id_name = cJSON_GetObjectCstr(dialog, "callee_id_name");
2467 callee_id_number = cJSON_GetObjectCstr(dialog, "callee_id_number");
2468
2469
2470 if ((session = switch_core_session_locate(call_id)switch_core_session_perform_locate(call_id, "mod_verto.c", (const
char *)__func__, 2470)
)) {
2471 verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
2472
2473 tech_pvt->r_sdp = switch_core_session_strdup(session, sdp)switch_core_perform_session_strdup(session, sdp, "mod_verto.c"
, (const char *)__func__, 2473)
;
2474 switch_channel_set_variable(tech_pvt->channel, SWITCH_R_SDP_VARIABLE, sdp)switch_channel_set_variable_var_check(tech_pvt->channel, "switch_r_sdp"
, sdp, SWITCH_TRUE)
;
2475 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_verto.c", (const char *)__func__
, 2475, (const char*)(session)
, SWITCH_LOG_DEBUG, "Remote SDP %s:\n%s\n", switch_channel_get_name(tech_pvt->channel), sdp);
2476 switch_core_media_set_sdp_codec_string(session, sdp, SDP_TYPE_RESPONSE);
2477
2478 if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE)) {
2479 pass_sdp(tech_pvt);
2480 } else {
2481 if (verto_tech_media(tech_pvt, tech_pvt->r_sdp, SDP_TYPE_RESPONSE) != SWITCH_STATUS_SUCCESS) {
2482 switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR")switch_channel_set_variable_var_check(tech_pvt->channel, "endpoint_disposition"
, "CODEC NEGOTIATION ERROR", SWITCH_TRUE)
;
2483 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CODEC ERROR"));
2484 err = 1;
2485 }
2486
2487 if (!err && switch_core_media_activate_rtp(tech_pvt->session) != SWITCH_STATUS_SUCCESS) {
2488 switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 2488, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
2489 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("MEDIA ERROR"));
2490 err = 1;
2491 }
2492 }
2493
2494 if (!err) {
2495 if (callee_id_name) {
2496 switch_channel_set_profile_var(tech_pvt->channel, "callee_id_name", callee_id_name);
2497 }
2498 if (callee_id_number) {
2499 switch_channel_set_profile_var(tech_pvt->channel, "callee_id_number", callee_id_number);
2500 }
2501 switch_channel_mark_answered(tech_pvt->channel)switch_channel_perform_mark_answered(tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 2501)
;
2502 }
2503
2504 switch_core_session_rwunlock(session);
2505 }
2506
2507 cleanup:
2508
2509
2510 if (!err) return SWITCH_TRUE;
2511
2512 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CALL DOES NOT EXIST"));
2513 cJSON_AddItemToObject(obj, "code", cJSON_CreateNumber(CODE_SESSION_ERROR-32002));
2514
2515
2516 return SWITCH_FALSE;
2517
2518}
2519
2520static switch_bool_t verto__bye_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
2521{
2522 cJSON *obj = cJSON_CreateObject();
2523 switch_core_session_t *session;
2524 cJSON *dialog = NULL((void*)0);
2525 const char *call_id = NULL((void*)0), *cause_str = NULL((void*)0);
2526 int err = 0;
2527 switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
2528
2529 *response = obj;
2530
2531 if (!(dialog = cJSON_GetObjectItem(params, "dialogParams"))) {
2532 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("Dialog data missing"));
2533 err = 1; goto cleanup;
2534 }
2535
2536 if (!(call_id = cJSON_GetObjectCstr(dialog, "callID"))) {
2537 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CallID missing"));
2538 err = 1; goto cleanup;
2539 }
2540
2541 if ((cause_str = cJSON_GetObjectCstr(params, "cause"))) {
2542 switch_call_cause_t check = switch_channel_str2cause(cause_str);
2543
2544 if (check != SWITCH_CAUSE_NONE) {
2545 cause = check;
2546 }
2547 }
2548
2549 cJSON_AddItemToObject(obj, "callID", cJSON_CreateString(call_id));
2550
2551 if ((session = switch_core_session_locate(call_id)switch_core_session_perform_locate(call_id, "mod_verto.c", (const
char *)__func__, 2551)
)) {
2552 verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
2553 tech_pvt->remote_hangup_cause = cause;
2554 switch_channel_hangup(tech_pvt->channel, cause)switch_channel_perform_hangup(tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 2554, cause)
;
2555
2556 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CALL ENDED"));
2557 cJSON_AddItemToObject(obj, "causeCode", cJSON_CreateNumber(cause));
2558 cJSON_AddItemToObject(obj, "cause", cJSON_CreateString(switch_channel_cause2str(cause)));
2559 switch_core_session_rwunlock(session);
2560 } else {
2561 err = 1;
2562 }
2563
2564 cleanup:
2565
2566
2567 if (!err) return SWITCH_TRUE;
2568
2569 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CALL DOES NOT EXIST"));
2570 cJSON_AddItemToObject(obj, "code", cJSON_CreateNumber(CODE_SESSION_ERROR-32002));
2571
2572
2573 return SWITCH_FALSE;
2574}
2575
2576static switch_status_t xfer_hanguphook(switch_core_session_t *session)
2577{
2578 switch_channel_t *channel = switch_core_session_get_channel(session);
2579 switch_channel_state_t state = switch_channel_get_state(channel);
2580
2581 if (state == CS_HANGUP) {
2582 switch_core_session_t *ksession;
2583 const char *uuid = switch_channel_get_variable(channel, "att_xfer_kill_uuid")switch_channel_get_variable_dup(channel, "att_xfer_kill_uuid"
, SWITCH_TRUE, -1)
;
2584
2585 if (uuid && (ksession = switch_core_session_force_locate(uuid)switch_core_session_perform_force_locate(uuid, "mod_verto.c",
(const char *)__func__, 2585)
)) {
2586 switch_channel_t *kchannel = switch_core_session_get_channel(ksession);
2587
2588 switch_channel_clear_flag(kchannel, CF_XFER_ZOMBIE);
2589 switch_channel_clear_flag(kchannel, CF_TRANSFER);
2590 if (switch_channel_up(kchannel)(switch_channel_check_signal(kchannel, SWITCH_TRUE) || switch_channel_get_state
(kchannel) < CS_HANGUP)
) {
2591 switch_channel_hangup(kchannel, SWITCH_CAUSE_NORMAL_CLEARING)switch_channel_perform_hangup(kchannel, "mod_verto.c", (const
char *)__func__, 2591, SWITCH_CAUSE_NORMAL_CLEARING)
;
2592 }
2593
2594 switch_core_session_rwunlock(ksession);
2595 }
2596
2597 switch_core_event_hook_remove_state_change(session, xfer_hanguphook);
2598
2599 }
2600
2601 return SWITCH_STATUS_SUCCESS;
2602}
2603
2604static void mark_transfer_record(switch_core_session_t *session, const char *br_a, const char *br_b)
2605{
2606 switch_core_session_t *br_b_session, *br_a_session;
2607 switch_channel_t *channel;
2608 const char *uvar1, *dvar1, *uvar2, *dvar2;
2609
2610 channel = switch_core_session_get_channel(session);
2611
2612 uvar1 = "verto_user";
2613 dvar1 = "verto_host";
2614
2615 if ((br_b_session = switch_core_session_locate(br_b)switch_core_session_perform_locate(br_b, "mod_verto.c", (const
char *)__func__, 2615)
) ) {
2616 switch_channel_t *br_b_channel = switch_core_session_get_channel(br_b_session);
2617 switch_caller_profile_t *cp = switch_channel_get_caller_profile(br_b_channel);
2618
2619 if (switch_channel_direction(br_b_channel) == SWITCH_CALL_DIRECTION_INBOUND) {
2620 uvar2 = "sip_from_user";
2621 dvar2 = "sip_from_host";
2622 } else {
2623 uvar2 = "sip_to_user";
2624 dvar2 = "sip_to_host";
2625 }
2626
2627 cp->transfer_source = switch_core_sprintf(cp->pool,
2628 "%ld:%s:att_xfer:%s@%s/%s@%s",
2629 (long) switch_epoch_time_now(NULL((void*)0)),
2630 cp->uuid_str,
2631 switch_channel_get_variable(channel, uvar1)switch_channel_get_variable_dup(channel, uvar1, SWITCH_TRUE, -
1)
,
2632 switch_channel_get_variable(channel, dvar1)switch_channel_get_variable_dup(channel, dvar1, SWITCH_TRUE, -
1)
,
2633 switch_channel_get_variable(br_b_channel, uvar2)switch_channel_get_variable_dup(br_b_channel, uvar2, SWITCH_TRUE
, -1)
,
2634 switch_channel_get_variable(br_b_channel, dvar2)switch_channel_get_variable_dup(br_b_channel, dvar2, SWITCH_TRUE
, -1)
);
2635
2636 switch_channel_add_variable_var_check(br_b_channel, SWITCH_TRANSFER_HISTORY_VARIABLE"transfer_history", cp->transfer_source, SWITCH_FALSE, SWITCH_STACK_PUSH);
2637 switch_channel_set_variable(br_b_channel, SWITCH_TRANSFER_SOURCE_VARIABLE, cp->transfer_source)switch_channel_set_variable_var_check(br_b_channel, "transfer_source"
, cp->transfer_source, SWITCH_TRUE)
;
2638
2639 switch_core_session_rwunlock(br_b_session);
2640 }
2641
2642
2643
2644 if ((br_a_session = switch_core_session_locate(br_a)switch_core_session_perform_locate(br_a, "mod_verto.c", (const
char *)__func__, 2644)
) ) {
2645 switch_channel_t *br_a_channel = switch_core_session_get_channel(br_a_session);
2646 switch_caller_profile_t *cp = switch_channel_get_caller_profile(br_a_channel);
2647
2648 if (switch_channel_direction(br_a_channel) == SWITCH_CALL_DIRECTION_INBOUND) {
2649 uvar2 = "sip_from_user";
2650 dvar2 = "sip_from_host";
2651 } else {
2652 uvar2 = "sip_to_user";
2653 dvar2 = "sip_to_host";
2654 }
2655
2656 cp->transfer_source = switch_core_sprintf(cp->pool,
2657 "%ld:%s:att_xfer:%s@%s/%s@%s",
2658 (long) switch_epoch_time_now(NULL((void*)0)),
2659 cp->uuid_str,
2660 switch_channel_get_variable(channel, uvar1)switch_channel_get_variable_dup(channel, uvar1, SWITCH_TRUE, -
1)
,
2661 switch_channel_get_variable(channel, dvar1)switch_channel_get_variable_dup(channel, dvar1, SWITCH_TRUE, -
1)
,
2662 switch_channel_get_variable(br_a_channel, uvar2)switch_channel_get_variable_dup(br_a_channel, uvar2, SWITCH_TRUE
, -1)
,
2663 switch_channel_get_variable(br_a_channel, dvar2)switch_channel_get_variable_dup(br_a_channel, dvar2, SWITCH_TRUE
, -1)
);
2664
2665 switch_channel_add_variable_var_check(br_a_channel, SWITCH_TRANSFER_HISTORY_VARIABLE"transfer_history", cp->transfer_source, SWITCH_FALSE, SWITCH_STACK_PUSH);
2666 switch_channel_set_variable(br_a_channel, SWITCH_TRANSFER_SOURCE_VARIABLE, cp->transfer_source)switch_channel_set_variable_var_check(br_a_channel, "transfer_source"
, cp->transfer_source, SWITCH_TRUE)
;
2667
2668 switch_core_session_rwunlock(br_a_session);
2669 }
2670
2671
2672}
2673
2674static switch_bool_t attended_transfer(switch_core_session_t *session, switch_core_session_t *b_session) {
2675 verto_pvt_t *tech_pvt = NULL((void*)0), *b_tech_pvt = NULL((void*)0);
2676 switch_bool_t result = SWITCH_FALSE;
2677 const char *br_a = NULL((void*)0), *br_b = NULL((void*)0);
2678
2679 tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
2680 b_tech_pvt = switch_core_session_get_private_class(b_session, SWITCH_PVT_SECONDARY);
2681
2682 switch_assert(b_tech_pvt)((b_tech_pvt) ? (void) (0) : __assert_fail ("b_tech_pvt", "mod_verto.c"
, 2682, __PRETTY_FUNCTION__))
;
2683 switch_assert(tech_pvt)((tech_pvt) ? (void) (0) : __assert_fail ("tech_pvt", "mod_verto.c"
, 2683, __PRETTY_FUNCTION__))
;
2684
2685 switch_channel_set_variable(tech_pvt->channel, "refer_uuid", switch_core_session_get_uuid(b_tech_pvt->session))switch_channel_set_variable_var_check(tech_pvt->channel, "refer_uuid"
, switch_core_session_get_uuid(b_tech_pvt->session), SWITCH_TRUE
)
;
2686 switch_channel_set_variable(b_tech_pvt->channel, "transfer_disposition", "replaced")switch_channel_set_variable_var_check(b_tech_pvt->channel,
"transfer_disposition", "replaced", SWITCH_TRUE)
;
2687
2688 br_a = switch_channel_get_partner_uuid(tech_pvt->channel);
2689 br_b = switch_channel_get_partner_uuid(b_tech_pvt->channel);
2690
2691 if (!switch_ivr_uuid_exists(br_a)) {
2692 br_a = NULL((void*)0);
2693 }
2694
2695 if (!switch_ivr_uuid_exists(br_b)) {
2696 br_b = NULL((void*)0);
2697 }
2698
2699 if (switch_channel_test_flag(b_tech_pvt->channel, CF_ORIGINATOR)) {
2700 switch_core_session_t *a_session;
2701
2702 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_verto.c", (const char *)__func__
, 2702, (const char*)(session)
, SWITCH_LOG_NOTICE,
2703 "Attended Transfer on originating session %s\n", switch_core_session_get_uuid(b_session));
2704
2705
2706
2707 switch_channel_set_variable_printf(b_tech_pvt->channel, "transfer_to", "satt:%s", br_a);
2708
2709 switch_channel_set_variable(b_tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER")switch_channel_set_variable_var_check(b_tech_pvt->channel,
"endpoint_disposition", "ATTENDED_TRANSFER", SWITCH_TRUE)
;
2710
2711
2712 switch_channel_clear_flag(b_tech_pvt->channel, CF_LEG_HOLDING);
2713 switch_channel_set_variable(b_tech_pvt->channel, SWITCH_HOLDING_UUID_VARIABLE, br_a)switch_channel_set_variable_var_check(b_tech_pvt->channel,
"holding_uuid", br_a, SWITCH_TRUE)
;
2714 switch_channel_set_flag(b_tech_pvt->channel, CF_XFER_ZOMBIE)switch_channel_set_flag_value(b_tech_pvt->channel, CF_XFER_ZOMBIE
, 1)
;
2715 switch_channel_set_flag(b_tech_pvt->channel, CF_TRANSFER)switch_channel_set_flag_value(b_tech_pvt->channel, CF_TRANSFER
, 1)
;
2716
2717
2718 if ((a_session = switch_core_session_locate(br_a)switch_core_session_perform_locate(br_a, "mod_verto.c", (const
char *)__func__, 2718)
)) {
2719 const char *moh = "local_stream://moh";
2720 switch_channel_t *a_channel = switch_core_session_get_channel(a_session);
2721 switch_caller_profile_t *prof = switch_channel_get_caller_profile(b_tech_pvt->channel);
2722 const char *tmp;
2723
2724 switch_core_event_hook_add_state_change(a_session, xfer_hanguphook);
2725 switch_channel_set_variable(a_channel, "att_xfer_kill_uuid", switch_core_session_get_uuid(b_session))switch_channel_set_variable_var_check(a_channel, "att_xfer_kill_uuid"
, switch_core_session_get_uuid(b_session), SWITCH_TRUE)
;
2726 switch_channel_set_variable(a_channel, "att_xfer_destination_number", prof->destination_number)switch_channel_set_variable_var_check(a_channel, "att_xfer_destination_number"
, prof->destination_number, SWITCH_TRUE)
;
2727 switch_channel_set_variable(a_channel, "att_xfer_callee_id_name", prof->callee_id_name)switch_channel_set_variable_var_check(a_channel, "att_xfer_callee_id_name"
, prof->callee_id_name, SWITCH_TRUE)
;
2728 switch_channel_set_variable(a_channel, "att_xfer_callee_id_number", prof->callee_id_number)switch_channel_set_variable_var_check(a_channel, "att_xfer_callee_id_number"
, prof->callee_id_number, SWITCH_TRUE)
;
2729
2730 if ((tmp = switch_channel_get_hold_music(a_channel))) {
2731 moh = tmp;
2732 }
2733
2734 if (!zstr(moh)_zstr(moh) && !strcasecmp(moh, "silence")) {
2735 moh = NULL((void*)0);
2736 }
2737
2738 if (moh) {
2739 char *xdest;
2740 xdest = switch_core_session_sprintf(a_session, "endless_playback:%s,park", moh);
2741 switch_ivr_session_transfer(a_session, xdest, "inline", NULL((void*)0));
2742 } else {
2743 switch_ivr_session_transfer(a_session, "park", "inline", NULL((void*)0));
2744 }
2745
2746 switch_core_session_rwunlock(a_session);
2747
2748 result = SWITCH_TRUE;
2749
2750 switch_channel_hangup(b_tech_pvt->channel, SWITCH_CAUSE_NORMAL_CLEARING)switch_channel_perform_hangup(b_tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 2750, SWITCH_CAUSE_NORMAL_CLEARING)
;
2751 } else {
2752 result = SWITCH_FALSE;
2753 }
2754
2755 } else if (br_a && br_b) {
2756 switch_core_session_t *tmp = NULL((void*)0);
2757
2758 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_verto.c", (const char *)__func__
, 2758, (const char*)(session)
, SWITCH_LOG_NOTICE, "Attended Transfer [%s][%s]\n",
2759 switch_str_nil(br_a)(br_a ? br_a : ""), switch_str_nil(br_b)(br_b ? br_b : ""));
2760
2761 if ((tmp = switch_core_session_locate(br_b)switch_core_session_perform_locate(br_b, "mod_verto.c", (const
char *)__func__, 2761)
)) {
2762 switch_channel_t *tchannel = switch_core_session_get_channel(tmp);
2763
2764 switch_channel_set_variable(tchannel, "transfer_disposition", "bridge")switch_channel_set_variable_var_check(tchannel, "transfer_disposition"
, "bridge", SWITCH_TRUE)
;
2765
2766 switch_channel_set_flag(tchannel, CF_ATTENDED_TRANSFER)switch_channel_set_flag_value(tchannel, CF_ATTENDED_TRANSFER,
1)
;
2767 switch_core_session_rwunlock(tmp);
2768 }
2769
2770 if (switch_true(switch_channel_get_variable(tech_pvt->channel, "recording_follow_transfer")switch_channel_get_variable_dup(tech_pvt->channel, "recording_follow_transfer"
, SWITCH_TRUE, -1)
) &&
2771 (tmp = switch_core_session_locate(br_a)switch_core_session_perform_locate(br_a, "mod_verto.c", (const
char *)__func__, 2771)
)) {
2772 switch_channel_set_variable(switch_core_session_get_channel(tmp), "transfer_disposition", "bridge")switch_channel_set_variable_var_check(switch_core_session_get_channel
(tmp), "transfer_disposition", "bridge", SWITCH_TRUE)
;
2773 switch_core_media_bug_transfer_recordings(session, tmp);
2774 switch_core_session_rwunlock(tmp);
2775 }
2776
2777
2778 if (switch_true(switch_channel_get_variable(b_tech_pvt->channel, "recording_follow_transfer")switch_channel_get_variable_dup(b_tech_pvt->channel, "recording_follow_transfer"
, SWITCH_TRUE, -1)
) &&
2779 (tmp = switch_core_session_locate(br_b)switch_core_session_perform_locate(br_b, "mod_verto.c", (const
char *)__func__, 2779)
)) {
2780 switch_core_media_bug_transfer_recordings(b_session, tmp);
2781 switch_core_session_rwunlock(tmp);
2782 }
2783
2784 switch_channel_set_variable_printf(tech_pvt->channel, "transfer_to", "att:%s", br_b);
2785
2786 mark_transfer_record(session, br_a, br_b);
2787
2788 switch_ivr_uuid_bridge(br_a, br_b);
2789 switch_channel_set_variable(b_tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER")switch_channel_set_variable_var_check(b_tech_pvt->channel,
"endpoint_disposition", "ATTENDED_TRANSFER", SWITCH_TRUE)
;
2790
2791 result = SWITCH_TRUE;
2792
2793 switch_channel_clear_flag(b_tech_pvt->channel, CF_LEG_HOLDING);
2794 switch_channel_set_variable(b_tech_pvt->channel, "park_timeout", "2:attended_transfer")switch_channel_set_variable_var_check(b_tech_pvt->channel,
"park_timeout", "2:attended_transfer", SWITCH_TRUE)
;
2795 switch_channel_set_state(b_tech_pvt->channel, CS_PARK)switch_channel_perform_set_state(b_tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 2795, CS_PARK)
;
2796
2797 } else {
2798 if (!br_a && !br_b) {
2799 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_verto.c", (const char *)__func__
, 2799, (const char*)(session)
, SWITCH_LOG_WARNING,
2800 "Cannot transfer channels that are not in a bridge.\n");
2801 result = SWITCH_FALSE;
2802 } else {
2803 switch_core_session_t *t_session, *hup_session;
2804 switch_channel_t *hup_channel;
2805 const char *ext;
2806
2807 if (br_a && !br_b) {
2808 t_session = switch_core_session_locate(br_a)switch_core_session_perform_locate(br_a, "mod_verto.c", (const
char *)__func__, 2808)
;
2809 hup_channel = b_tech_pvt->channel;
2810 hup_session = b_session;
2811 } else {
2812 verto_pvt_t *h_tech_pvt = (verto_pvt_t *) switch_core_session_get_private_class(b_session, SWITCH_PVT_SECONDARY);
2813 t_session = switch_core_session_locate(br_b)switch_core_session_perform_locate(br_b, "mod_verto.c", (const
char *)__func__, 2813)
;
2814 hup_channel = tech_pvt->channel;
2815 hup_session = session;
2816 switch_channel_clear_flag(h_tech_pvt->channel, CF_LEG_HOLDING);
2817 switch_channel_hangup(b_tech_pvt->channel, SWITCH_CAUSE_ATTENDED_TRANSFER)switch_channel_perform_hangup(b_tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 2817, SWITCH_CAUSE_ATTENDED_TRANSFER
)
;
2818 }
2819
2820 if (t_session) {
2821 //switch_channel_t *t_channel = switch_core_session_get_channel(t_session);
2822 const char *idest = switch_channel_get_variable(hup_channel, "inline_destination")switch_channel_get_variable_dup(hup_channel, "inline_destination"
, SWITCH_TRUE, -1)
;
2823 ext = switch_channel_get_variable(hup_channel, "destination_number")switch_channel_get_variable_dup(hup_channel, "destination_number"
, SWITCH_TRUE, -1)
;
2824
2825 if (switch_true(switch_channel_get_variable(hup_channel, "recording_follow_transfer")switch_channel_get_variable_dup(hup_channel, "recording_follow_transfer"
, SWITCH_TRUE, -1)
)) {
2826 switch_core_media_bug_transfer_recordings(hup_session, t_session);
2827 }
2828
2829 if (idest) {
2830 switch_ivr_session_transfer(t_session, idest, "inline", NULL((void*)0));
2831 } else {
2832 switch_ivr_session_transfer(t_session, ext, NULL((void*)0), NULL((void*)0));
2833 }
2834
2835 result = SWITCH_TRUE;
2836 switch_channel_hangup(hup_channel, SWITCH_CAUSE_ATTENDED_TRANSFER)switch_channel_perform_hangup(hup_channel, "mod_verto.c", (const
char *)__func__, 2836, SWITCH_CAUSE_ATTENDED_TRANSFER)
;
2837 } else {
2838 result = SWITCH_FALSE;
2839 }
2840 }
2841 }
2842 if (b_session) {
2843 switch_core_session_rwunlock(b_session);
2844 }
2845
2846 return result;
2847}
2848
2849
2850static switch_bool_t verto__modify_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
2851{
2852 cJSON *obj = cJSON_CreateObject();
2853 switch_core_session_t *session;
2854 cJSON *dialog = NULL((void*)0);
2855 const char *call_id = NULL((void*)0), *destination = NULL((void*)0), *action = NULL((void*)0);
2856 int err = 0;
2857
2858 *response = obj;
2859
2860 if (!(dialog = cJSON_GetObjectItem(params, "dialogParams"))) {
2861 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("Dialog data missing"));
2862 err = 1; goto cleanup;
2863 }
2864
2865 if (!(call_id = cJSON_GetObjectCstr(dialog, "callID"))) {
2866 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CallID missing"));
2867 err = 1; goto cleanup;
2868 }
2869
2870 if (!(action = cJSON_GetObjectCstr(params, "action"))) {
2871 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("action missing"));
2872 err = 1; goto cleanup;
2873 }
2874
2875 cJSON_AddItemToObject(obj, "callID", cJSON_CreateString(call_id));
2876 cJSON_AddItemToObject(obj, "action", cJSON_CreateString(action));
2877
2878
2879 if ((session = switch_core_session_locate(call_id)switch_core_session_perform_locate(call_id, "mod_verto.c", (const
char *)__func__, 2879)
)) {
2880 verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
2881
2882 if (!strcasecmp(action, "transfer")) {
2883 switch_core_session_t *other_session = NULL((void*)0);
2884
2885 if (!(destination = cJSON_GetObjectCstr(params, "destination"))) {
2886 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("destination missing"));
2887 err = 1; goto rwunlock;
2888 }
2889
2890 if (switch_core_session_get_partner(tech_pvt->session, &other_session)switch_core_session_perform_get_partner(tech_pvt->session,
&other_session, "mod_verto.c", (const char *)__func__, 2890
)
== SWITCH_STATUS_SUCCESS) {
2891 switch_ivr_session_transfer(other_session, destination, NULL((void*)0), NULL((void*)0));
2892 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CALL TRANSFERRED"));
2893 switch_core_session_rwunlock(other_session);
2894 } else {
2895 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("call is not bridged"));
2896 err = 1; goto rwunlock;
2897 }
2898
2899 } else if (!strcasecmp(action, "replace")) {
2900 const char *replace_call_id;
2901 switch_core_session_t *b_session = NULL((void*)0);
2902
2903 if (!(replace_call_id = cJSON_GetObjectCstr(params, "replaceCallID"))) {
2904 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("replaceCallID missing"));
2905 err = 1; goto rwunlock;
2906 }
2907
2908 if ((b_session = switch_core_session_locate(replace_call_id)switch_core_session_perform_locate(replace_call_id, "mod_verto.c"
, (const char *)__func__, 2908)
)) {
2909 err = (int) attended_transfer(session, b_session);
2910 if (err) {
2911 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("transfer failed"));
2912 }
2913 switch_core_session_rwunlock(b_session);
2914 } else {
2915 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("invalid transfer leg"));
2916 err = 1; goto rwunlock;
2917 }
2918 } else if (!strcasecmp(action, "hold")) {
2919 switch_core_media_toggle_hold(session, 1);
2920 } else if (!strcasecmp(action, "unhold")) {
2921 switch_core_media_toggle_hold(session, 0);
2922 } else if (!strcasecmp(action, "toggleHold")) {
2923 switch_core_media_toggle_hold(session, !!!switch_channel_test_flag(tech_pvt->channel, CF_PROTO_HOLD));
2924 }
2925
2926 cJSON_AddItemToObject(obj, "holdState", cJSON_CreateString(switch_channel_test_flag(tech_pvt->channel, CF_PROTO_HOLD) ? "held" : "active"));
2927
2928
2929 rwunlock:
2930
2931 switch_core_session_rwunlock(session);
2932 } else {
2933 err = 1;
2934 }
2935
2936 cleanup:
2937
2938
2939 if (!err) return SWITCH_TRUE;
2940
2941 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CALL DOES NOT EXIST"));
2942 cJSON_AddItemToObject(obj, "code", cJSON_CreateNumber(CODE_SESSION_ERROR-32002));
2943
2944
2945 return SWITCH_FALSE;
2946}
2947
2948static switch_bool_t verto__attach_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
2949{
2950 cJSON *obj = cJSON_CreateObject();
2951 switch_core_session_t *session = NULL((void*)0);
2952 int err = 0;
2953 cJSON *dialog;
2954 verto_pvt_t *tech_pvt = NULL((void*)0);
2955 const char *call_id = NULL((void*)0), *sdp = NULL((void*)0);
2956 uint8_t match = 0, p = 0;
2957
2958 *response = obj;
2959
2960 if (!(dialog = cJSON_GetObjectItem(params, "dialogParams"))) {
2961 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("Dialog data missing"));
2962 err = 1; goto cleanup;
2963 }
2964
2965 if (!(sdp = cJSON_GetObjectCstr(params, "sdp"))) {
2966 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("SDP missing"));
2967 err = 1; goto cleanup;
2968 }
2969
2970 if (!(call_id = cJSON_GetObjectCstr(dialog, "callID"))) {
2971 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CallID missing"));
2972 err = 1; goto cleanup;
2973 }
2974
2975 if (!(session = switch_core_session_locate(call_id)switch_core_session_perform_locate(call_id, "mod_verto.c", (const
char *)__func__, 2975)
)) {
2976 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("Call does not exist"));
2977 err = 1; goto cleanup;
2978 }
2979
2980 tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
2981 tech_pvt->r_sdp = switch_core_session_strdup(session, sdp)switch_core_perform_session_strdup(session, sdp, "mod_verto.c"
, (const char *)__func__, 2981)
;
2982
2983
2984 if (!switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED)) {
2985 switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 2985, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
2986 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("Cannot attach to a call that has not been answered."));
2987 err = 1; goto cleanup;
2988 }
2989
2990
2991 switch_channel_set_variable(tech_pvt->channel, SWITCH_R_SDP_VARIABLE, tech_pvt->r_sdp)switch_channel_set_variable_var_check(tech_pvt->channel, "switch_r_sdp"
, tech_pvt->r_sdp, SWITCH_TRUE)
;
2992 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_verto.c", (const char *)__func__
, 2992, (const char*)(session)
, SWITCH_LOG_DEBUG, "Remote SDP %s:\n%s\n",
2993 switch_channel_get_name(tech_pvt->channel), tech_pvt->r_sdp);
2994
2995 switch_core_media_clear_ice(tech_pvt->session);
2996 switch_channel_set_flag(tech_pvt->channel, CF_REINVITE)switch_channel_set_flag_value(tech_pvt->channel, CF_REINVITE
, 1)
;
2997
2998 //switch_channel_audio_sync(tech_pvt->channel);
2999 //switch_channel_set_flag(tech_pvt->channel, CF_VIDEO_BREAK);
3000 //switch_core_session_kill_channel(tech_pvt->session, SWITCH_SIG_BREAK);
3001
3002 if ((match = switch_core_media_negotiate_sdp(tech_pvt->session, tech_pvt->r_sdp, &p, SDP_TYPE_RESPONSE))) {
3003 if (switch_core_media_activate_rtp(tech_pvt->session) != SWITCH_STATUS_SUCCESS) {
3004 switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "MEDIA ERROR")switch_channel_set_variable_var_check(tech_pvt->channel, "endpoint_disposition"
, "MEDIA ERROR", SWITCH_TRUE)
;
3005 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("MEDIA ERROR"));
3006 err = 1; goto cleanup;
3007 }
3008 } else {
3009 switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR")switch_channel_set_variable_var_check(tech_pvt->channel, "endpoint_disposition"
, "CODEC NEGOTIATION ERROR", SWITCH_TRUE)
;
3010 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CODEC NEGOTIATION ERROR"));
3011 err = 1; goto cleanup;
3012 }
3013
3014 cleanup:
3015
3016 if (tech_pvt) {
3017 switch_channel_clear_flag(tech_pvt->channel, CF_REINVITE);
3018 switch_clear_flag(tech_pvt, TFLAG_ATTACH_REQ)(tech_pvt)->flags &= ~(TFLAG_ATTACH_REQ);
3019 if (switch_channel_test_flag(tech_pvt->channel, CF_CONFERENCE)) {
3020 switch_channel_set_flag(tech_pvt->channel, CF_CONFERENCE_ADV)switch_channel_set_flag_value(tech_pvt->channel, CF_CONFERENCE_ADV
, 1)
;
3021 }
3022 }
3023
3024 if (session) {
3025 switch_core_session_rwunlock(session);
3026 }
3027
3028 if (!err) {
3029 return SWITCH_TRUE;
3030 }
3031
3032 if (tech_pvt && tech_pvt->channel) {
3033 switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL)switch_channel_perform_hangup(tech_pvt->channel, "mod_verto.c"
, (const char *)__func__, 3033, SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL
)
;
3034 }
3035
3036
3037 cJSON_AddItemToObject(obj, "code", cJSON_CreateNumber(CODE_SESSION_ERROR-32002));
3038
3039 return SWITCH_FALSE;
3040}
3041
3042static switch_bool_t verto__info_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
3043{
3044 cJSON *msg = NULL((void*)0), *dialog = NULL((void*)0);
3045 const char *call_id = NULL((void*)0), *dtmf = NULL((void*)0);
3046 switch_bool_t r = SWITCH_TRUE;
3047 char *proto = VERTO_CHAT_PROTO"verto";
3048 char *pproto = NULL((void*)0);
3049
3050 *response = cJSON_CreateObject();
3051
3052 if ((dialog = cJSON_GetObjectItem(params, "dialogParams")) && (call_id = cJSON_GetObjectCstr(dialog, "callID"))) {
3053 switch_core_session_t *session = NULL((void*)0);
3054
3055 if ((session = switch_core_session_locate(call_id)switch_core_session_perform_locate(call_id, "mod_verto.c", (const
char *)__func__, 3055)
)) {
3056
3057 if ((dtmf = cJSON_GetObjectCstr(params, "dtmf"))) {
3058 verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
3059 char *send = switch_mprintf("~%s", dtmf);
3060
3061 if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE)) {
3062 switch_core_session_t *other_session = NULL((void*)0);
3063
3064 if (switch_core_session_get_partner(tech_pvt->session, &other_session)switch_core_session_perform_get_partner(tech_pvt->session,
&other_session, "mod_verto.c", (const char *)__func__, 3064
)
== SWITCH_STATUS_SUCCESS) {
3065 switch_core_session_send_dtmf_string(other_session, send);
3066 switch_core_session_rwunlock(other_session);
3067 }
3068 } else {
3069 switch_channel_queue_dtmf_string(tech_pvt->channel, send);
3070 }
3071 free(send);
3072 cJSON_AddItemToObject(*response, "message", cJSON_CreateString("SENT"));
3073 }
3074
3075 switch_core_session_rwunlock(session);
3076 }
3077 }
3078
3079 if ((msg = cJSON_GetObjectItem(params, "msg"))) {
3080 switch_event_t *event;
3081 char *to = (char *) cJSON_GetObjectCstr(msg, "to");
3082 //char *from = (char *) cJSON_GetObjectCstr(msg, "from");
3083 cJSON *i, *indialog = cJSON_GetObjectItem(msg, "inDialog");
3084 const char *body = cJSON_GetObjectCstr(msg, "body");
3085 switch_bool_t is_dialog = indialog && (indialog->type == cJSON_True1 || (indialog->type == cJSON_String4 && switch_true(indialog->valuestring)));
3086
3087 if (!zstr(to)_zstr(to)) {
3088 if (strchr(to, '+')(__extension__ (__builtin_constant_p ('+') && !__builtin_constant_p
(to) && ('+') == '\0' ? (char *) __rawmemchr (to, '+'
) : __builtin_strchr (to, '+')))
) {
3089 pproto = strdup(to)(__extension__ (__builtin_constant_p (to) && ((size_t
)(const void *)((to) + 1) - (size_t)(const void *)(to) == 1) ?
(((const char *) (to))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (to) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, to, __len); __retval; })) : __strdup
(to)))
;
3090 if ((to = strchr(pproto, '+')(__extension__ (__builtin_constant_p ('+') && !__builtin_constant_p
(pproto) && ('+') == '\0' ? (char *) __rawmemchr (pproto
, '+') : __builtin_strchr (pproto, '+')))
)) {
3091 *to++ = '\0';
3092 }
3093 proto = pproto;
3094 }
3095 }
3096
3097 if (!zstr(to)_zstr(to) && !zstr(body)_zstr(body) && switch_event_create(&event, SWITCH_EVENT_MESSAGE)switch_event_create_subclass_detailed("mod_verto.c", (const char
* )(const char *)__func__, 3097, &event, SWITCH_EVENT_MESSAGE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
3098 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VERTO_CHAT_PROTO"verto");
3099
3100 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", jsock->uid);
3101 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_user", jsock->id);
3102 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_host", jsock->domain);
3103
3104
3105 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to", to);
3106 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "text/plain");
3107 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_full", jsock->id);
3108 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "verto_profile", jsock->profile->name);
3109 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "verto_jsock_uuid", jsock->uuid_str);
3110
3111 for(i = msg->child; i; i = i->next) {
3112 if (!zstr(i->string)_zstr(i->string) && !zstr(i->valuestring)_zstr(i->valuestring) && (!strncasecmp(i->string, "from_", 5) || !strncasecmp(i->string, "to_", 3))) {
3113 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, i->string, i->valuestring);
3114 }
3115 }
3116
3117 if (is_dialog) {
3118 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call_id", call_id);
3119 }
3120
3121 switch_event_add_body(event, "%s", body);
3122
3123 if (strcasecmp(proto, VERTO_CHAT_PROTO"verto")) {
3124 switch_core_chat_send(proto, event);
3125 }
3126
3127 if (is_dialog) {
3128 if ((dialog = cJSON_GetObjectItem(params, "dialogParams")) && (call_id = cJSON_GetObjectCstr(dialog, "callID"))) {
3129 switch_core_session_t *session = NULL((void*)0);
3130
3131 if ((session = switch_core_session_locate(call_id)switch_core_session_perform_locate(call_id, "mod_verto.c", (const
char *)__func__, 3131)
)) {
3132 switch_core_session_queue_event(session, &event);
3133 switch_core_session_rwunlock(session);
3134 }
3135 }
3136
3137 } else {
3138 switch_core_chat_send("GLOBAL", event);
3139 }
3140
3141 if (event) {
3142 switch_event_destroy(&event);
3143 }
3144
3145 cJSON_AddItemToObject(*response, "message", cJSON_CreateString("SENT"));
3146 r = SWITCH_TRUE;
3147
3148 } else {
3149 r = SWITCH_FALSE;
3150 cJSON_AddItemToObject(*response, "message", cJSON_CreateString("INVALID MESSAGE to and body params required"));
3151 }
3152
3153
3154 switch_safe_free(pproto)if (pproto) {free(pproto);pproto=((void*)0);};
3155 }
3156
3157
3158 return r;
3159}
3160
3161static switch_bool_t verto__invite_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
3162{
3163 cJSON *obj = cJSON_CreateObject();
3164 switch_core_session_t *session = NULL((void*)0);
3165 switch_channel_t *channel;
3166 switch_event_t *var_event;
3167 switch_call_cause_t reason = SWITCH_CAUSE_INVALID_MSG_UNSPECIFIED, cancel_cause = 0;
3168 switch_caller_profile_t *caller_profile;
3169 int err = 0;
3170 cJSON *dialog;
3171 verto_pvt_t *tech_pvt;
3172 char name[512];
3173 const char *var, *destination_number, *call_id = NULL((void*)0), *sdp = NULL((void*)0),
3174 *caller_id_name = NULL((void*)0), *caller_id_number = NULL((void*)0), *remote_caller_id_name = NULL((void*)0), *remote_caller_id_number = NULL((void*)0),*context = NULL((void*)0);
3175
3176 *response = obj;
3177
3178 switch_event_create_plain(&var_event, SWITCH_EVENT_CHANNEL_DATA);
3179
3180 if (!(dialog = cJSON_GetObjectItem(params, "dialogParams"))) {
3181 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("Dialog data missing"));
3182 err = 1; goto cleanup;
3183 }
3184
3185 if (!(call_id = cJSON_GetObjectCstr(dialog, "callID"))) {
3186 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CallID missing"));
3187 err = 1; goto cleanup;
3188 }
3189
3190 if (!(sdp = cJSON_GetObjectCstr(params, "sdp"))) {
3191 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("SDP missing"));
3192 err = 1; goto cleanup;
3193 }
3194
3195 switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_uuid", call_id);
3196 if ((reason = switch_core_session_outgoing_channel(NULL((void*)0), var_event, "rtc",
3197 NULL((void*)0), &session, NULL((void*)0), SOF_NONE, &cancel_cause)) != SWITCH_CAUSE_SUCCESS) {
3198 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("Cannot create channel"));
3199 err = 1; goto cleanup;
3200 }
3201
3202 switch_ivr_set_user(session, jsock->uid);
3203
3204 channel = switch_core_session_get_channel(session);
3205 switch_channel_set_direction(channel, SWITCH_CALL_DIRECTION_INBOUND);
3206
3207 tech_pvt = switch_core_session_alloc(session, sizeof(*tech_pvt))switch_core_perform_session_alloc(session, sizeof(*tech_pvt),
"mod_verto.c", (const char *)__func__, 3207)
;
3208 tech_pvt->session = session;
3209 tech_pvt->channel = channel;
3210 tech_pvt->jsock_uuid = switch_core_session_strdup(session, jsock->uuid_str)switch_core_perform_session_strdup(session, jsock->uuid_str
, "mod_verto.c", (const char *)__func__, 3210)
;
3211 tech_pvt->r_sdp = switch_core_session_strdup(session, sdp)switch_core_perform_session_strdup(session, sdp, "mod_verto.c"
, (const char *)__func__, 3211)
;
3212 switch_core_media_set_sdp_codec_string(session, sdp, SDP_TYPE_REQUEST);
3213 switch_core_session_set_private_class(session, tech_pvt, SWITCH_PVT_SECONDARY);
3214
3215
3216 tech_pvt->call_id = switch_core_session_strdup(session, call_id)switch_core_perform_session_strdup(session, call_id, "mod_verto.c"
, (const char *)__func__, 3216)
;
3217 if ((tech_pvt->smh = switch_core_session_get_media_handle(session))) {
3218 tech_pvt->mparams = switch_core_media_get_mparams(tech_pvt->smh);
3219 verto_set_media_options(tech_pvt, jsock->profile);
3220 } else {
3221 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("Cannot create media handle"));
3222 err = 1; goto cleanup;
3223 }
3224
3225 if (!(destination_number = cJSON_GetObjectCstr(dialog, "destination_number"))) {
3226 destination_number = "service";
3227 }
3228
3229 switch_snprintf(name, sizeof(name), "verto.rtc/%s", destination_number);
3230 switch_channel_set_name(channel, name);
3231 switch_channel_set_variable(channel, "jsock_uuid_str", jsock->uuid_str)switch_channel_set_variable_var_check(channel, "jsock_uuid_str"
, jsock->uuid_str, SWITCH_TRUE)
;
3232 switch_channel_set_variable(channel, "verto_user", jsock->uid)switch_channel_set_variable_var_check(channel, "verto_user", jsock
->uid, SWITCH_TRUE)
;
3233 switch_channel_set_variable(channel, "presence_id", jsock->uid)switch_channel_set_variable_var_check(channel, "presence_id",
jsock->uid, SWITCH_TRUE)
;
3234 switch_channel_set_variable(channel, "chat_proto", VERTO_CHAT_PROTO)switch_channel_set_variable_var_check(channel, "chat_proto", "verto"
, SWITCH_TRUE)
;
3235 switch_channel_set_variable(channel, "verto_host", jsock->domain)switch_channel_set_variable_var_check(channel, "verto_host", jsock
->domain, SWITCH_TRUE)
;
3236 switch_channel_set_variable(channel, "event_channel_cookie", tech_pvt->jsock_uuid)switch_channel_set_variable_var_check(channel, "event_channel_cookie"
, tech_pvt->jsock_uuid, SWITCH_TRUE)
;
3237 switch_channel_set_variable(channel, "verto_profile_name", jsock->profile->name)switch_channel_set_variable_var_check(channel, "verto_profile_name"
, jsock->profile->name, SWITCH_TRUE)
;
3238
3239 caller_id_name = cJSON_GetObjectCstr(dialog, "caller_id_name");
3240 caller_id_number = cJSON_GetObjectCstr(dialog, "caller_id_number");
3241
3242 remote_caller_id_name = cJSON_GetObjectCstr(dialog, "remote_caller_id_name");
3243 remote_caller_id_number = cJSON_GetObjectCstr(dialog, "remote_caller_id_number");
3244
3245 if (zstr(caller_id_name)_zstr(caller_id_name)) {
3246 if ((var = switch_event_get_header(jsock->params, "caller-id-name")switch_event_get_header_idx(jsock->params, "caller-id-name"
, -1)
)) {
3247 caller_id_name = var;
3248 }
3249 }
3250
3251 if (zstr(caller_id_number)_zstr(caller_id_number)) {
3252 if ((var = switch_event_get_header(jsock->params, "caller-id-number")switch_event_get_header_idx(jsock->params, "caller-id-number"
, -1)
)) {
3253 caller_id_number = var;
3254 }
3255 }
3256
3257 if (!(context = switch_event_get_header(jsock->vars, "user_context")switch_event_get_header_idx(jsock->vars, "user_context", -
1)
)) {
3258 context = switch_either(jsock->context, jsock->profile->context)_zstr(jsock->context) ? jsock->profile->context : jsock
->context
;
3259 }
3260
3261 if ((caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
3262 jsock->uid,
3263 switch_either(jsock->dialplan, jsock->profile->dialplan)_zstr(jsock->dialplan) ? jsock->profile->dialplan : jsock
->dialplan
,
3264 caller_id_name,
3265 caller_id_number,
3266 inet_ntoa(jsock->remote_addr.sin_addr),
3267 cJSON_GetObjectCstr(dialog, "ani"),
3268 cJSON_GetObjectCstr(dialog, "aniii"),
3269 cJSON_GetObjectCstr(dialog, "rdnis"),
3270 modname,
3271 context,
3272 destination_number))) {
3273
3274 switch_channel_set_caller_profile(channel, caller_profile);
3275
3276 }
3277
3278 switch_channel_set_profile_var(channel, "callee_id_name", remote_caller_id_name);
3279 switch_channel_set_profile_var(channel, "callee_id_number", remote_caller_id_number);
3280
3281
3282 switch_channel_set_variable(channel, "verto_remote_caller_id_name", remote_caller_id_name)switch_channel_set_variable_var_check(channel, "verto_remote_caller_id_name"
, remote_caller_id_name, SWITCH_TRUE)
;
3283 switch_channel_set_variable(channel, "verto_remote_caller_id_number", remote_caller_id_number)switch_channel_set_variable_var_check(channel, "verto_remote_caller_id_number"
, remote_caller_id_number, SWITCH_TRUE)
;
3284
3285
3286
3287 switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, sdp)switch_channel_set_variable_var_check(channel, "switch_r_sdp"
, sdp, SWITCH_TRUE)
;
3288 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_verto.c", (const char *)__func__
, 3288, (const char*)(session)
, SWITCH_LOG_DEBUG, "Remote SDP %s:\n%s\n", switch_channel_get_name(tech_pvt->channel), sdp);
3289
3290 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CALL CREATED"));
3291 cJSON_AddItemToObject(obj, "callID", cJSON_CreateString(tech_pvt->call_id));
3292
3293 switch_channel_add_state_handler(channel, &verto_state_handlers);
3294 switch_core_event_hook_add_receive_message(session, messagehook);
3295 switch_channel_set_state(channel, CS_INIT)switch_channel_perform_set_state(channel, "mod_verto.c", (const
char *)__func__, 3295, CS_INIT)
;
3296 track_pvt(tech_pvt);
3297 switch_core_session_thread_launch(session);
3298
3299 cleanup:
3300
3301 switch_event_destroy(&var_event);
3302
3303 if (!err) {
3304 return SWITCH_TRUE;
3305 }
3306
3307 if (session) {
3308 switch_core_session_destroy(&session)switch_core_session_perform_destroy(&session, "mod_verto.c"
, (const char *)__func__, 3308)
;
3309 }
3310
3311 cJSON_AddItemToObject(obj, "causeCode", cJSON_CreateNumber(reason));
3312 cJSON_AddItemToObject(obj, "cause", cJSON_CreateString(switch_channel_cause2str(reason)));
3313 cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CALL ERROR"));
3314 cJSON_AddItemToObject(obj, "code", cJSON_CreateNumber(CODE_SESSION_ERROR-32002));
3315
3316 return SWITCH_FALSE;
3317
3318}
3319
3320static switch_bool_t event_channel_check_auth(jsock_t *jsock, const char *event_channel)
3321{
3322
3323 char *main_event_channel = NULL((void*)0);
3324 switch_bool_t ok = SWITCH_TRUE, pre_ok = SWITCH_FALSE;
3325 switch_core_session_t *session = NULL((void*)0);
3326
3327 switch_assert(event_channel)((event_channel) ? (void) (0) : __assert_fail ("event_channel"
, "mod_verto.c", 3327, __PRETTY_FUNCTION__))
;
3328
3329 pre_ok = switch_event_channel_permission_verify(jsock->uuid_str, event_channel);
3330
3331 if (!pre_ok && (session = switch_core_session_locate(event_channel)switch_core_session_perform_locate(event_channel, "mod_verto.c"
, (const char *)__func__, 3331)
)) {
3332 switch_channel_t *channel = switch_core_session_get_channel(session);
3333 const char *jsock_uuid_str = switch_channel_get_variable(channel, "jsock_uuid_str")switch_channel_get_variable_dup(channel, "jsock_uuid_str", SWITCH_TRUE
, -1)
;
3334
3335 if (jsock_uuid_str && !strcmp(jsock_uuid_str, jsock->uuid_str)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(jsock_uuid_str) && __builtin_constant_p (jsock->
uuid_str) && (__s1_len = __builtin_strlen (jsock_uuid_str
), __s2_len = __builtin_strlen (jsock->uuid_str), (!((size_t
)(const void *)((jsock_uuid_str) + 1) - (size_t)(const void *
)(jsock_uuid_str) == 1) || __s1_len >= 4) && (!((size_t
)(const void *)((jsock->uuid_str) + 1) - (size_t)(const void
*)(jsock->uuid_str) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(jsock_uuid_str, jsock->uuid_str) : (__builtin_constant_p
(jsock_uuid_str) && ((size_t)(const void *)((jsock_uuid_str
) + 1) - (size_t)(const void *)(jsock_uuid_str) == 1) &&
(__s1_len = __builtin_strlen (jsock_uuid_str), __s1_len <
4) ? (__builtin_constant_p (jsock->uuid_str) && (
(size_t)(const void *)((jsock->uuid_str) + 1) - (size_t)(const
void *)(jsock->uuid_str) == 1) ? __builtin_strcmp (jsock_uuid_str
, jsock->uuid_str) : (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (jsock->uuid_str
); int __result = (((const unsigned char *) (const char *) (jsock_uuid_str
))[0] - __s2[0]); if (__s1_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (jsock_uuid_str
))[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (jsock_uuid_str
))[2] - __s2[2]); if (__s1_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (jsock_uuid_str
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
jsock->uuid_str) && ((size_t)(const void *)((jsock
->uuid_str) + 1) - (size_t)(const void *)(jsock->uuid_str
) == 1) && (__s2_len = __builtin_strlen (jsock->uuid_str
), __s2_len < 4) ? (__builtin_constant_p (jsock_uuid_str) &&
((size_t)(const void *)((jsock_uuid_str) + 1) - (size_t)(const
void *)(jsock_uuid_str) == 1) ? __builtin_strcmp (jsock_uuid_str
, jsock->uuid_str) : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (jsock_uuid_str
); int __result = (((const unsigned char *) (const char *) (jsock
->uuid_str))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (jsock->uuid_str))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (jsock->uuid_str))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (jsock->uuid_str))[3] - __s2[3]); }
} __result; })))) : __builtin_strcmp (jsock_uuid_str, jsock->
uuid_str)))); })
) {
3336 pre_ok = SWITCH_TRUE;
3337 }
3338
3339 switch_core_session_rwunlock(session);
3340 }
3341
3342 if (pre_ok) {
3343 return pre_ok;
3344 }
3345
3346 if (jsock->allowed_event_channels) {
3347 if (strchr(event_channel, '.')(__extension__ (__builtin_constant_p ('.') && !__builtin_constant_p
(event_channel) && ('.') == '\0' ? (char *) __rawmemchr
(event_channel, '.') : __builtin_strchr (event_channel, '.')
))
) {
3348 char *p;
3349 main_event_channel = strdup(event_channel)(__extension__ (__builtin_constant_p (event_channel) &&
((size_t)(const void *)((event_channel) + 1) - (size_t)(const
void *)(event_channel) == 1) ? (((const char *) (event_channel
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen (event_channel) + 1; char *__retval = (
char *) malloc (__len); if (__retval != ((void*)0)) __retval =
(char *) memcpy (__retval, event_channel, __len); __retval; }
)) : __strdup (event_channel)))
;
3350 if ((p = strchr(main_event_channel, '.')(__extension__ (__builtin_constant_p ('.') && !__builtin_constant_p
(main_event_channel) && ('.') == '\0' ? (char *) __rawmemchr
(main_event_channel, '.') : __builtin_strchr (main_event_channel
, '.')))
)) {
3351 *p = '\0';
3352 }
3353 }
3354
3355 if ((!globals.enable_fs_events && (!strcasecmp(event_channel, "FSevent") || (main_event_channel && !strcasecmp(main_event_channel, "FSevent")))) ||
3356 !(switch_event_get_header(jsock->allowed_event_channels, event_channel)switch_event_get_header_idx(jsock->allowed_event_channels,
event_channel, -1)
||
3357 (main_event_channel && switch_event_get_header(jsock->allowed_event_channels, main_event_channel)switch_event_get_header_idx(jsock->allowed_event_channels,
main_event_channel, -1)
))) {
3358 ok = SWITCH_FALSE;
3359 }
3360 }
3361
3362 switch_safe_free(main_event_channel)if (main_event_channel) {free(main_event_channel);main_event_channel
=((void*)0);}
;
3363 return ok;
3364
3365}
3366
3367static switch_bool_t parse_subs(jsock_t *jsock, const char *event_channel, cJSON **sub_list, cJSON **err_list, cJSON **exist_list)
3368{
3369 switch_bool_t r = SWITCH_FALSE;
3370
3371 if (event_channel_check_auth(jsock, event_channel)) {
3372 if (!*sub_list) {
3373 *sub_list = cJSON_CreateArray();
3374 }
3375
3376 if (jsock_sub_channel(jsock, event_channel) == SWITCH_STATUS_SUCCESS) {
3377 cJSON_AddItemToArray(*sub_list, cJSON_CreateString(event_channel));
3378 } else {
3379 if (!*exist_list) {
3380 *exist_list = cJSON_CreateArray();
3381 }
3382 cJSON_AddItemToArray(*exist_list, cJSON_CreateString(event_channel));
3383 }
3384
3385 r = SWITCH_TRUE;
3386 } else {
3387 if (!*err_list) {
3388 *err_list = cJSON_CreateArray();
3389 }
3390 cJSON_AddItemToArray(*err_list, cJSON_CreateString(event_channel));
3391 }
3392
3393 return r;
3394}
3395
3396static switch_bool_t verto__subscribe_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
3397{
3398 switch_bool_t r = SWITCH_TRUE;
3399 cJSON *subs = NULL((void*)0), *errs = NULL((void*)0), *exist = NULL((void*)0);
3400
3401 *response = cJSON_CreateObject();
3402
3403 if (params) {
3404 cJSON *jchannel = cJSON_GetObjectItem(params, "eventChannel");
3405
3406 if (jchannel) {
3407 if (jchannel->type == cJSON_String4) {
3408 parse_subs(jsock, jchannel->valuestring, &subs, &errs, &exist);
3409 } else if (jchannel->type == cJSON_Array5) {
3410 int i, len = cJSON_GetArraySize(jchannel);
3411
3412 for(i = 0; i < len; i++) {
3413 cJSON *str = cJSON_GetArrayItem(jchannel, i);
3414 if (str->type == cJSON_String4) {
3415 parse_subs(jsock, str->valuestring, &subs, &errs, &exist);
3416 }
3417 }
3418 }
3419 }
3420 }
3421
3422 if (subs) {
3423 cJSON_AddItemToObject(*response, "subscribedChannels", subs);
3424 }
3425
3426 if (errs) {
3427 cJSON_AddItemToObject(*response, "unauthorizedChannels", errs);
3428 }
3429
3430 if (exist) {
3431 cJSON_AddItemToObject(*response, "alreadySubscribedChannels", exist);
3432 }
3433
3434 if (!subs) {
3435 r = SWITCH_FALSE;
3436 }
3437
3438 return r;
3439}
3440
3441static void do_unsub(jsock_t *jsock, const char *event_channel, cJSON **subs, cJSON **errs)
3442{
3443 if (jsock_unsub_channel(jsock, event_channel)) {
3444 if (!*subs) {
3445 *subs = cJSON_CreateArray();
3446 }
3447 cJSON_AddItemToArray(*subs, cJSON_CreateString(event_channel));
3448 } else {
3449 if (!*errs) {
3450 *errs = cJSON_CreateArray();
3451 }
3452 cJSON_AddItemToArray(*errs, cJSON_CreateString(event_channel));
3453 }
3454}
3455
3456static switch_bool_t verto__unsubscribe_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
3457{
3458 switch_bool_t r = SWITCH_TRUE;
3459 cJSON *subs = NULL((void*)0), *errs = NULL((void*)0);
3460
3461 *response = cJSON_CreateObject();
3462
3463 if (params) {
3464 cJSON *jchannel = cJSON_GetObjectItem(params, "eventChannel");
3465
3466 if (jchannel) {
3467 if (jchannel->type == cJSON_String4) {
3468 do_unsub(jsock, jchannel->valuestring, &subs, &errs);
3469 } else if (jchannel->type == cJSON_Array5) {
3470 int i, len = cJSON_GetArraySize(jchannel);
3471
3472 for(i = 0; i < len; i++) {
3473 cJSON *str = cJSON_GetArrayItem(jchannel, i);
3474 if (str->type == cJSON_String4) {
3475 do_unsub(jsock, str->valuestring, &subs, &errs);
3476 }
3477 }
3478 }
3479 }
3480 }
3481
3482 if (subs) {
3483 cJSON_AddItemToObject(*response, "unsubscribedChannels", subs);
3484 }
3485
3486 if (errs) {
3487 cJSON_AddItemToObject(*response, "notSubscribedChannels", errs);
3488 }
3489
3490 if (errs && !subs) {
3491 r = SWITCH_FALSE;
3492 }
3493
3494 return r;
3495}
3496
3497static switch_bool_t verto__broadcast_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
3498{
3499 char *json_text = NULL((void*)0);
3500 switch_bool_t r = SWITCH_FALSE;
3501 const char *event_channel = cJSON_GetObjectCstr(params, "eventChannel");
3502 cJSON *jevent;
3503
3504 *response = cJSON_CreateObject();
3505
3506
3507 if (!event_channel) {
3508 cJSON_AddItemToObject(*response, "message", cJSON_CreateString("eventChannel not specified."));
3509 cJSON_AddItemToObject(*response, "code", cJSON_CreateNumber(CODE_SESSION_ERROR-32002));
3510 goto end;
3511 }
3512
3513 if (!event_channel_check_auth(jsock, event_channel)) {
3514 cJSON_AddItemToObject(*response, "message", cJSON_CreateString("Permission Denied."));
3515 cJSON_AddItemToObject(*response, "code", cJSON_CreateNumber(CODE_SESSION_ERROR-32002));
3516 goto end;
3517 }
3518
3519
3520 cJSON_AddItemToObject(params, "userid", cJSON_CreateString(jsock->uid));
3521
3522 jevent = cJSON_Duplicate(params, 1);
3523 switch_event_channel_broadcast(event_channel, &jevent, modname, globals.event_channel_id);
3524
3525 if (jsock->profile->mcast_pub.sock > -1) {
3526 if ((json_text = cJSON_PrintUnformatted(params))) {
3527
3528 if ( mcast_socket_send(&jsock->profile->mcast_pub, json_text, strlen(json_text) + 1) < 0 ) {
3529 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
3529, ((void*)0)
, SWITCH_LOG_ERROR, "multicast socket send error!\n");
3530 }
3531
3532 free(json_text);
3533 json_text = NULL((void*)0);
3534 r = SWITCH_TRUE;
3535 cJSON_AddItemToObject(*response, "message", cJSON_CreateString("MCAST Data Sent"));
3536 } else {
3537 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
3537, ((void*)0)
, SWITCH_LOG_ERROR, "JSON ERROR!\n");
3538 }
3539 }
3540
3541 end:
3542
3543 return r;
3544}
3545
3546static switch_bool_t login_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
3547{
3548 *response = cJSON_CreateObject();
3549 cJSON_AddItemToObject(*response, "message", cJSON_CreateString("logged in"));
3550
3551 login_fire_custom_event(jsock, params, 1, "Logged in");
3552
3553 return SWITCH_TRUE;
3554}
3555
3556static switch_bool_t echo_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
3557{
3558 *response = cJSON_Duplicate(params, 1);
3559 return SWITCH_TRUE;
3560}
3561
3562static switch_bool_t jsapi_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
3563{
3564 if (jsock->allowed_jsapi) {
3565 const char *function;
3566
3567 if (params) {
3568 if ((function = cJSON_GetObjectCstr(params, "command"))) {
3569 if (!switch_event_get_header(jsock->allowed_jsapi, function)switch_event_get_header_idx(jsock->allowed_jsapi, function
, -1)
) {
3570 return SWITCH_FALSE;
3571 }
3572
3573 if (jsock->allowed_fsapi && !strcmp(function, "fsapi")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(function) && __builtin_constant_p ("fsapi") &&
(__s1_len = __builtin_strlen (function), __s2_len = __builtin_strlen
("fsapi"), (!((size_t)(const void *)((function) + 1) - (size_t
)(const void *)(function) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)(("fsapi") + 1) - (size_t)(const void
*)("fsapi") == 1) || __s2_len >= 4)) ? __builtin_strcmp (
function, "fsapi") : (__builtin_constant_p (function) &&
((size_t)(const void *)((function) + 1) - (size_t)(const void
*)(function) == 1) && (__s1_len = __builtin_strlen (
function), __s1_len < 4) ? (__builtin_constant_p ("fsapi")
&& ((size_t)(const void *)(("fsapi") + 1) - (size_t)
(const void *)("fsapi") == 1) ? __builtin_strcmp (function, "fsapi"
) : (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) ("fsapi"); int __result = (((const unsigned
char *) (const char *) (function))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (function))[1] - __s2[1]); if (__s1_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (function))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (function))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p ("fsapi") && ((size_t)
(const void *)(("fsapi") + 1) - (size_t)(const void *)("fsapi"
) == 1) && (__s2_len = __builtin_strlen ("fsapi"), __s2_len
< 4) ? (__builtin_constant_p (function) && ((size_t
)(const void *)((function) + 1) - (size_t)(const void *)(function
) == 1) ? __builtin_strcmp (function, "fsapi") : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (function); int __result = (((const unsigned char *)
(const char *) ("fsapi"))[0] - __s2[0]); if (__s2_len > 0
&& __result == 0) { __result = (((const unsigned char
*) (const char *) ("fsapi"))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) ("fsapi"))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) ("fsapi"))[3] - __s2[3]); } } __result; })
))) : __builtin_strcmp (function, "fsapi")))); })
) {
3574 cJSON *cmd = cJSON_GetObjectItem(params, "cmd");
3575 cJSON *arg = cJSON_GetObjectItem(params, "arg");
3576
3577 if (cmd->type == cJSON_String4 && cmd->valuestring && !auth_api_command(jsock, cmd->valuestring, arg ? arg->valuestring : NULL((void*)0))) {
3578 return SWITCH_FALSE;
3579 }
3580 }
3581 }
3582 }
3583 }
3584
3585 switch_json_api_execute(params, NULL((void*)0), response);
3586
3587 return *response ? SWITCH_TRUE : SWITCH_FALSE;
3588}
3589
3590static switch_bool_t fsapi_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
3591{
3592 cJSON *cmd, *arg, *reply;
3593 switch_stream_handle_t stream = { 0 };
3594 switch_status_t status = SWITCH_STATUS_SUCCESS;
3595
3596 cmd = cJSON_GetObjectItem(params, "cmd");
3597 arg = cJSON_GetObjectItem(params, "arg");
3598
3599
3600 if (jsock->allowed_fsapi) {
3601 if (cmd->type == cJSON_String4 && cmd->valuestring && !auth_api_command(jsock, cmd->valuestring, arg ? arg->valuestring : NULL((void*)0))) {
3602 return SWITCH_FALSE;
3603 }
3604 }
3605
3606 if (cmd && !cmd->valuestring) {
3607 cmd = NULL((void*)0);
3608 }
3609
3610 if (arg && !arg->valuestring) {
3611 arg = NULL((void*)0);
3612 }
3613
3614 reply = cJSON_CreateObject();
3615
3616 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "mod_verto.c", 3616, __PRETTY_FUNCTION__)); memset(stream.data
, 0, 1024); stream.end = stream.data; stream.data_size = 1024
; stream.write_function = switch_console_stream_write; stream
.raw_write_function = switch_console_stream_raw_write; stream
.alloc_len = 1024; stream.alloc_chunk = 1024
;
3617
3618 if (cmd && (status = switch_api_execute(cmd->valuestring, arg ? arg->valuestring : NULL((void*)0), NULL((void*)0), &stream)) == SWITCH_STATUS_SUCCESS) {
3619 cJSON_AddItemToObject(reply, "message", cJSON_CreateString((char *) stream.data));
3620 } else {
3621 cJSON_AddItemToObject(reply, "message", cJSON_CreateString("INVALID CALL"));
3622 }
3623
3624 switch_safe_free(stream.data)if (stream.data) {free(stream.data);stream.data=((void*)0);};
3625
3626 if (reply) {
3627 *response = reply;
3628 return SWITCH_TRUE;
3629 }
3630
3631 return SWITCH_FALSE;
3632}
3633
3634////
3635
3636static void jrpc_init(void)
3637{
3638 jrpc_add_func("echo", echo_func);
3639 jrpc_add_func("jsapi", jsapi_func);
3640 jrpc_add_func("fsapi", fsapi_func);
3641 jrpc_add_func("login", login_func);
3642
3643 jrpc_add_func("verto.invite", verto__invite_func);
3644 jrpc_add_func("verto.info", verto__info_func);
3645 jrpc_add_func("verto.attach", verto__attach_func);
3646 jrpc_add_func("verto.bye", verto__bye_func);
3647 jrpc_add_func("verto.answer", verto__answer_func);
3648 jrpc_add_func("verto.subscribe", verto__subscribe_func);
3649 jrpc_add_func("verto.unsubscribe", verto__unsubscribe_func);
3650 jrpc_add_func("verto.broadcast", verto__broadcast_func);
3651 jrpc_add_func("verto.modify", verto__modify_func);
3652
3653}
3654
3655
3656
3657
3658static int start_jsock(verto_profile_t *profile, ws_socket_t sock)
3659{
3660 jsock_t *jsock = NULL((void*)0);
3661 int flag = 1;
3662 int i;
3663#ifndef WIN32
3664 unsigned int len;
3665#else
3666 int len;
3667#endif
3668 jsock_type_t ptype = PTYPE_CLIENT;
3669 switch_thread_data_t *td;
3670 switch_memory_pool_t *pool;
3671 switch_event_t *s_event;
3672
3673 switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "mod_verto.c",
(const char *)__func__, 3673)
;
3674
3675
3676 jsock = (jsock_t *) switch_core_alloc(pool, sizeof(*jsock))switch_core_perform_alloc(pool, sizeof(*jsock), "mod_verto.c"
, (const char *)__func__, 3676)
;
3677 jsock->pool = pool;
3678
3679 len = sizeof(jsock->remote_addr);
3680
3681 if ((jsock->client_socket = accept(sock, (struct sockaddr *) &jsock->remote_addr, &len)) < 0) {
3682 die("ACCEPT FAILED\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 3682, ((void*)0), SWITCH_LOG_DEBUG, "ACCEPT FAILED\n"
); goto error
;
3683 }
3684
3685 for (i = 0; i < profile->i; i++) {
3686 if ( profile->server_socket[i] == sock ) {
3687 if (profile->ip[i].secure) {
3688 ptype = PTYPE_CLIENT_SSL;
3689 }
3690 break;
3691 }
3692 }
3693
3694 jsock->local_sock = sock;
3695 jsock->profile = profile;
3696
3697 if (zstr(jsock->name)_zstr(jsock->name)) {
3698 jsock->name = switch_core_sprintf(pool, "%s:%d", inet_ntoa(jsock->remote_addr.sin_addr), ntohs(jsock->remote_addr.sin_port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (jsock->remote_addr.sin_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; }))
);
3699 }
3700
3701 jsock->ptype = ptype;
3702
3703 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
3703, ((void*)0)
, SWITCH_LOG_INFO, "%s Client Connect.\n", jsock->name);
3704 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_CLIENT_CONNECT)switch_event_create_subclass_detailed("mod_verto.c", (const char
* )(const char *)__func__, 3704, &s_event, SWITCH_EVENT_CUSTOM
, "verto::client_connect")
== SWITCH_STATUS_SUCCESS) {
3705 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "verto_profile_name", profile->name);
3706 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "verto_client_address", "%s:%d", inet_ntoa(jsock->remote_addr.sin_addr), ntohs(jsock->remote_addr.sin_port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (jsock->remote_addr.sin_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; }))
);
3707 switch_event_fire(&s_event)switch_event_fire_detailed("mod_verto.c", (const char * )(const
char *)__func__, 3707, &s_event, ((void*)0))
;
3708 }
3709
3710 /* no nagle please */
3711 setsockopt(jsock->client_socket, IPPROTO_TCPIPPROTO_TCP, TCP_NODELAY1, (char *)&flag, sizeof(flag));
3712
3713
3714#if defined(SO_KEEPALIVE9)
3715 setsockopt(jsock->client_socket, SOL_SOCKET1, SO_KEEPALIVE9, (void *)&flag, sizeof(flag));
3716#endif
3717 flag = 30;
3718#if defined(TCP_KEEPIDLE4)
3719 setsockopt(jsock->client_socket, IPPROTO_TCPIPPROTO_TCP, TCP_KEEPIDLE4, (void *)&flag, sizeof(flag));
3720#endif
3721#if defined(TCP_KEEPINTVL5)
3722 setsockopt(jsock->client_socket, IPPROTO_TCPIPPROTO_TCP, TCP_KEEPINTVL5, (void *)&flag, sizeof(flag));
3723#endif
3724
3725 td = switch_core_alloc(jsock->pool, sizeof(*td))switch_core_perform_alloc(jsock->pool, sizeof(*td), "mod_verto.c"
, (const char *)__func__, 3725)
;
3726
3727 td->alloc = 0;
3728 td->func = client_thread;
3729 td->obj = jsock;
3730 td->pool = pool;
3731
3732 switch_mutex_init(&jsock->write_mutex, SWITCH_MUTEX_NESTED0x1, jsock->pool);
3733 switch_mutex_init(&jsock->filter_mutex, SWITCH_MUTEX_NESTED0x1, jsock->pool);
3734 switch_queue_create(&jsock->event_queue, MAX_QUEUE_LEN100000, jsock->pool);
3735 switch_thread_rwlock_create(&jsock->rwlock, jsock->pool);
3736 switch_thread_pool_launch_thread(&td);
3737
3738 return 0;
3739
3740 error:
3741
3742 if (jsock) {
3743 if (jsock->client_socket > -1) {
3744 close_socket(&jsock->client_socket);
3745 }
3746
3747 switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "mod_verto.c"
, (const char *)__func__, 3747)
;
3748 }
3749
3750 return -1;
3751}
3752
3753static ws_socket_t prepare_socket(int ip, uint16_t port)
3754{
3755 ws_socket_t sock = ws_sock_invalid(ws_socket_t)-1;
3756#ifndef WIN32
3757 int reuse_addr = 1;
3758#else
3759 char reuse_addr = 1;
3760#endif
3761 struct sockaddr_in addr;
3762
3763 if ((sock = socket(PF_INET2, SOCK_STREAMSOCK_STREAM, IPPROTO_TCPIPPROTO_TCP)) < 0) {
3764 die("Socket Error!\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 3764, ((void*)0), SWITCH_LOG_DEBUG, "Socket Error!\n"
); goto error
;
3765 }
3766
3767 if ( setsockopt(sock, SOL_SOCKET1, SO_REUSEADDR2, &reuse_addr, sizeof(reuse_addr)) < 0 ) {
3768 die("Socket setsockopt Error!\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 3768, ((void*)0), SWITCH_LOG_DEBUG, "Socket setsockopt Error!\n"
); goto error
;
3769 }
3770
3771 memset(&addr, 0, sizeof(addr));
3772 addr.sin_family = AF_INET2;
3773 addr.sin_addr.s_addr = ip;
3774 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; }))
;
3775
3776 if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3777 die("Bind Error!\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 3777, ((void*)0), SWITCH_LOG_DEBUG, "Bind Error!\n"
); goto error
;
3778 }
3779
3780 if (listen(sock, MAXPENDING10000) < 0) {
3781 die("Listen error\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 3781, ((void*)0), SWITCH_LOG_DEBUG, "Listen error\n"
); goto error
;
3782 }
3783
3784 return sock;
3785
3786 error:
3787
3788 close_file(&sock);
3789
3790 return ws_sock_invalid(ws_socket_t)-1;
3791}
3792
3793static void handle_mcast_sub(verto_profile_t *profile)
3794{
3795 int bytes = mcast_socket_recv(&profile->mcast_sub, NULL((void*)0), 0, 0);
3796
3797 if (bytes > 0) {
3798 cJSON *json;
3799
3800 profile->mcast_sub.buffer[bytes] = '\0';
3801
3802 if ((json = cJSON_Parse((char *)profile->mcast_sub.buffer))) {
3803 jsock_send_event(json);
3804 cJSON_Delete(json);
3805 } else {
3806 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
3806, ((void*)0)
, SWITCH_LOG_ERROR, "MCAST JSON PARSE ERR: %s\n", (char *)profile->mcast_sub.buffer);
3807 }
3808
3809 } else {
3810 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
3810, ((void*)0)
, SWITCH_LOG_ERROR, "MCAST INVALID READ %d\n", bytes);
3811 }
3812
3813}
3814
3815static int profile_one_loop(verto_profile_t *profile)
3816{
3817 switch_waitlist_t pfds[MAX_BIND25+4];
3818 int res, x = 0;
3819 int i = 0;
3820 int max = 2;
3821
3822 memset(&pfds[0], 0, sizeof(pfds[0]) * MAX_BIND25+2);
3823
3824 for (i = 0; i < profile->i; i++) {
3825 pfds[i].sock = profile->server_socket[i];
3826 pfds[i].events = SWITCH_POLL_READ|SWITCH_POLL_ERROR;
3827 }
3828
3829 if (profile->mcast_ip) {
3830 pfds[i].sock = profile->mcast_sub.sock;
3831 pfds[i++].events = SWITCH_POLL_READ|SWITCH_POLL_ERROR;
3832 }
3833
3834 max = i;
3835
3836 if ((res = switch_wait_socklist(pfds, max, 100)) < 0) {
3837 if (errno(*__errno_location ()) != EINTR4) {
3838 die("POLL FAILED\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 3838, ((void*)0), SWITCH_LOG_DEBUG, "POLL FAILED\n"
); goto error
;
3839 }
3840 }
3841
3842 if (res == 0) {
3843 return 0;
3844 }
3845
3846 for (x = 0; x < max; x++) {
3847 if (pfds[x].revents & SWITCH_POLL_ERROR) {
3848 die("POLL ERROR\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 3848, ((void*)0), SWITCH_LOG_DEBUG, "POLL ERROR\n"
); goto error
;
3849 }
3850
3851 if (pfds[x].revents & SWITCH_POLL_HUP) {
3852 die("POLL HUP\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 3852, ((void*)0), SWITCH_LOG_DEBUG, "POLL HUP\n"
); goto error
;
3853 }
3854
3855 if (pfds[x].revents & SWITCH_POLL_READ) {
3856 if (profile->mcast_ip && pfds[x].sock == (switch_os_socket_t)profile->mcast_sub.sock) {
3857 handle_mcast_sub(profile);
3858 } else {
3859 start_jsock(profile, pfds[x].sock);
3860 }
3861 }
3862 }
3863
3864 return res;
3865
3866 error:
3867 return -1;
3868}
3869
3870
3871static int runtime(verto_profile_t *profile)
3872{
3873 int i;
3874
3875 for (i = 0; i < profile->i; i++) {
3876 if ((profile->server_socket[i] = prepare_socket(profile->ip[i].local_ip_addr, profile->ip[i].local_port)) < 0) {
3877 die("Client Socket Error!\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 3877, ((void*)0), SWITCH_LOG_DEBUG, "Client Socket Error!\n"
); goto error
;
3878 }
3879 }
3880
3881 if (profile->mcast_ip) {
3882 if (mcast_socket_create(profile->mcast_ip, profile->mcast_port, &profile->mcast_sub, MCAST_RECV | MCAST_TTL_HOST) < 0) {
3883 die("mcast recv socket create")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 3883, ((void*)0), SWITCH_LOG_DEBUG, "mcast recv socket create"
); goto error
;
3884 }
3885
3886 if (mcast_socket_create(profile->mcast_ip, profile->mcast_port + 1, &profile->mcast_pub, MCAST_SEND | MCAST_TTL_HOST) > 0) {
3887 mcast_socket_close(&profile->mcast_sub);
3888 die("mcast send socket create")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const
char *)__func__, 3888, ((void*)0), SWITCH_LOG_DEBUG, "mcast send socket create"
); goto error
;
3889 }
3890
3891 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
3891, ((void*)0)
, SWITCH_LOG_INFO, "MCAST Bound to %s:%d/%d\n", profile->mcast_ip, profile->mcast_port, profile->mcast_port + 1);
3892 }
3893
3894
3895 while(profile->running) {
3896 if (profile_one_loop(profile) < 0) {
3897 goto error;
3898 }
3899 }
3900
3901 if (profile->mcast_sub.sock > -1) {
3902 mcast_socket_close(&profile->mcast_sub);
3903 }
3904
3905 if (profile->mcast_pub.sock > -1) {
3906 mcast_socket_close(&profile->mcast_pub);
3907 }
3908
3909 return 0;
3910
3911 error:
3912
3913 return -1;
3914
3915}
3916
3917static void kill_profile(verto_profile_t *profile)
3918{
3919 jsock_t *p;
3920 verto_vhost_t *h;
3921 int i;
3922
3923 profile->running = 0;
3924
3925 //if (switch_thread_rwlock_tryrdlock(profile->rwlock) != SWITCH_STATUS_SUCCESS) {
3926 // return;
3927 //}
3928
3929 switch_mutex_lock(profile->mutex);
3930 for (i = 0; i < profile->i; i++) {
3931 close_socket(&profile->server_socket[i]);
3932 }
3933
3934 for(p = profile->jsock_head; p; p = p->next) {
3935 close_socket(&p->client_socket);
3936 }
3937
3938 h = profile->vhosts;
3939 while(h) {
3940 if (h->rewrites) {
3941 switch_event_destroy(&h->rewrites);
3942 }
3943
3944 h = h->next;
3945 }
3946
3947 switch_mutex_unlock(profile->mutex);
3948
3949
3950
3951 //switch_thread_rwlock_unlock(profile->rwlock);
3952}
3953
3954static void kill_profiles(void)
3955{
3956 verto_profile_t *pp;
3957 int sanity = 50;
3958
3959 switch_mutex_lock(globals.mutex);
3960 for(pp = globals.profile_head; pp; pp = pp->next) {
3961 kill_profile(pp);
3962 }
3963 switch_mutex_unlock(globals.mutex);
3964
3965
3966 while(--sanity > 0 && globals.profile_threads > 0) {
3967 switch_yield(100000)switch_sleep(100000);;
3968 }
3969}
3970
3971
3972static void do_shutdown(void)
3973{
3974 globals.running = 0;
3975
3976 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
3976, ((void*)0)
, SWITCH_LOG_INFO, "Shutting down (SIG %d)\n", globals.sig);
3977
3978 kill_profiles();
3979
3980 unsub_all_jsock();
3981
3982 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
3982, ((void*)0)
, SWITCH_LOG_INFO, "Done\n");
3983}
3984
3985static void parse_ip(char *host, uint16_t *port, in_addr_t *addr, char *input)
3986{
3987 char *p;
3988 struct hostent *hent;
3989
3990 strncpy(host, input, 255)__builtin_strncpy (host, input, 255);
3991
3992 host[255] = 0;
3993
3994 if ((p = strchr(host, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(host) && (':') == '\0' ? (char *) __rawmemchr (host
, ':') : __builtin_strchr (host, ':')))
) != NULL((void*)0)) {
3995 *p++ = '\0';
3996 *port = (uint16_t)atoi(p);
3997 }
3998
3999 if ( host[0] < '0' || host[0] > '9' ) {
4000 // Non-numeric host (at least it doesn't start with one). Convert it to ip addr first
4001 if ((hent = gethostbyname(host)) != NULL((void*)0)) {
4002 if (hent->h_addrtype == AF_INET2) {
4003 memcpy(addr, hent->h_addr_list[0], 4);
4004 }
4005 }
4006
4007 } else {
4008 *addr = inet_addr(host);
4009 }
4010}
4011
4012static verto_profile_t *find_profile(const char *name)
4013{
4014 verto_profile_t *p, *r = NULL((void*)0);
4015 switch_mutex_lock(globals.mutex);
4016 for(p = globals.profile_head; p; p = p->next) {
4017 if (!strcmp(name, p->name)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(name) && __builtin_constant_p (p->name) &&
(__s1_len = __builtin_strlen (name), __s2_len = __builtin_strlen
(p->name), (!((size_t)(const void *)((name) + 1) - (size_t
)(const void *)(name) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)((p->name) + 1) - (size_t)(const void
*)(p->name) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(name, p->name) : (__builtin_constant_p (name) &&
((size_t)(const void *)((name) + 1) - (size_t)(const void *)
(name) == 1) && (__s1_len = __builtin_strlen (name), __s1_len
< 4) ? (__builtin_constant_p (p->name) && ((size_t
)(const void *)((p->name) + 1) - (size_t)(const void *)(p->
name) == 1) ? __builtin_strcmp (name, p->name) : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (p->name); int __result = (((const unsigned char *
) (const char *) (name))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (name))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (name))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (name))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(p->name) && ((size_t)(const void *)((p->name)
+ 1) - (size_t)(const void *)(p->name) == 1) && (
__s2_len = __builtin_strlen (p->name), __s2_len < 4) ? (
__builtin_constant_p (name) && ((size_t)(const void *
)((name) + 1) - (size_t)(const void *)(name) == 1) ? __builtin_strcmp
(name, p->name) : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (name); int __result
= (((const unsigned char *) (const char *) (p->name))[0] -
__s2[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (p->name))[1] -
__s2[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (p->name))[2] -
__s2[2]); if (__s2_len > 2 && __result == 0) __result
= (((const unsigned char *) (const char *) (p->name))[3] -
__s2[3]); } } __result; })))) : __builtin_strcmp (name, p->
name)))); })
) {
4018 r = p;
4019 break;
4020 }
4021 }
4022
4023 if (r && (!r->in_thread || !r->running)) {
4024 r = NULL((void*)0);
4025 }
4026
4027 if (r && switch_thread_rwlock_tryrdlock(r->rwlock) != SWITCH_STATUS_SUCCESS) {
4028 r = NULL((void*)0);
4029 }
4030 switch_mutex_unlock(globals.mutex);
4031
4032 return r;
4033}
4034
4035static switch_bool_t profile_exists(const char *name)
4036{
4037 switch_bool_t r = SWITCH_FALSE;
4038 verto_profile_t *p;
4039
4040 switch_mutex_lock(globals.mutex);
4041 for(p = globals.profile_head; p; p = p->next) {
4042 if (!strcmp(p->name, name)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(p->name) && __builtin_constant_p (name) &&
(__s1_len = __builtin_strlen (p->name), __s2_len = __builtin_strlen
(name), (!((size_t)(const void *)((p->name) + 1) - (size_t
)(const void *)(p->name) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((name) + 1) - (size_t)(const void *
)(name) == 1) || __s2_len >= 4)) ? __builtin_strcmp (p->
name, name) : (__builtin_constant_p (p->name) && (
(size_t)(const void *)((p->name) + 1) - (size_t)(const void
*)(p->name) == 1) && (__s1_len = __builtin_strlen
(p->name), __s1_len < 4) ? (__builtin_constant_p (name
) && ((size_t)(const void *)((name) + 1) - (size_t)(const
void *)(name) == 1) ? __builtin_strcmp (p->name, name) : (
__extension__ ({ const unsigned char *__s2 = (const unsigned char
*) (const char *) (name); int __result = (((const unsigned char
*) (const char *) (p->name))[0] - __s2[0]); if (__s1_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) (p->name))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (p->name))[2] - __s2[2]); if (__s1_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (p->name))[3] - __s2[3]); } } __result;
}))) : (__builtin_constant_p (name) && ((size_t)(const
void *)((name) + 1) - (size_t)(const void *)(name) == 1) &&
(__s2_len = __builtin_strlen (name), __s2_len < 4) ? (__builtin_constant_p
(p->name) && ((size_t)(const void *)((p->name)
+ 1) - (size_t)(const void *)(p->name) == 1) ? __builtin_strcmp
(p->name, name) : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (p->name);
int __result = (((const unsigned char *) (const char *) (name
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (name
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (name
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (name))
[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (p->
name, name)))); })
) {
4043 r = SWITCH_TRUE;
4044 break;
4045 }
4046 }
4047 switch_mutex_unlock(globals.mutex);
4048
4049 return r;
4050}
4051
4052static void del_profile(verto_profile_t *profile)
4053{
4054 verto_profile_t *p, *last = NULL((void*)0);
4055
4056 switch_mutex_lock(globals.mutex);
4057 for(p = globals.profile_head; p; p = p->next) {
4058 if (p == profile) {
4059 if (last) {
4060 last->next = p->next;
4061 } else {
4062 globals.profile_head = p->next;
4063 }
4064 globals.profile_count--;
4065 break;
4066 }
4067
4068 last = p;
4069 }
4070 switch_mutex_unlock(globals.mutex);
4071}
4072
4073static switch_status_t add_profile(verto_profile_t *profile)
4074{
4075 switch_status_t status = SWITCH_STATUS_FALSE;
4076
4077 switch_mutex_lock(globals.mutex);
4078
4079 if (!profile_exists(profile->name)) {
4080 status = SWITCH_STATUS_SUCCESS;
4081 }
4082
4083 if (status == SWITCH_STATUS_SUCCESS) {
4084 profile->next = globals.profile_head;
4085 globals.profile_head = profile;
4086 globals.profile_count++;
4087 }
4088
4089 switch_mutex_unlock(globals.mutex);
4090
4091 return status;
4092}
4093
4094static switch_status_t parse_config(const char *cf)
4095{
4096
4097 switch_xml_t cfg, xml, settings, param, xprofile, xprofiles;
4098 switch_xml_t xvhosts, xvhost, rewrites, rule;
4099 switch_status_t status = SWITCH_STATUS_SUCCESS;
4100
4101 if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL((void*)0)))) {
4102 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4102, ((void*)0)
, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
4103 return SWITCH_STATUS_TERM;
4104 }
4105
4106 if ((xprofiles = switch_xml_child(cfg, "profiles"))) {
4107 for (xprofile = switch_xml_child(xprofiles, "profile"); xprofile; xprofile = xprofile->next) {
4108 verto_profile_t *profile;
4109 switch_memory_pool_t *pool;
4110 const char *name = switch_xml_attr(xprofile, "name");
4111
4112 if (zstr(name)_zstr(name)) {
4113 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4113, ((void*)0)
, SWITCH_LOG_ERROR, "Required field name missing\n");
4114 continue;
4115 }
4116
4117 if (profile_exists(name)) {
4118 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4118, ((void*)0)
, SWITCH_LOG_ERROR, "Profile %s already exists\n", name);
4119 continue;
4120 }
4121
4122
4123 switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "mod_verto.c",
(const char *)__func__, 4123)
;
4124 profile = switch_core_alloc(pool, sizeof(*profile))switch_core_perform_alloc(pool, sizeof(*profile), "mod_verto.c"
, (const char *)__func__, 4124)
;
4125 profile->pool = pool;
4126 profile->name = switch_core_strdup(profile->pool, name)switch_core_perform_strdup(profile->pool, name, "mod_verto.c"
, (const char *)__func__, 4126)
;
4127 switch_mutex_init(&profile->mutex, SWITCH_MUTEX_NESTED0x1, profile->pool);
4128 switch_thread_rwlock_create(&profile->rwlock, profile->pool);
4129 add_profile(profile);
4130
4131 profile->local_network = "localnet.auto";
4132
4133 for (param = switch_xml_child(xprofile, "param"); param; param = param->next) {
4134 char *var = NULL((void*)0);
4135 char *val = NULL((void*)0);
4136 int i = 0;
4137
4138 var = (char *) switch_xml_attr_soft(param, "name");
4139 val = (char *) switch_xml_attr_soft(param, "value");
4140
4141 if (!strcasecmp(var, "bind-local")) {
4142 const char *secure = switch_xml_attr_soft(param, "secure");
4143 if (i < MAX_BIND25) {
4144 parse_ip(profile->ip[profile->i].local_ip, &profile->ip[profile->i].local_port, &profile->ip[profile->i].local_ip_addr, val);
4145 if (switch_true(secure)) {
4146 profile->ip[profile->i].secure = 1;
4147 }
4148 profile->i++;
4149 } else {
4150 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4150, ((void*)0)
, SWITCH_LOG_ERROR, "Max Bindings Reached!\n");
4151 }
4152 } else if (!strcasecmp(var, "secure-combined")) {
4153 set_string(profile->cert, val)__builtin_strncpy (profile->cert, val, sizeof(profile->
cert)-1)
;
4154 set_string(profile->key, val)__builtin_strncpy (profile->key, val, sizeof(profile->key
)-1)
;
4155 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4155, ((void*)0)
, SWITCH_LOG_INFO, "Secure key and cert specified\n");
4156 } else if (!strcasecmp(var, "secure-cert")) {
4157 set_string(profile->cert, val)__builtin_strncpy (profile->cert, val, sizeof(profile->
cert)-1)
;
4158 } else if (!strcasecmp(var, "secure-key")) {
4159 set_string(profile->key, val)__builtin_strncpy (profile->key, val, sizeof(profile->key
)-1)
;
4160 } else if (!strcasecmp(var, "secure-chain")) {
4161 set_string(profile->chain, val)__builtin_strncpy (profile->chain, val, sizeof(profile->
chain)-1)
;
4162 } else if (!strcasecmp(var, "inbound-codec-string") && !zstr(val)_zstr(val)) {
4163 profile->inbound_codec_string = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_verto.c"
, (const char *)__func__, 4163)
;
4164 } else if (!strcasecmp(var, "outbound-codec-string") && !zstr(val)_zstr(val)) {
4165 profile->outbound_codec_string = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_verto.c"
, (const char *)__func__, 4165)
;
4166 } else if (!strcasecmp(var, "blind-reg") && !zstr(val)_zstr(val)) {
4167 profile->blind_reg = switch_true(val);
4168 } else if (!strcasecmp(var, "userauth") && !zstr(val)_zstr(val)) {
4169 profile->userauth = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_verto.c"
, (const char *)__func__, 4169)
;
4170 } else if (!strcasecmp(var, "root-password") && !zstr(val)_zstr(val)) {
4171 profile->root_passwd = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_verto.c"
, (const char *)__func__, 4171)
;
4172 } else if (!strcasecmp(var, "context") && !zstr(val)_zstr(val)) {
4173 profile->context = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_verto.c"
, (const char *)__func__, 4173)
;
4174 } else if (!strcasecmp(var, "dialplan") && !zstr(val)_zstr(val)) {
4175 profile->dialplan = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_verto.c"
, (const char *)__func__, 4175)
;
4176 } else if (!strcasecmp(var, "mcast-ip") && val) {
4177 profile->mcast_ip = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_verto.c"
, (const char *)__func__, 4177)
;
4178 } else if (!strcasecmp(var, "mcast-port") && val) {
4179 profile->mcast_port = (switch_port_t) atoi(val);
4180 } else if (!strcasecmp(var, "timer-name") && !zstr(var)_zstr(var)) {
4181 profile->timer_name = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_verto.c"
, (const char *)__func__, 4181)
;
4182 } else if (!strcasecmp(var, "local-network") && !zstr(val)_zstr(val)) {
4183 profile->local_network = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_verto.c"
, (const char *)__func__, 4183)
;
4184 } else if (!strcasecmp(var, "apply-candidate-acl")) {
4185 if (profile->cand_acl_count < SWITCH_MAX_CAND_ACL25) {
4186 profile->cand_acl[profile->cand_acl_count++] = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_verto.c"
, (const char *)__func__, 4186)
;
4187 } else {
4188 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4188, ((void*)0)
, SWITCH_LOG_ERROR, "Max acl records of %d reached\n", SWITCH_MAX_CAND_ACL25);
4189 }
4190 } else if (!strcasecmp(var, "rtp-ip")) {
4191 if (zstr(val)_zstr(val)) {
4192 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4192, ((void*)0)
, SWITCH_LOG_WARNING, "Invalid RTP IP.\n");
4193 } else {
4194 if (profile->rtpip_index < MAX_RTPIP25 -1) {
4195 profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_verto.c"
, (const char *)__func__, 4195)
;
4196 } else {
4197 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4197, ((void*)0)
, SWITCH_LOG_WARNING, "Too many RTP IP.\n");
4198 }
4199 }
4200 } else if (!strcasecmp(var, "ext-rtp-ip")) {
4201 if (zstr(val)_zstr(val)) {
4202 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4202, ((void*)0)
, SWITCH_LOG_WARNING, "Invalid External RTP IP.\n");
4203 } else {
4204 profile->extrtpip = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_verto.c"
, (const char *)__func__, 4204)
;
4205 }
4206 } else if (!strcasecmp(var, "debug")) {
4207 if (val) {
4208 profile->debug = atoi(val);
4209 }
4210 }
4211 }
4212
4213 if (zstr(profile->outbound_codec_string)_zstr(profile->outbound_codec_string)) {
4214 profile->outbound_codec_string = "opus,vp8";
4215 }
4216
4217 if (zstr(profile->inbound_codec_string)_zstr(profile->inbound_codec_string)) {
4218 profile->inbound_codec_string = profile->outbound_codec_string;
4219 }
4220
4221 if (zstr(profile->timer_name)_zstr(profile->timer_name)) {
4222 profile->timer_name = "soft";
4223 }
4224
4225 if (zstr(profile->dialplan)_zstr(profile->dialplan)) {
4226 profile->dialplan = "XML";
4227 }
4228
4229 if (zstr(profile->context)_zstr(profile->context)) {
4230 profile->context = "default";
4231 }
4232
4233 if (zstr(profile->ip[0].local_ip)_zstr(profile->ip[0].local_ip) ) switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4233, ((void*)0)
, SWITCH_LOG_ERROR, "%s: local_ip bad\n", profile->name);
4234 if (profile->ip[0].local_port <= 0 ) switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4234, ((void*)0)
, SWITCH_LOG_ERROR, "%s: local_port bad\n", profile->name);
4235
4236 if (zstr(profile->ip[0].local_ip)_zstr(profile->ip[0].local_ip) || profile->ip[0].local_port <= 0) {
4237 del_profile(profile);
4238 switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "mod_verto.c"
, (const char *)__func__, 4238)
;
4239 } else {
4240 int i;
4241
4242 for (i = 0; i < profile->i; i++) {
4243 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4243, ((void*)0)
, SWITCH_LOG_INFO, "%s Bound to %s:%d\n",
4244 profile->name, profile->ip[i].local_ip, profile->ip[i].local_port);
4245 }
4246 }
4247
4248 /* parse vhosts */
4249 /* WARNNING: Experimental feature, DO NOT use until we remove this warnning!! */
4250 if ((xvhosts = switch_xml_child(xprofile, "vhosts"))) {
4251 verto_vhost_t *vhost_tail = NULL((void*)0);
4252
4253 for (xvhost = switch_xml_child(xvhosts, "vhost"); xvhost; xvhost = xvhost->next) {
4254 verto_vhost_t *vhost;
4255 const char *domain = switch_xml_attr(xvhost, "domain");
4256
4257 if (zstr(domain)_zstr(domain)) {
4258 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4258, ((void*)0)
, SWITCH_LOG_ERROR, "Required field domain missing\n");
4259 continue;
4260 }
4261
4262 vhost = switch_core_alloc(profile->pool, sizeof(*vhost))switch_core_perform_alloc(profile->pool, sizeof(*vhost), "mod_verto.c"
, (const char *)__func__, 4262)
;
4263 memset(vhost, 0, sizeof(*vhost));
4264 vhost->pool = profile->pool;
4265 vhost->domain = switch_core_strdup(profile->pool, domain)switch_core_perform_strdup(profile->pool, domain, "mod_verto.c"
, (const char *)__func__, 4265)
;
4266
4267 if (!vhost_tail) {
4268 profile->vhosts = vhost;
4269 } else {
4270 vhost_tail->next = vhost;
4271 }
4272
4273 vhost_tail = vhost;
4274
4275 for (param = switch_xml_child(xvhost, "param"); param; param = param->next) {
4276 char *var = NULL((void*)0);
4277 char *val = NULL((void*)0);
4278
4279 var = (char *) switch_xml_attr_soft(param, "name");
4280 val = (char *) switch_xml_attr_soft(param, "value");
4281
4282 if (!strcasecmp(var, "alias")) {
4283 vhost->alias = switch_core_strdup(vhost->pool, val)switch_core_perform_strdup(vhost->pool, val, "mod_verto.c"
, (const char *)__func__, 4283)
;
4284 } else if (!strcasecmp(var, "root")) {
4285 vhost->root = switch_core_strdup(vhost->pool, val)switch_core_perform_strdup(vhost->pool, val, "mod_verto.c"
, (const char *)__func__, 4285)
;
4286 } else if (!strcasecmp(var, "script_root")) {
4287 vhost->script_root = switch_core_strdup(vhost->pool, val)switch_core_perform_strdup(vhost->pool, val, "mod_verto.c"
, (const char *)__func__, 4287)
;
4288 } else if (!strcasecmp(var, "index")) {
4289 vhost->index = switch_core_strdup(vhost->pool, val)switch_core_perform_strdup(vhost->pool, val, "mod_verto.c"
, (const char *)__func__, 4289)
;
4290 } else if (!strcasecmp(var, "auth-realm")) {
4291 vhost->auth_realm = switch_core_strdup(vhost->pool, val)switch_core_perform_strdup(vhost->pool, val, "mod_verto.c"
, (const char *)__func__, 4291)
;
4292 } else if (!strcasecmp(var, "auth-user")) {
4293 vhost->auth_user = switch_core_strdup(vhost->pool, val)switch_core_perform_strdup(vhost->pool, val, "mod_verto.c"
, (const char *)__func__, 4293)
;
4294 } else if (!strcasecmp(var, "auth-pass")) {
4295 vhost->auth_pass = switch_core_strdup(vhost->pool, val)switch_core_perform_strdup(vhost->pool, val, "mod_verto.c"
, (const char *)__func__, 4295)
;
4296 }
4297 }
4298
4299 if (zstr(vhost->root)_zstr(vhost->root)) {
4300 vhost->root = SWITCH_GLOBAL_dirs.htdocs_dir;
4301 }
4302
4303 if (zstr(vhost->script_root)_zstr(vhost->script_root)) {
4304 vhost->script_root = SWITCH_GLOBAL_dirs.script_dir;
4305 }
4306
4307 if (zstr(vhost->index)_zstr(vhost->index)) {
4308 vhost->index = "index.html";
4309 }
4310
4311 if ((rewrites = switch_xml_child(xvhost, "rewrites"))) {
4312 if (switch_event_create(&vhost->rewrites, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("mod_verto.c", (const char
* )(const char *)__func__, 4312, &vhost->rewrites, SWITCH_EVENT_CLONE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
4313 for (rule = switch_xml_child(rewrites, "rule"); rule; rule = rule->next) {
4314 char *expr = NULL((void*)0);
4315 char *val = NULL((void*)0);
4316
4317 expr = (char *) switch_xml_attr_soft(rule, "expression");
4318 val = (char *) switch_xml_attr_soft(rule, "value");
4319
4320 if (zstr(expr)_zstr(expr)) continue;
4321
4322 switch_event_add_header_string(vhost->rewrites, SWITCH_STACK_BOTTOM, expr, val);
4323 }
4324 }
4325 } // rewrites
4326 } // xvhost
4327 } // xvhosts
4328 } // xprofile
4329 } // xprofiles
4330
4331 if ((settings = switch_xml_child(cfg, "settings"))) {
4332 for (param = switch_xml_child(settings, "param"); param; param = param->next) {
4333 char *var = NULL((void*)0);
4334 char *val = NULL((void*)0);
4335
4336 var = (char *) switch_xml_attr_soft(param, "name");
4337 val = (char *) switch_xml_attr_soft(param, "value");
4338
4339
4340 if (!strcasecmp(var, "debug")) {
4341 if (val) {
4342 globals.debug = atoi(val);
4343 }
4344 } else if (!strcasecmp(var, "enable-presence") && val) {
4345 globals.enable_presence = switch_true(val);
4346 } else if (!strcasecmp(var, "enable-fs-events") && val) {
4347 globals.enable_fs_events = switch_true(val);
4348 } else if (!strcasecmp(var, "detach-timeout-sec") && val) {
4349 int tmp = atoi(val);
4350 if (tmp > 0) {
4351 globals.detach_timeout = tmp;
4352 }
4353 }
4354 }
4355 }
4356
4357 switch_xml_free(xml);
4358
4359 return status;
4360}
4361
4362static int init(void)
4363{
4364 verto_profile_t *p;
4365
4366 parse_config("verto.conf");
4367
4368 switch_mutex_lock(globals.mutex);
4369 for(p = globals.profile_head; p; p = p->next) {
4370 verto_init_ssl(p);
4371 }
4372 switch_mutex_unlock(globals.mutex);
4373
4374 globals.running = 1;
4375
4376 return 0;
4377}
4378
4379
4380#if 0
4381static void print_status(verto_profile_t *profile, switch_stream_handle_t *stream)
4382{
4383 jsock_t *p;
4384
4385 stream->write_function(stream, "REMOTE\t\t\tLOCAL\n");
4386
4387 for(p = profile->jsock_head; p; p = p->next) {
4388 if (p->ptype & PTYPE_CLIENT) {
4389 int i;
4390
4391 for (i = 0; i < profile->i; i++) {
4392 if (profile->server_socket[i] == p->local_sock) {
4393 stream->write_function(stream, "%s\t%s:%d\n", p->name, profile->ip[i].local_ip, profile->ip[i].local_port);
4394 }
4395 }
4396 }
4397 }
4398}
4399#endif
4400typedef switch_status_t (*verto_command_t) (char **argv, int argc, switch_stream_handle_t *stream);
4401static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t *stream)
4402{
4403 verto_profile_t *profile = NULL((void*)0);
4404 jsock_t *jsock;
4405 verto_vhost_t *vhost;
4406 int cp = 0;
4407 int cc = 0;
4408 const char *line = "=================================================================================================";
4409 int i;
4410
4411 stream->write_function(stream, "%25s\t%s\t %40s\t%s\n", "Name", " Type", "Data", "State");
4412 stream->write_function(stream, "%s\n", line);
4413
4414 switch_mutex_lock(globals.mutex);
4415 for(profile = globals.profile_head; profile; profile = profile->next) {
4416 for (i = 0; i < profile->i; i++) {
4417 char *tmpurl = switch_mprintf("%s:%s:%d",(profile->ip[i].secure == 1) ? "wss" : "ws", profile->ip[i].local_ip, profile->ip[i].local_port);
4418 stream->write_function(stream, "%25s\t%s\t %40s\t%s\n", profile->name, "profile", tmpurl, (profile->running) ? "RUNNING" : "DOWN");
4419 switch_safe_free(tmpurl)if (tmpurl) {free(tmpurl);tmpurl=((void*)0);};
4420 }
4421 cp++;
4422
4423 switch_mutex_lock(profile->mutex);
4424 for (vhost = profile->vhosts; vhost; vhost = vhost->next) {
4425 char *tmpname = switch_mprintf("%s::%s", profile->name, vhost->domain);
4426 stream->write_function(stream, "%25s\t%s\t %40s\t%s (%s)\n", tmpname, "vhost", vhost->root, vhost->auth_user ? "AUTH" : "NOAUTH", vhost->auth_user ? vhost->auth_user : "");
4427 switch_safe_free(tmpname)if (tmpname) {free(tmpname);tmpname=((void*)0);};
4428 }
4429
4430 for (jsock = profile->jsock_head; jsock; jsock = jsock->next) {
4431 char *tmpname = switch_mprintf("%s::%s@%s", profile->name, jsock->id, jsock->domain);
4432 stream->write_function(stream, "%25s\t%s\t %40s\t%s (%s)\n", tmpname, "client", jsock->name, (!zstr(jsock->uid)_zstr(jsock->uid)) ? "CONN_REG" : "CONN_NO_REG", (jsock->ptype & PTYPE_CLIENT_SSL) ? "WSS": "WS");
4433 cc++;
4434 switch_safe_free(tmpname)if (tmpname) {free(tmpname);tmpname=((void*)0);};
4435 }
4436 switch_mutex_unlock(profile->mutex);
4437 }
4438 switch_mutex_unlock(globals.mutex);
4439
4440 stream->write_function(stream, "%s\n", line);
4441 stream->write_function(stream, "%d profile%s , %d client%s\n", cp, cp == 1 ? "" : "s", cc, cc == 1 ? "" : "s");
4442
4443 return SWITCH_STATUS_SUCCESS;
4444}
4445
4446static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handle_t *stream)
4447{
4448 verto_profile_t *profile = NULL((void*)0);
4449 jsock_t *jsock;
4450 int cp = 0;
4451 int cc = 0;
4452 const char *header = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
4453 int i;
4454
4455 stream->write_function(stream, "%s\n", header);
4456 stream->write_function(stream, "<profiles>\n");
4457 switch_mutex_lock(globals.mutex);
4458 for(profile = globals.profile_head; profile; profile = profile->next) {
4459 for (i = 0; i < profile->i; i++) {
4460 char *tmpurl = switch_mprintf("%s:%s:%d",(profile->ip[i].secure == 1) ? "wss" : "ws", profile->ip[i].local_ip, profile->ip[i].local_port);
4461 stream->write_function(stream, "<profile>\n<name>%s</name>\n<type>%s</type>\n<data>%s</data>\n<state>%s</state>\n</profile>\n", profile->name, "profile", tmpurl, (profile->running) ? "RUNNING" : "DOWN");
4462 switch_safe_free(tmpurl)if (tmpurl) {free(tmpurl);tmpurl=((void*)0);};
4463 }
4464 cp++;
4465
4466 switch_mutex_lock(profile->mutex);
4467 for(jsock = profile->jsock_head; jsock; jsock = jsock->next) {
4468 char *tmpname = switch_mprintf("%s@%s", jsock->id, jsock->domain);
4469 stream->write_function(stream, "<client>\n<profile>%s</profile>\n<name>%s</name>\n<type>%s</type>\n<data>%s</data>\n<state>%s (%s)</state>\n</client>\n", profile->name, tmpname, "client", jsock->name,
4470 (!zstr(jsock->uid)_zstr(jsock->uid)) ? "CONN_REG" : "CONN_NO_REG", (jsock->ptype & PTYPE_CLIENT_SSL) ? "WSS": "WS");
4471 cc++;
4472 switch_safe_free(tmpname)if (tmpname) {free(tmpname);tmpname=((void*)0);};
4473 }
4474 switch_mutex_unlock(profile->mutex);
4475 }
4476 switch_mutex_unlock(globals.mutex);
4477 stream->write_function(stream, "</profiles>\n");
4478 return SWITCH_STATUS_SUCCESS;
4479}
4480
4481SWITCH_STANDARD_API(verto_function)static switch_status_t verto_function ( const char *cmd, switch_core_session_t
*session, switch_stream_handle_t *stream)
4482{
4483 char *argv[1024] = { 0 };
4484 int argc = 0;
4485 char *mycmd = NULL((void*)0);
4486 switch_status_t status = SWITCH_STATUS_SUCCESS;
4487 verto_command_t func = NULL((void*)0);
4488 int lead = 1;
4489 static const char usage_string[] = "USAGE:\n"
4490 "--------------------------------------------------------------------------------\n"
4491 "verto [status|xmlstatus]\n"
4492 "verto help\n"
4493 "--------------------------------------------------------------------------------\n";
4494
4495 if (zstr(cmd)_zstr(cmd)) {
4496 stream->write_function(stream, "%s", usage_string);
4497 goto done;
4498 }
4499
4500 if (!(mycmd = strdup(cmd)(__extension__ (__builtin_constant_p (cmd) && ((size_t
)(const void *)((cmd) + 1) - (size_t)(const void *)(cmd) == 1
) ? (((const char *) (cmd))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (cmd) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, cmd, __len); __retval
; })) : __strdup (cmd)))
)) {
4501 status = SWITCH_STATUS_MEMERR;
4502 goto done;
4503 }
4504
4505 if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) || !argv[0]) {
4506 stream->write_function(stream, "%s", usage_string);
4507 goto done;
4508 }
4509
4510 if (!strcasecmp(argv[0], "help")) {
4511 stream->write_function(stream, "%s", usage_string);
4512 goto done;
4513 } else if (!strcasecmp(argv[0], "status")) {
4514 func = cmd_status;
4515 } else if (!strcasecmp(argv[0], "xmlstatus")) {
4516 func = cmd_xml_status;
4517 }
4518
4519 if (func) {
4520 status = func(&argv[lead], argc - lead, stream);
4521 } else {
4522 stream->write_function(stream, "Unknown Command [%s]\n", argv[0]);
4523 }
4524
4525 done:
4526 switch_safe_free(mycmd)if (mycmd) {free(mycmd);mycmd=((void*)0);};
4527 return status;
4528
4529}
4530
4531
4532
4533static void *SWITCH_THREAD_FUNC profile_thread(switch_thread_t *thread, void *obj)
4534{
4535 verto_profile_t *profile = (verto_profile_t *) obj;
4536 int sanity = 50;
4537
4538 switch_mutex_lock(globals.mutex);
4539 globals.profile_threads++;
4540 switch_mutex_unlock(globals.mutex);
4541
4542 profile->in_thread = 1;
4543 profile->running = 1;
4544
4545
4546 runtime(profile);
4547 profile->running = 0;
4548
4549 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4549, ((void*)0)
, SWITCH_LOG_INFO, "profile %s shutdown, Waiting for %d threads\n", profile->name, profile->jsock_count);
4550
4551 while(--sanity > 0 && profile->jsock_count > 0) {
4552 switch_yield(100000)switch_sleep(100000);;
4553 }
4554
4555 verto_deinit_ssl(profile);
4556
4557 del_profile(profile);
4558
4559 switch_thread_rwlock_wrlock(profile->rwlock);
4560 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4560, ((void*)0)
, SWITCH_LOG_INFO, "%s Thread ending\n", profile->name);
4561 switch_thread_rwlock_unlock(profile->rwlock);
4562 profile->in_thread = 0;
4563
4564 switch_mutex_lock(globals.mutex);
4565 globals.profile_threads--;
4566 switch_mutex_unlock(globals.mutex);
4567
4568 return NULL((void*)0);
4569
4570}
4571
4572static void run_profile_thread(verto_profile_t *profile) {
4573 switch_thread_data_t *td;
4574
4575 td = switch_core_alloc(profile->pool, sizeof(*td))switch_core_perform_alloc(profile->pool, sizeof(*td), "mod_verto.c"
, (const char *)__func__, 4575)
;
4576
4577 td->alloc = 0;
4578 td->func = profile_thread;
4579 td->obj = profile;
4580 td->pool = profile->pool;
4581
4582 switch_thread_pool_launch_thread(&td);
4583}
4584
4585static void run_profiles(void)
4586{
4587 verto_profile_t *p;
4588
4589 switch_mutex_lock(globals.mutex);
4590 for(p = globals.profile_head; p; p = p->next) {
4591 if (!p->in_thread) {
4592 run_profile_thread(p);
4593 }
4594 }
4595 switch_mutex_unlock(globals.mutex);
4596
4597}
4598
4599
4600//// ENDPOINT
4601
4602switch_endpoint_interface_t *verto_endpoint_interface;
4603static switch_call_cause_t verto_outgoing_channel(switch_core_session_t *session,
4604 switch_event_t *var_event,
4605 switch_caller_profile_t *outbound_profile,
4606 switch_core_session_t **new_session,
4607 switch_memory_pool_t **pool,
4608 switch_originate_flag_t flags,
4609 switch_call_cause_t *cancel_cause);
4610switch_io_routines_t verto_io_routines = {
4611 /*.outgoing_channel */ verto_outgoing_channel
4612};
4613
4614static char *verto_get_dial_string(const char *uid, switch_stream_handle_t *rstream)
4615{
4616 jsock_t *jsock;
4617 verto_profile_t *profile;
4618 switch_stream_handle_t *use_stream = NULL((void*)0), stream = { 0 };
4619 char *gen_uid = NULL((void*)0);
4620 int hits = 0;
4621
4622 if (!strchr(uid, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(uid) && ('@') == '\0' ? (char *) __rawmemchr (uid, '@'
) : __builtin_strchr (uid, '@')))
) {
4623 gen_uid = switch_mprintf("%s@%s", uid, switch_core_get_domain(SWITCH_FALSE));
4624 uid = gen_uid;
4625 }
4626
4627 if (rstream) {
4628 use_stream = rstream;
4629 } else {
4630 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "mod_verto.c", 4630, __PRETTY_FUNCTION__)); memset(stream.data
, 0, 1024); stream.end = stream.data; stream.data_size = 1024
; stream.write_function = switch_console_stream_write; stream
.raw_write_function = switch_console_stream_raw_write; stream
.alloc_len = 1024; stream.alloc_chunk = 1024
;
4631 use_stream = &stream;
4632 }
4633
4634 switch_mutex_lock(globals.mutex);
4635 for(profile = globals.profile_head; profile; profile = profile->next) {
4636
4637 switch_mutex_lock(profile->mutex);
4638
4639 for(jsock = profile->jsock_head; jsock; jsock = jsock->next) {
4640 if (jsock->ready && !zstr(jsock->uid)_zstr(jsock->uid) && !zstr(uid)_zstr(uid) && !strcmp(uid, jsock->uid)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(uid) && __builtin_constant_p (jsock->uid) &&
(__s1_len = __builtin_strlen (uid), __s2_len = __builtin_strlen
(jsock->uid), (!((size_t)(const void *)((uid) + 1) - (size_t
)(const void *)(uid) == 1) || __s1_len >= 4) && (!
((size_t)(const void *)((jsock->uid) + 1) - (size_t)(const
void *)(jsock->uid) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(uid, jsock->uid) : (__builtin_constant_p (uid) &&
((size_t)(const void *)((uid) + 1) - (size_t)(const void *)(
uid) == 1) && (__s1_len = __builtin_strlen (uid), __s1_len
< 4) ? (__builtin_constant_p (jsock->uid) && (
(size_t)(const void *)((jsock->uid) + 1) - (size_t)(const void
*)(jsock->uid) == 1) ? __builtin_strcmp (uid, jsock->uid
) : (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (jsock->uid); int __result = (((const
unsigned char *) (const char *) (uid))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (uid))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (uid))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (uid))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(jsock->uid) && ((size_t)(const void *)((jsock->
uid) + 1) - (size_t)(const void *)(jsock->uid) == 1) &&
(__s2_len = __builtin_strlen (jsock->uid), __s2_len < 4
) ? (__builtin_constant_p (uid) && ((size_t)(const void
*)((uid) + 1) - (size_t)(const void *)(uid) == 1) ? __builtin_strcmp
(uid, jsock->uid) : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (uid); int __result
= (((const unsigned char *) (const char *) (jsock->uid))[
0] - __s2[0]); if (__s2_len > 0 && __result == 0) {
__result = (((const unsigned char *) (const char *) (jsock->
uid))[1] - __s2[1]); if (__s2_len > 1 && __result ==
0) { __result = (((const unsigned char *) (const char *) (jsock
->uid))[2] - __s2[2]); if (__s2_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (jsock
->uid))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(uid, jsock->uid)))); })
) {
4641 use_stream->write_function(use_stream, "%s/u:%s,", EP_NAME"verto.rtc", jsock->uuid_str);
4642 hits++;
4643 }
4644 }
4645
4646 switch_mutex_unlock(profile->mutex);
4647 }
4648 switch_mutex_unlock(globals.mutex);
4649
4650 switch_safe_free(gen_uid)if (gen_uid) {free(gen_uid);gen_uid=((void*)0);};
4651
4652 if (!hits) {
4653 use_stream->write_function(use_stream, "error/user_not_registered");
4654 }
4655
4656 if (use_stream->data) {
4657 char *p = use_stream->data;
4658 if (end_of(p)*(*p == '\0' ? p : p + strlen(p) - 1) == ',') {
4659 end_of(p)*(*p == '\0' ? p : p + strlen(p) - 1) = '\0';
4660 }
4661 }
4662
4663 return use_stream->data;
4664}
4665
4666SWITCH_STANDARD_API(verto_contact_function)static switch_status_t verto_contact_function ( const char *cmd
, switch_core_session_t *session, switch_stream_handle_t *stream
)
4667{
4668 char *uid = (char *) cmd;
4669
4670 if (!zstr(uid)_zstr(uid)) {
4671 verto_get_dial_string(uid, stream);
4672 }
4673
4674 return SWITCH_STATUS_SUCCESS;
4675}
4676
4677
4678static switch_call_cause_t verto_outgoing_channel(switch_core_session_t *session,
4679 switch_event_t *var_event,
4680 switch_caller_profile_t *outbound_profile,
4681 switch_core_session_t **new_session,
4682 switch_memory_pool_t **pool,
4683 switch_originate_flag_t flags,
4684 switch_call_cause_t *cancel_cause)
4685{
4686 switch_call_cause_t cause = SWITCH_CAUSE_CHANNEL_UNACCEPTABLE;
4687 char *dest = NULL((void*)0);
4688
4689 if (!zstr(outbound_profile->destination_number)_zstr(outbound_profile->destination_number)) {
4690 dest = strdup(outbound_profile->destination_number)(__extension__ (__builtin_constant_p (outbound_profile->destination_number
) && ((size_t)(const void *)((outbound_profile->destination_number
) + 1) - (size_t)(const void *)(outbound_profile->destination_number
) == 1) ? (((const char *) (outbound_profile->destination_number
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen (outbound_profile->destination_number
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, outbound_profile
->destination_number, __len); __retval; })) : __strdup (outbound_profile
->destination_number)))
;
4691 }
4692
4693 if (zstr(dest)_zstr(dest)) {
4694 goto end;
4695 }
4696
4697 if (!switch_stristr("u:", dest)) {
4698 char *dial_str = verto_get_dial_string(dest, NULL((void*)0));
4699
4700 switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "verto_orig_dest", dest);
4701 if (zstr(switch_event_get_header(var_event, "origination_callee_id_number"))_zstr(switch_event_get_header_idx(var_event, "origination_callee_id_number"
, -1))
) {
4702 char *trimmed_dest = strdup(dest)(__extension__ (__builtin_constant_p (dest) && ((size_t
)(const void *)((dest) + 1) - (size_t)(const void *)(dest) ==
1) ? (((const char *) (dest))[0] == '\0' ? (char *) calloc (
(size_t) 1, (size_t) 1) : ({ size_t __len = strlen (dest) + 1
; char *__retval = (char *) malloc (__len); if (__retval != (
(void*)0)) __retval = (char *) memcpy (__retval, dest, __len)
; __retval; })) : __strdup (dest)))
;
4703 char *p = strchr(trimmed_dest, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(trimmed_dest) && ('@') == '\0' ? (char *) __rawmemchr
(trimmed_dest, '@') : __builtin_strchr (trimmed_dest, '@')))
;
4704 if (p) *p = '\0';
4705 switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_callee_id_number", trimmed_dest);
4706 free(trimmed_dest);
4707 }
4708
4709 cause = SWITCH_CAUSE_USER_NOT_REGISTERED;
4710
4711 if (dial_str) {
4712 switch_originate_flag_t myflags = SOF_NONE;
4713
4714 if ((flags & SOF_NO_LIMITS)) {
4715 myflags |= SOF_NO_LIMITS;
4716 }
4717
4718 if ((flags & SOF_FORKED_DIAL)) {
4719 myflags |= SOF_NOBLOCK;
4720 }
4721
4722 if (switch_ivr_originate(session, new_session, &cause, dial_str, 0, NULL((void*)0),
4723 NULL((void*)0), NULL((void*)0), outbound_profile, var_event, myflags, cancel_cause) == SWITCH_STATUS_SUCCESS) {
4724 switch_core_session_rwunlock(*new_session);
4725 }
4726
4727 free(dial_str);
4728 }
4729
4730 return cause;
4731 } else {
4732 const char *dialed_user = switch_event_get_header(var_event, "dialed_user")switch_event_get_header_idx(var_event, "dialed_user", -1);
4733 const char *dialed_domain = switch_event_get_header(var_event, "dialed_domain")switch_event_get_header_idx(var_event, "dialed_domain", -1);
4734
4735 if (dialed_user) {
4736 if (dialed_domain) {
4737 switch_event_add_header(var_event, SWITCH_STACK_BOTTOM, "verto_orig_dest", "%s@%s", dialed_user, dialed_domain);
4738 } else {
4739 switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "verto_orig_dest", dialed_user);
4740 }
4741 if (zstr(switch_event_get_header(var_event, "origination_callee_id_number"))_zstr(switch_event_get_header_idx(var_event, "origination_callee_id_number"
, -1))
) {
4742 switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_callee_id_number", dialed_user);
4743 outbound_profile->callee_id_number = switch_sanitize_number(switch_core_strdup(outbound_profile->pool, dialed_user)switch_core_perform_strdup(outbound_profile->pool, dialed_user
, "mod_verto.c", (const char *)__func__, 4743)
);
4744 }
4745 }
4746 }
4747
4748 if ((cause = switch_core_session_outgoing_channel(session, var_event, "rtc",
4749 outbound_profile, new_session, NULL((void*)0), SOF_NONE, cancel_cause)) == SWITCH_CAUSE_SUCCESS) {
4750 switch_channel_t *channel = switch_core_session_get_channel(*new_session);
4751 char *jsock_uuid_str = outbound_profile->destination_number + 2;
4752 switch_caller_profile_t *caller_profile;
4753 verto_pvt_t *tech_pvt = NULL((void*)0);
4754 char name[512];
4755
4756 tech_pvt = switch_core_session_alloc(*new_session, sizeof(*tech_pvt))switch_core_perform_session_alloc(*new_session, sizeof(*tech_pvt
), "mod_verto.c", (const char *)__func__, 4756)
;
4757 tech_pvt->session = *new_session;
4758 tech_pvt->channel = channel;
4759 tech_pvt->jsock_uuid = switch_core_session_strdup(*new_session, jsock_uuid_str)switch_core_perform_session_strdup(*new_session, jsock_uuid_str
, "mod_verto.c", (const char *)__func__, 4759)
;
4760 switch_core_session_set_private_class(*new_session, tech_pvt, SWITCH_PVT_SECONDARY);
4761
4762 if (session) {
4763 switch_channel_t *ochannel = switch_core_session_get_channel(session);
4764 const char *ep_codec;
4765
4766 if (switch_true(switch_channel_get_variable(ochannel, SWITCH_BYPASS_MEDIA_VARIABLE)switch_channel_get_variable_dup(ochannel, "bypass_media", SWITCH_TRUE
, -1)
)) {
4767 switch_channel_set_flag(channel, CF_PROXY_MODE)switch_channel_set_flag_value(channel, CF_PROXY_MODE, 1);
4768 switch_channel_set_flag(ochannel, CF_PROXY_MODE)switch_channel_set_flag_value(ochannel, CF_PROXY_MODE, 1);
4769 switch_channel_set_cap(channel, CC_BYPASS_MEDIA)switch_channel_set_cap_value(channel, CC_BYPASS_MEDIA, 1);
4770 }
4771
4772 if ((ep_codec = switch_channel_get_variable(ochannel, "ep_codec_string")switch_channel_get_variable_dup(ochannel, "ep_codec_string", SWITCH_TRUE
, -1)
)) {
4773 switch_channel_set_variable(tech_pvt->channel, "codec_string", ep_codec)switch_channel_set_variable_var_check(tech_pvt->channel, "codec_string"
, ep_codec, SWITCH_TRUE)
;
4774 }
4775 }
4776
4777 tech_pvt->call_id = switch_core_session_strdup(*new_session, switch_core_session_get_uuid(*new_session))switch_core_perform_session_strdup(*new_session, switch_core_session_get_uuid
(*new_session), "mod_verto.c", (const char *)__func__, 4777)
;
4778 if ((tech_pvt->smh = switch_core_session_get_media_handle(*new_session))) {
4779 tech_pvt->mparams = switch_core_media_get_mparams(tech_pvt->smh);
4780 }
4781
4782 switch_snprintf(name, sizeof(name), "verto.rtc/%s", tech_pvt->jsock_uuid);
4783 switch_channel_set_name(channel, name);
4784 switch_channel_set_variable(channel, "jsock_uuid_str", tech_pvt->jsock_uuid)switch_channel_set_variable_var_check(channel, "jsock_uuid_str"
, tech_pvt->jsock_uuid, SWITCH_TRUE)
;
4785 switch_channel_set_variable(channel, "event_channel_cookie", tech_pvt->jsock_uuid)switch_channel_set_variable_var_check(channel, "event_channel_cookie"
, tech_pvt->jsock_uuid, SWITCH_TRUE)
;
4786
4787
4788 if ((caller_profile = switch_caller_profile_dup(switch_core_session_get_pool(*new_session), outbound_profile))) {
4789 switch_channel_set_caller_profile(channel, caller_profile);
4790 }
4791
4792 switch_channel_add_state_handler(channel, &verto_state_handlers);
4793 switch_core_event_hook_add_receive_message(*new_session, messagehook);
4794 switch_channel_set_state(channel, CS_INIT)switch_channel_perform_set_state(channel, "mod_verto.c", (const
char *)__func__, 4794, CS_INIT)
;
4795 track_pvt(tech_pvt);
4796 }
4797
4798 end:
4799
4800 switch_safe_free(dest)if (dest) {free(dest);dest=((void*)0);};
4801
4802 return cause;
4803}
4804
4805void verto_broadcast(const char *event_channel, cJSON *json, const char *key, switch_event_channel_id_t id)
4806{
4807 if (globals.debug > 9) {
4808 char *json_text;
4809 if ((json_text = cJSON_Print(json))) {
4810 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4810, ((void*)0)
, SWITCH_LOG_ALERT, "EVENT BROADCAST %s %s\n", event_channel, json_text);
4811 free(json_text);
4812 }
4813 }
4814
4815 jsock_send_event(json);
4816}
4817
4818
4819static int verto_send_chat(const char *uid, const char *call_id, cJSON *msg)
4820{
4821 jsock_t *jsock;
4822 verto_profile_t *profile;
4823 int hits = 0;
4824 int done = 0;
4825
4826 if (!strchr(uid, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(uid) && ('@') == '\0' ? (char *) __rawmemchr (uid, '@'
) : __builtin_strchr (uid, '@')))
) {
4827 return 0;
4828 }
4829
4830 if (call_id) {
4831 switch_core_session_t *session;
4832 if ((session = switch_core_session_locate(call_id)switch_core_session_perform_locate(call_id, "mod_verto.c", (const
char *)__func__, 4832)
)) {
4833 verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
4834 jsock_t *jsock;
4835
4836 if ((jsock = get_jsock(tech_pvt->jsock_uuid))) {
4837 jsock_queue_event(jsock, &msg, SWITCH_FALSE);
4838 //if (ws_write_json(jsock, &msg, SWITCH_FALSE) <= 0) {
4839 // switch_channel_hangup(switch_core_session_get_channel(session), SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
4840 //}
4841 switch_thread_rwlock_unlock(jsock->rwlock);
4842 done = 1;
4843 }
4844
4845 switch_core_session_rwunlock(session);
4846 }
4847 }
4848
4849 if (done) {
4850 return 1;
4851 }
4852
4853 switch_mutex_lock(globals.mutex);
4854 for(profile = globals.profile_head; profile; profile = profile->next) {
4855
4856 switch_mutex_lock(profile->mutex);
4857
4858 for(jsock = profile->jsock_head; jsock; jsock = jsock->next) {
4859 if (jsock->ready && !zstr(jsock->uid)_zstr(jsock->uid) && !strcmp(uid, jsock->uid)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(uid) && __builtin_constant_p (jsock->uid) &&
(__s1_len = __builtin_strlen (uid), __s2_len = __builtin_strlen
(jsock->uid), (!((size_t)(const void *)((uid) + 1) - (size_t
)(const void *)(uid) == 1) || __s1_len >= 4) && (!
((size_t)(const void *)((jsock->uid) + 1) - (size_t)(const
void *)(jsock->uid) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(uid, jsock->uid) : (__builtin_constant_p (uid) &&
((size_t)(const void *)((uid) + 1) - (size_t)(const void *)(
uid) == 1) && (__s1_len = __builtin_strlen (uid), __s1_len
< 4) ? (__builtin_constant_p (jsock->uid) && (
(size_t)(const void *)((jsock->uid) + 1) - (size_t)(const void
*)(jsock->uid) == 1) ? __builtin_strcmp (uid, jsock->uid
) : (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (jsock->uid); int __result = (((const
unsigned char *) (const char *) (uid))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (uid))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (uid))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (uid))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(jsock->uid) && ((size_t)(const void *)((jsock->
uid) + 1) - (size_t)(const void *)(jsock->uid) == 1) &&
(__s2_len = __builtin_strlen (jsock->uid), __s2_len < 4
) ? (__builtin_constant_p (uid) && ((size_t)(const void
*)((uid) + 1) - (size_t)(const void *)(uid) == 1) ? __builtin_strcmp
(uid, jsock->uid) : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (uid); int __result
= (((const unsigned char *) (const char *) (jsock->uid))[
0] - __s2[0]); if (__s2_len > 0 && __result == 0) {
__result = (((const unsigned char *) (const char *) (jsock->
uid))[1] - __s2[1]); if (__s2_len > 1 && __result ==
0) { __result = (((const unsigned char *) (const char *) (jsock
->uid))[2] - __s2[2]); if (__s2_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (jsock
->uid))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(uid, jsock->uid)))); })
) {
4860 jsock_queue_event(jsock, &msg, SWITCH_FALSE);
4861 hits++;
4862 }
4863 }
4864
4865 switch_mutex_unlock(profile->mutex);
4866 }
4867 switch_mutex_unlock(globals.mutex);
4868
4869 return hits;
4870}
4871
4872static switch_status_t chat_send(switch_event_t *message_event)
4873{
4874 switch_status_t status = SWITCH_STATUS_SUCCESS;
4875 const char *to = switch_event_get_header(message_event, "to")switch_event_get_header_idx(message_event, "to", -1);
4876 const char *from = switch_event_get_header(message_event, "from")switch_event_get_header_idx(message_event, "from", -1);
4877 const char *body = switch_event_get_body(message_event);
4878 const char *call_id = switch_event_get_header(message_event, "call_id")switch_event_get_header_idx(message_event, "call_id", -1);
4879
4880 //DUMP_EVENT(message_event);
4881
4882
4883 if (!zstr(to)_zstr(to) && !zstr(body)_zstr(body) && !zstr(from)_zstr(from)) {
4884 cJSON *obj = NULL((void*)0), *msg = NULL((void*)0), *params = NULL((void*)0);
4885 switch_event_header_t *eh;
4886
4887 obj = jrpc_new_req("verto.info", call_id, &params);
4888 msg = json_add_child_obj(params, "msg", NULL((void*)0));
4889
4890 cJSON_AddItemToObject(msg, "from", cJSON_CreateString(from));
4891 cJSON_AddItemToObject(msg, "to", cJSON_CreateString(to));
4892 cJSON_AddItemToObject(msg, "body", cJSON_CreateString(body));
4893
4894 for (eh = message_event->headers; eh; eh = eh->next) {
4895 if ((!strncasecmp(eh->name, "from_", 5) || !strncasecmp(eh->name, "to_", 3))) {
4896 cJSON_AddItemToObject(msg, eh->name, cJSON_CreateString(eh->value));
4897 }
4898 }
4899
4900 verto_send_chat(to, call_id, obj);
4901 cJSON_Delete(obj);
4902 } else {
4903 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4903, ((void*)0)
, SWITCH_LOG_ERROR, "INVALID EVENT\n");
4904 DUMP_EVENT(message_event){char *event_str;switch_event_serialize(message_event, &event_str
, SWITCH_FALSE);switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_verto.c"
, (const char *)__func__, 4904, ((void*)0), SWITCH_LOG_CRIT, "DUMP\n%s\n"
, event_str);free(event_str);}
;
4905 status = SWITCH_STATUS_FALSE;
4906 }
4907
4908
4909 return status;
4910}
4911
4912
4913
4914static switch_cache_db_handle_t *json_get_db_handle(void)
4915{
4916
4917 switch_cache_db_handle_t *dbh = NULL((void*)0);
4918 const char *dsn;
4919
4920
4921 if (!(dsn = switch_core_get_variable("json_db_handle"))) {
4922 dsn = "json";
4923 }
4924
4925
4926 if (switch_cache_db_get_db_handle_dsn(&dbh, dsn)_switch_cache_db_get_db_handle_dsn(&dbh, dsn, "mod_verto.c"
, (const char *)__func__, 4926)
!= SWITCH_STATUS_SUCCESS) {
4927 dbh = NULL((void*)0);
4928 }
4929
4930 return dbh;
4931}
4932
4933
4934static int jcallback(void *pArg, int argc, char **argv, char **columnNames)
4935{
4936 char **data = (char **) pArg;
4937
4938 if (argv[0] && !*data) {
4939 *data = strdup(argv[0])(__extension__ (__builtin_constant_p (argv[0]) && ((size_t
)(const void *)((argv[0]) + 1) - (size_t)(const void *)(argv[
0]) == 1) ? (((const char *) (argv[0]))[0] == '\0' ? (char *)
calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (
argv[0]) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, argv[0]
, __len); __retval; })) : __strdup (argv[0])))
;
4940 }
4941
4942 return 0;
4943}
4944
4945static cJSON *json_retrieve(const char *name, switch_mutex_t *mutex)
4946{
4947 char *sql, *errmsg;
4948 switch_cache_db_handle_t *dbh;
4949 char *ascii = NULL((void*)0);
4950 cJSON *json = NULL((void*)0);
4951
4952 if (!check_name(name)) {
4953 return NULL((void*)0);
4954 }
4955
4956 sql = switch_mprintf("select data from json_store where name='%q'", name);
4957
4958 dbh = json_get_db_handle();
4959
4960 if (mutex) switch_mutex_lock(mutex);
4961 switch_cache_db_execute_sql_callback(dbh, sql, jcallback, &ascii, &errmsg);
4962
4963 switch_cache_db_release_db_handle(&dbh);
4964
4965 if (errmsg) {
4966 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
4966, ((void*)0)
, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", sql, errmsg);
4967 free(errmsg);
4968 } else {
4969 if (ascii) {
4970 json = cJSON_Parse(ascii);
4971 }
4972 }
4973
4974 if (mutex) switch_mutex_unlock(mutex);
4975
4976
4977 switch_safe_free(ascii)if (ascii) {free(ascii);ascii=((void*)0);};
4978
4979 return json;
4980
4981}
4982
4983static switch_bool_t json_commit(cJSON *json, const char *name, switch_mutex_t *mutex)
4984{
4985 char *ascii;
4986 char *sql;
4987 char del_sql[128] = "";
4988 switch_cache_db_handle_t *dbh;
4989 char *err;
4990
4991 if (!check_name(name)) {
4992 return SWITCH_FALSE;
4993 }
4994
4995 if (!(ascii = cJSON_PrintUnformatted(json))) {
4996 return SWITCH_FALSE;
4997 }
4998
4999
5000 sql = switch_mprintf("insert into json_store (name,data) values('%q','%q')", name, ascii);
5001 switch_snprintfv(del_sql, sizeof(del_sql), "delete from json_store where name='%q'", name);
5002
5003 dbh = json_get_db_handle();
5004
5005
5006 if (mutex) switch_mutex_lock(mutex);
5007 switch_cache_db_execute_sql(dbh, del_sql, &err);
5008
5009 if (err) {
5010 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
5010, ((void*)0)
, SWITCH_LOG_ERROR, "sql err [%s]\n", err);
5011 free(err);
5012 } else {
5013 switch_cache_db_execute_sql(dbh, sql, &err);
5014
5015 if (err) {
5016 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
5016, ((void*)0)
, SWITCH_LOG_ERROR, "sql err [%s]\n", err);
5017 free(err);
5018 }
5019 }
5020
5021 if (mutex) switch_mutex_unlock(mutex);
5022
5023 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
5024 switch_safe_free(ascii)if (ascii) {free(ascii);ascii=((void*)0);};
5025
5026 switch_cache_db_release_db_handle(&dbh);
5027
5028 return SWITCH_TRUE;
5029}
5030
5031static switch_status_t json_hanguphook(switch_core_session_t *session)
5032{
5033 switch_channel_t *channel = switch_core_session_get_channel(session);
5034 switch_channel_state_t state = switch_channel_get_state(channel);
5035 json_store_t *session_store = NULL((void*)0);
5036 char *ascii = NULL((void*)0);
5037
5038 if (state == CS_HANGUP) {
5039 if ((session_store = (json_store_t *) switch_channel_get_private(channel, "_json_store_"))) {
5040 if ((ascii = cJSON_PrintUnformatted(session_store->JSON_STORE))) {
5041 switch_channel_set_variable(channel, "json_store_data", ascii)switch_channel_set_variable_var_check(channel, "json_store_data"
, ascii, SWITCH_TRUE)
;
5042 free(ascii);
5043 }
5044 cJSON_Delete(session_store->JSON_STORE);
5045 session_store->JSON_STORE = NULL((void*)0);
5046 switch_channel_set_private(channel, "_json_store_", NULL((void*)0));
5047 }
5048 switch_core_event_hook_remove_state_change(session, json_hanguphook);
5049 }
5050
5051 return SWITCH_STATUS_SUCCESS;
5052}
5053
5054SWITCH_STANDARD_JSON_API(json_store_function)static switch_status_t json_store_function (const cJSON *json
, switch_core_session_t *session, cJSON **json_reply)
5055{
5056 cJSON *JSON_STORE = NULL((void*)0), *reply = NULL((void*)0), *data = cJSON_GetObjectItem(json, "data");
5057 switch_status_t status = SWITCH_STATUS_FALSE;
5058 const char *cmd_attr = cJSON_GetObjectCstr(data, "cmd");
5059 const char *uuid = cJSON_GetObjectCstr(data, "uuid");
5060 const char *error = NULL((void*)0), *message = NULL((void*)0);
5061 store_cmd_t cmd;
5062 const char *key = cJSON_GetObjectCstr(data, "key");
5063 const char *verbose = cJSON_GetObjectCstr(data, "verbose");
5064 const char *commit = cJSON_GetObjectCstr(data, "commit");
5065 const char *file = cJSON_GetObjectCstr(data, "file");
5066 const char *storename = cJSON_GetObjectCstr(data, "storeName");
5067 cJSON *obj, **use_store = NULL((void*)0);
5068 switch_core_session_t *tsession = NULL((void*)0);
5069 switch_channel_t *tchannel = NULL((void*)0);
5070 json_store_t *session_store = NULL((void*)0);
5071
5072 reply = cJSON_CreateObject();
5073
5074 if (uuid) {
5075 if ((tsession = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "mod_verto.c", (const
char *)__func__, 5075)
)) {
5076 tchannel = switch_core_session_get_channel(tsession);
5077 } else {
5078 error = "Invalid INPUT, Missing UUID";
5079 goto end;
5080 }
5081 } else {
5082 if (zstr(storename)_zstr(storename)) {
5083 storename = "global";
5084 }
5085 }
5086
5087
5088 if (zstr(cmd_attr)_zstr(cmd_attr)) {
5089 error = "INVALID INPUT, Command not supplied";
5090 goto end;
5091 }
5092
5093
5094 if (!strcasecmp(cmd_attr, "add")) {
5095 cmd = CMD_ADD;
5096 } else if (!strcasecmp(cmd_attr, "del")) {
5097 cmd = CMD_DEL;
5098 } else if (!strcasecmp(cmd_attr, "dump")) {
5099 cmd = CMD_DUMP;
5100 } else if (!strcasecmp(cmd_attr, "commit")) {
5101 cmd = CMD_COMMIT;
5102 } else if (!strcasecmp(cmd_attr, "retrieve")) {
5103 cmd = CMD_RETRIEVE;
5104 } else {
5105 error = "INVALID INPUT, Unknown Command";
5106 goto end;
5107 }
5108
5109
5110 if (cmd == CMD_ADD) {
5111 if (zstr(key)_zstr(key)) {
5112 error = "INVALID INPUT, No key supplied";
5113 goto end;
5114 }
5115 }
5116
5117
5118 if (cmd == CMD_RETRIEVE || cmd == CMD_COMMIT) {
5119 if (zstr(file)_zstr(file)) {
5120 error = "INVALID INPUT, No file specified";
5121 goto end;
5122 }
5123 }
5124
5125 switch_mutex_lock(json_GLOBALS.store_mutex);
5126 if (tsession) {
5127 if (!(session_store = (json_store_t *) switch_channel_get_private(tchannel, "_json_store_"))) {
5128 session_store = switch_core_session_alloc(tsession, sizeof(*session_store))switch_core_perform_session_alloc(tsession, sizeof(*session_store
), "mod_verto.c", (const char *)__func__, 5128)
;
5129 switch_mutex_init(&session_store->mutex, SWITCH_MUTEX_NESTED0x1, switch_core_session_get_pool(tsession));
5130 session_store->JSON_STORE = cJSON_CreateObject();
5131 switch_channel_set_private(tchannel, "_json_store_", session_store);
5132 switch_core_event_hook_add_state_change(tsession, json_hanguphook);
5133 }
5134
5135 use_store = &session_store->JSON_STORE;
5136 switch_mutex_lock(session_store->mutex);
5137 switch_mutex_unlock(json_GLOBALS.store_mutex);
5138 } else {
5139 JSON_STORE = switch_core_hash_find(json_GLOBALS.store_hash, storename);
5140
5141 if (!JSON_STORE) {
5142 JSON_STORE = cJSON_CreateObject();
5143 switch_core_hash_insert(json_GLOBALS.store_hash, storename, JSON_STORE)switch_core_hash_insert_destructor(json_GLOBALS.store_hash, storename
, JSON_STORE, ((void*)0))
;
5144 }
5145 use_store = &JSON_STORE;
5146 }
5147
5148 switch(cmd) {
5149 case CMD_RETRIEVE:
5150 obj = json_retrieve(file, NULL((void*)0));
5151
5152 if (!obj) {
5153 error = "CANNOT LOAD DATA";
5154
5155 if (session_store) {
5156 switch_mutex_unlock(session_store->mutex);
5157 } else {
5158 switch_mutex_unlock(json_GLOBALS.store_mutex);
5159 }
5160
5161 goto end;
5162 }
5163
5164 cJSON_Delete(*use_store);
5165 *use_store = obj;
5166 message = "Store Loaded";
5167
5168 break;
5169 case CMD_ADD:
5170
5171 if (!(obj = cJSON_GetObjectItem(data, key))) {
5172 error = "INVALID INPUT";
5173
5174 if (session_store) {
5175 switch_mutex_unlock(session_store->mutex);
5176 } else {
5177 switch_mutex_unlock(json_GLOBALS.store_mutex);
5178 }
5179
5180 goto end;
5181 }
5182
5183 cJSON_DeleteItemFromObject(*use_store, key);
5184 obj = cJSON_Duplicate(obj, 1);
5185 cJSON_AddItemToObject(*use_store, key, obj);
5186 message = "Item Added";
5187 break;
5188
5189 case CMD_DEL:
5190
5191 if (!key) {
5192 cJSON_Delete(*use_store);
5193 *use_store = cJSON_CreateObject();
5194 message = "Store Deleted";
5195 } else {
5196 cJSON_DeleteItemFromObject(*use_store, key);
5197 message = "Item Deleted";
5198 }
5199 break;
5200
5201 default:
5202 break;
5203 }
5204
5205
5206 if (switch_true(verbose) || cmd == CMD_DUMP) {
5207 cJSON *dump;
5208
5209 if (key) {
5210 dump = cJSON_GetObjectItem(*use_store, key);
5211 } else {
5212 dump = *use_store;
5213 }
5214
5215 if (dump) {
5216 dump = cJSON_Duplicate(dump, 1);
5217 cJSON_AddItemToObject(reply, "data", dump);
5218 message = "Data Dumped";
5219 } else {
5220 error = "Key not found";
5221 }
5222 }
5223
5224 if (session_store) {
5225 switch_mutex_unlock(session_store->mutex);
5226 } else {
5227 switch_mutex_unlock(json_GLOBALS.store_mutex);
5228 }
5229
5230 if (cmd == CMD_COMMIT || commit) {
5231 switch_bool_t ok;
5232
5233 if (commit && zstr(file)_zstr(file)) {
5234 file = commit;
5235 }
5236
5237 if (session_store) {
5238 ok = json_commit(session_store->JSON_STORE, file, session_store->mutex);
5239 } else {
5240 ok = json_commit(JSON_STORE, file, json_GLOBALS.store_mutex);
5241 }
5242
5243 cJSON_AddItemToObject(reply, "commitStatus", cJSON_CreateString(ok ? "success" : "fail"));
5244 if (!message) {
5245 message = "Message Comitted";
5246 }
5247 status = SWITCH_STATUS_SUCCESS;
5248 }
5249
5250
5251 end:
5252
5253 if (!zstr(error)_zstr(error)) {
5254 cJSON_AddItemToObject(reply, "errorMessage", cJSON_CreateString(error));
5255 }
5256
5257 if (!zstr(message)_zstr(message)) {
5258 cJSON_AddItemToObject(reply, "message", cJSON_CreateString(message));
5259 status = SWITCH_STATUS_SUCCESS;
5260 }
5261
5262 *json_reply = reply;
5263
5264 if (tsession) {
5265 switch_core_session_rwunlock(tsession);
5266 }
5267
5268 return status;
5269}
5270
5271#define add_it(_name, _ename)if ((tmp = switch_event_get_header_idx(event, _ename, -1))) {
cJSON_AddItemToObject(data, _name, cJSON_CreateString(tmp));
}
if ((tmp = switch_event_get_header(event, _ename)switch_event_get_header_idx(event, _ename, -1))) { cJSON_AddItemToObject(data, _name, cJSON_CreateString(tmp));}
5272
5273static void presence_event_handler(switch_event_t *event)
5274{
5275 cJSON *msg = NULL((void*)0), *data = NULL((void*)0);
5276 const char *tmp;
5277 switch_event_header_t *hp;
5278 char *event_channel;
5279 const char *presence_id = switch_event_get_header(event, "channel-presence-id")switch_event_get_header_idx(event, "channel-presence-id", -1);
5280
5281 if (!globals.running) {
5282 return;
5283 }
5284
5285 if (!globals.enable_presence || zstr(presence_id)_zstr(presence_id)) {
5286 return;
5287 }
5288
5289 msg = cJSON_CreateObject();
5290 data = json_add_child_obj(msg, "data", NULL((void*)0));
5291
5292 event_channel = switch_mprintf("presence.%s", presence_id);
5293
5294 cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(event_channel));
5295 add_it("channelCallState", "channel-call-state")if ((tmp = switch_event_get_header_idx(event, "channel-call-state"
, -1))) { cJSON_AddItemToObject(data, "channelCallState", cJSON_CreateString
(tmp));}
;
5296 add_it("originalChannelCallState", "original-channel-call-state")if ((tmp = switch_event_get_header_idx(event, "original-channel-call-state"
, -1))) { cJSON_AddItemToObject(data, "originalChannelCallState"
, cJSON_CreateString(tmp));}
;
5297 add_it("channelState", "channel-state")if ((tmp = switch_event_get_header_idx(event, "channel-state"
, -1))) { cJSON_AddItemToObject(data, "channelState", cJSON_CreateString
(tmp));}
;
5298
5299 add_it("callerUserName", "caller-username")if ((tmp = switch_event_get_header_idx(event, "caller-username"
, -1))) { cJSON_AddItemToObject(data, "callerUserName", cJSON_CreateString
(tmp));}
;
5300 add_it("callerIDName", "caller-caller-id-name")if ((tmp = switch_event_get_header_idx(event, "caller-caller-id-name"
, -1))) { cJSON_AddItemToObject(data, "callerIDName", cJSON_CreateString
(tmp));}
;
5301 add_it("callerIDNumber", "caller-caller-id-number")if ((tmp = switch_event_get_header_idx(event, "caller-caller-id-number"
, -1))) { cJSON_AddItemToObject(data, "callerIDNumber", cJSON_CreateString
(tmp));}
;
5302 add_it("calleeIDName", "caller-callee-id-name")if ((tmp = switch_event_get_header_idx(event, "caller-callee-id-name"
, -1))) { cJSON_AddItemToObject(data, "calleeIDName", cJSON_CreateString
(tmp));}
;
5303 add_it("calleeIDNumber", "caller-callee-id-number")if ((tmp = switch_event_get_header_idx(event, "caller-callee-id-number"
, -1))) { cJSON_AddItemToObject(data, "calleeIDNumber", cJSON_CreateString
(tmp));}
;
5304 add_it("channelUUID", "unique-id")if ((tmp = switch_event_get_header_idx(event, "unique-id", -1
))) { cJSON_AddItemToObject(data, "channelUUID", cJSON_CreateString
(tmp));}
;
5305
5306 add_it("presenceCallDirection", "presence-call-direction")if ((tmp = switch_event_get_header_idx(event, "presence-call-direction"
, -1))) { cJSON_AddItemToObject(data, "presenceCallDirection"
, cJSON_CreateString(tmp));}
;
5307 add_it("channelPresenceID", "channel-presence-id")if ((tmp = switch_event_get_header_idx(event, "channel-presence-id"
, -1))) { cJSON_AddItemToObject(data, "channelPresenceID", cJSON_CreateString
(tmp));}
;
5308 add_it("channelPresenceData", "channel-presence-data")if ((tmp = switch_event_get_header_idx(event, "channel-presence-data"
, -1))) { cJSON_AddItemToObject(data, "channelPresenceData", cJSON_CreateString
(tmp));}
;
5309
5310 for(hp = event->headers; hp; hp = hp->next) {
5311 if (!strncasecmp(hp->name, "PD-", 3)) {
5312 add_it(hp->name, hp->name)if ((tmp = switch_event_get_header_idx(event, hp->name, -1
))) { cJSON_AddItemToObject(data, hp->name, cJSON_CreateString
(tmp));}
;
5313 }
5314 }
5315
5316 switch_event_channel_broadcast(event_channel, &msg, __FILE__"mod_verto.c", NO_EVENT_CHANNEL_ID0);
5317
5318 free(event_channel);
5319
5320}
5321
5322static void event_handler(switch_event_t *event)
5323{
5324 cJSON *msg = NULL((void*)0), *data = NULL((void*)0);
5325 char *event_channel;
5326
5327 if (!globals.enable_fs_events) {
5328 return;
5329 }
5330
5331 switch_event_serialize_json_obj(event, &data);
5332
5333 msg = cJSON_CreateObject();
5334
5335 if (event->event_id == SWITCH_EVENT_CUSTOM) {
5336 const char *subclass = switch_event_get_header(event, "Event-Subclass")switch_event_get_header_idx(event, "Event-Subclass", -1);
5337 event_channel = switch_mprintf("FSevent.%s::%s", switch_event_name(event->event_id), subclass);
5338 switch_tolower_max(event_channel + 8);
5339 } else {
5340 event_channel = switch_mprintf("FSevent.%s", switch_event_name(event->event_id));
5341 switch_tolower_max(event_channel + 8);
5342 }
5343
5344 cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(event_channel));
5345 cJSON_AddItemToObject(msg, "data", data);
5346
5347 /* comment broadcasting globally and change to only within the module cos FS events are heavy */
5348 //switch_event_channel_broadcast(event_channel, &msg, __FILE__, NO_EVENT_CHANNEL_ID);
5349 verto_broadcast(event_channel, msg, __FILE__"mod_verto.c", NO_EVENT_CHANNEL_ID0);cJSON_Delete(msg);
5350
5351 free(event_channel);
5352
5353}
5354
5355/* Macro expands to: switch_status_t mod_verto_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
5356SWITCH_MODULE_LOAD_FUNCTION(mod_verto_load)switch_status_t mod_verto_load (switch_loadable_module_interface_t
**module_interface, switch_memory_pool_t *pool)
5357{
5358 switch_api_interface_t *api_interface = NULL((void*)0);
5359 switch_chat_interface_t *chat_interface = NULL((void*)0);
5360 switch_json_api_interface_t *json_api_interface = NULL((void*)0);
5361 int r;
5362 switch_cache_db_handle_t *dbh;
5363 //switch_application_interface_t *app_interface = NULL;
5364
5365 memset(&globals, 0, sizeof(globals));
5366 globals.pool = pool;
5367#ifndef WIN32
5368 globals.ready = SIGUSR110;
5369#endif
5370 globals.enable_presence = SWITCH_TRUE;
5371 globals.enable_fs_events = SWITCH_FALSE;
5372
5373 switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED0x1, globals.pool);
5374
5375 switch_mutex_init(&globals.method_mutex, SWITCH_MUTEX_NESTED0x1, globals.pool);
5376 switch_core_hash_init(&globals.method_hash)switch_core_hash_init_case(&globals.method_hash, SWITCH_TRUE
)
;
5377
5378 switch_thread_rwlock_create(&globals.event_channel_rwlock, globals.pool);
5379 switch_core_hash_init(&globals.event_channel_hash)switch_core_hash_init_case(&globals.event_channel_hash, SWITCH_TRUE
)
;
5380
5381 switch_mutex_init(&globals.jsock_mutex, SWITCH_MUTEX_NESTED0x1, globals.pool);
5382 switch_core_hash_init(&globals.jsock_hash)switch_core_hash_init_case(&globals.jsock_hash, SWITCH_TRUE
)
;
5383
5384 switch_thread_rwlock_create(&globals.tech_rwlock, globals.pool);
5385
5386 switch_mutex_init(&globals.detach_mutex, SWITCH_MUTEX_NESTED0x1, globals.pool);
5387 switch_mutex_init(&globals.detach2_mutex, SWITCH_MUTEX_NESTED0x1, globals.pool);
5388 switch_thread_cond_create(&globals.detach_cond, globals.pool);
5389 globals.detach_timeout = 120;
5390
5391
5392
5393
5394 memset(&json_GLOBALS, 0, sizeof(json_GLOBALS));
5395 switch_mutex_init(&json_GLOBALS.store_mutex, SWITCH_MUTEX_NESTED0x1, pool);
5396 switch_core_hash_init(&json_GLOBALS.store_hash)switch_core_hash_init_case(&json_GLOBALS.store_hash, SWITCH_TRUE
)
;
5397
5398
5399 dbh = json_get_db_handle();
5400 switch_cache_db_test_reactive(dbh, "select name from json_store where name=''", "drop table json_store", json_sql);
5401 switch_cache_db_release_db_handle(&dbh);
5402
5403
5404
5405 switch_event_channel_bind(SWITCH_EVENT_CHANNEL_GLOBAL"__global__", verto_broadcast, &globals.event_channel_id);
5406
5407
5408 r = init();
5409
5410 if (r) return SWITCH_STATUS_TERM;
5411
5412 jrpc_init();
5413
5414 /* connect my internal structure to the blank pointer passed to me */
5415 *module_interface = switch_loadable_module_create_module_interface(pool, modname);
5416
5417 SWITCH_ADD_API(api_interface, "verto", "Verto API", verto_function, "syntax")for (;;) { api_interface = (switch_api_interface_t *)switch_loadable_module_create_interface
(*module_interface, SWITCH_API_INTERFACE); api_interface->
interface_name = "verto"; api_interface->desc = "Verto API"
; api_interface->function = verto_function; api_interface->
syntax = "syntax"; break; }
;
5418 SWITCH_ADD_API(api_interface, "verto_contact", "Generate a verto endpoint dialstring", verto_contact_function, "user@domain")for (;;) { api_interface = (switch_api_interface_t *)switch_loadable_module_create_interface
(*module_interface, SWITCH_API_INTERFACE); api_interface->
interface_name = "verto_contact"; api_interface->desc = "Generate a verto endpoint dialstring"
; api_interface->function = verto_contact_function; api_interface
->syntax = "user@domain"; break; }
;
5419 switch_console_set_complete("add verto help");
5420 switch_console_set_complete("add verto status");
5421 switch_console_set_complete("add verto xmlstatus");
5422
5423 SWITCH_ADD_JSON_API(json_api_interface, "store", "JSON store", json_store_function, "")for (;;) { json_api_interface = (switch_json_api_interface_t *
)switch_loadable_module_create_interface(*module_interface, SWITCH_JSON_API_INTERFACE
); json_api_interface->interface_name = "store"; json_api_interface
->desc = "JSON store"; json_api_interface->function = json_store_function
; json_api_interface->syntax = ""; break; }
;
5424
5425 verto_endpoint_interface = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
5426 verto_endpoint_interface->interface_name = EP_NAME"verto.rtc";
5427 verto_endpoint_interface->io_routines = &verto_io_routines;
5428
5429 SWITCH_ADD_CHAT(chat_interface, VERTO_CHAT_PROTO, chat_send)for (;;) { chat_interface = (switch_chat_interface_t *)switch_loadable_module_create_interface
(*module_interface, SWITCH_CHAT_INTERFACE); chat_interface->
chat_send = chat_send; chat_interface->interface_name = "verto"
; break; }
;
5430
5431 switch_core_register_secondary_recover_callback(modname, verto_recover_callback);
5432
5433 if (globals.enable_presence) {
5434 switch_event_bind(modname, SWITCH_EVENT_CHANNEL_CALLSTATE, SWITCH_EVENT_SUBCLASS_ANY((void*)0), presence_event_handler, NULL((void*)0));
5435 }
5436
5437 if (globals.enable_fs_events) {
5438 if (switch_event_bind(modname, SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY((void*)0), event_handler, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
5439 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_verto.c", (const char *)__func__,
5439, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't bind!\n");
5440 return SWITCH_STATUS_GENERR;
5441 }
5442 }
5443
5444 run_profiles();
5445
5446 /* indicate that the module should continue to be loaded */
5447 return SWITCH_STATUS_SUCCESS;
5448}
5449
5450/*
5451 Called when the system shuts down
5452 Macro expands to: switch_status_t mod_verto_shutdown() */
5453SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_verto_shutdown)switch_status_t mod_verto_shutdown (void)
5454{
5455 json_cleanup();
5456 switch_core_hash_destroy(&json_GLOBALS.store_hash);
5457
5458 switch_event_channel_unbind(NULL((void*)0), verto_broadcast);
5459 switch_event_unbind_callback(presence_event_handler);
5460 switch_event_unbind_callback(event_handler);
5461
5462 switch_core_unregister_secondary_recover_callback(modname);
5463 do_shutdown();
5464 attach_wake();
5465 attach_wake();
5466
5467 switch_core_hash_destroy(&globals.method_hash);
5468 switch_core_hash_destroy(&globals.event_channel_hash);
5469 switch_core_hash_destroy(&globals.jsock_hash);
5470
5471 return SWITCH_STATUS_SUCCESS;
5472}
5473
5474SWITCH_MODULE_RUNTIME_FUNCTION(mod_verto_runtime)switch_status_t mod_verto_runtime (void)
5475{
5476 switch_mutex_lock(globals.detach_mutex);
5477
5478 while(globals.running) {
5479 if (globals.detached) {
5480 drop_detached();
5481 switch_yield(1000000)switch_sleep(1000000);;
5482 } else {
5483 switch_mutex_lock(globals.detach2_mutex);
5484 if (globals.running) {
5485 switch_thread_cond_wait(globals.detach_cond, globals.detach_mutex);
5486 }
5487 switch_mutex_unlock(globals.detach2_mutex);
5488 }
5489 }
5490
5491 switch_mutex_unlock(globals.detach_mutex);
5492
5493 return SWITCH_STATUS_TERM;
5494}
5495
5496
5497/* For Emacs:
5498 * Local Variables:
5499 * mode:c
5500 * indent-tabs-mode:t
5501 * tab-width:4
5502 * c-basic-offset:4
5503 * End:
5504 * For VIM:
5505 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet
5506 */