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