Bug Summary

File:src/mod/endpoints/mod_verto/mod_verto.c
Location:line 801, column 3
Description:Value stored to 'cur' is never read

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;
Value stored to 'cur' is never read
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) {
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) {
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)))
) {
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;
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) {
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)) {
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;
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, ':')))
)) {
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)))); }
)
) {
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) {
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, '.'))) {
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) {
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) {
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
; }
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
; }
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
; }
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
; }
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
; }
1702 if (pflags & SWITCH_POLL_READ) {
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) {
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")) {
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;
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 */