1 /*
2  * mod_rayo for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2013-2018, Grasshopper
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 mod_rayo for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is Grasshopper
20  * Portions created by the Initial Developer are Copyright (C)
21  * the Initial Developer. All Rights Reserved.
22  *
23  * Contributor(s):
24  * Chris Rienzo <chris.rienzo@grasshopper.com>
25  *
26  * mod_rayo.c -- Rayo server / node implementation.  Allows MxN clustering of FreeSWITCH and Rayo Clients (like Adhearsion)
27  *
28  */
29 #include <switch.h>
30 #include <iksemel.h>
31 
32 #include "mod_rayo.h"
33 #include "rayo_components.h"
34 #include "rayo_elements.h"
35 #include "xmpp_streams.h"
36 
37 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_rayo_shutdown);
38 SWITCH_MODULE_LOAD_FUNCTION(mod_rayo_load);
39 SWITCH_MODULE_RUNTIME_FUNCTION(mod_rayo_runtime);
40 SWITCH_MODULE_DEFINITION(mod_rayo, mod_rayo_load, mod_rayo_shutdown, mod_rayo_runtime);
41 
42 #define RAYO_CAUSE_HANGUP SWITCH_CAUSE_NORMAL_CLEARING
43 #define RAYO_CAUSE_DECLINE SWITCH_CAUSE_CALL_REJECTED
44 #define RAYO_CAUSE_BUSY SWITCH_CAUSE_USER_BUSY
45 #define RAYO_CAUSE_ERROR SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE
46 
47 #define RAYO_END_REASON_HANGUP "hungup"
48 #define RAYO_END_REASON_HANGUP_LOCAL "hangup-command"
49 #define RAYO_END_REASON_TIMEOUT "timeout"
50 #define RAYO_END_REASON_BUSY "busy"
51 #define RAYO_END_REASON_REJECT "rejected"
52 #define RAYO_END_REASON_ERROR "error"
53 
54 #define RAYO_SIP_REQUEST_HEADER "sip_h_"
55 #define RAYO_SIP_RESPONSE_HEADER "sip_rh_"
56 #define RAYO_SIP_PROVISIONAL_RESPONSE_HEADER "sip_ph_"
57 #define RAYO_SIP_BYE_RESPONSE_HEADER "sip_bye_h_"
58 
59 #define RAYO_CONFIG_FILE "rayo.conf"
60 
61 #define JOINED_CALL 1
62 #define JOINED_MIXER 2
63 
64 #define OFFER_ALL 0
65 #define OFFER_FIRST 1
66 #define OFFER_RANDOM 2
67 
68 struct rayo_actor;
69 struct rayo_client;
70 struct rayo_call;
71 
72 #define rayo_call_get_uuid(call) RAYO_ID(call)
73 
74 /**
75  * Function pointer wrapper for the handlers hash
76  */
77 struct rayo_xmpp_handler {
78 	const char *from_type;
79 	const char *from_subtype;
80 	const char *to_type;
81 	const char *to_subtype;
82 	rayo_actor_xmpp_handler fn;
83 };
84 
85 /**
86  * Client availability
87  */
88 enum presence_status {
89 	PS_UNKNOWN = -1,
90 	PS_OFFLINE = 0,
91 	PS_ONLINE = 1
92 };
93 
94 /**
95  * A xmpp peer server that routes messages to/from clients
96  */
97 struct rayo_peer_server {
98 	/** base class */
99 	struct rayo_actor base;
100 	/** clients connected via this server */
101 	switch_hash_t *clients;
102 };
103 #define RAYO_PEER_SERVER(x) ((struct rayo_peer_server *)x)
104 
105 /**
106  * A Rayo client that controls calls
107  */
108 struct rayo_client {
109 	/** base class */
110 	struct rayo_actor base;
111 	/** availability */
112 	enum presence_status availability;
113 	/** set if reachable via s2s */
114 	struct rayo_peer_server *peer_server;
115 	/** domain or full JID to route to */
116 	const char *route;
117 	/** time when last probe was sent */
118 	switch_time_t last_probe;
119 };
120 #define RAYO_CLIENT(x) ((struct rayo_client *)x)
121 
122 /**
123  * A call controlled by a Rayo client
124  */
125 struct rayo_call {
126 	/** actor base class */
127 	struct rayo_actor base;
128 	/** Definitive controlling party JID */
129 	char *dcp_jid;
130 	/** Potential controlling parties (have sent offers to) */
131 	switch_hash_t *pcps;
132 	/** Available controlling parties (not sent offers to) */
133 	switch_hash_t *acps;
134 	/** Number of available controlling parties */
135 	int num_acps;
136 	/** current idle start time */
137 	switch_time_t idle_start_time;
138 	/** true if fax is in progress */
139 	int faxing;
140 	/** 1 if joined to call, 2 if joined to mixer */
141 	int joined;
142 	/** pending join */
143 	iks *pending_join_request;
144 	/** ID of joined party TODO this will be many mixers / calls */
145 	const char *joined_id;
146 	/** set if response needs to be sent to IQ request */
147 	const char *dial_request_id;
148 	/** channel destroy event */
149 	switch_event_t *end_event;
150 	/** True if ringing event sent to client */
151 	int ringing_sent;
152 	/** true if rayo app has started */
153 	int rayo_app_started;
154 	/** delayed delivery of answer event because rayo APP wasn't started yet */
155 	switch_event_t *answer_event;
156 	/** True if request to create this call failed */
157 	int dial_request_failed;
158 };
159 
160 /**
161  * A conference
162  */
163 struct rayo_mixer {
164 	/** actor base class */
165 	struct rayo_actor base;
166 	/** member JIDs */
167 	switch_hash_t *members;
168 	/** subscriber JIDs */
169 	switch_hash_t *subscribers;
170 };
171 
172 /**
173  * A member of a mixer
174  */
175 struct rayo_mixer_member {
176 	/** JID of member */
177 	const char *jid;
178 	/** Controlling party JID */
179 	const char *dcp_jid;
180 };
181 
182 /**
183  * A subscriber to mixer events
184  */
185 struct rayo_mixer_subscriber {
186 	/** JID of client */
187 	const char *jid;
188 	/** Number of client's calls in mixer */
189 	int ref_count;
190 };
191 
192 /**
193  * Module state
194  */
195 static struct {
196 	/** module memory pool */
197 	switch_memory_pool_t *pool;
198 	/** Rayo <iq> set commands mapped to functions */
199 	switch_hash_t *command_handlers;
200 	/** Rayo <presence> events mapped to functions */
201 	switch_hash_t *event_handlers;
202 	/** Active Rayo actors mapped by JID */
203 	switch_hash_t *actors;
204 	/** Rayo actors pending destruction */
205 	switch_hash_t *destroy_actors;
206 	/** Active Rayo actors mapped by internal ID */
207 	switch_hash_t *actors_by_id;
208 	/** synchronizes access to actors */
209 	switch_mutex_t *actors_mutex;
210 	/** map of DCP JID to client */
211 	switch_hash_t *clients_roster;
212 	/** synchronizes access to available clients */
213 	switch_mutex_t *clients_mutex;
214 	/** server for calls/mixers/etc */
215 	struct rayo_actor *server;
216 	/** Maximum idle time before call is considered abandoned */
217 	int max_idle_ms;
218 	/** Conference profile to use for mixers */
219 	char *mixer_conf_profile;
220 	/** to URI prefixes mapped to gateways */
221 	switch_hash_t *dial_gateways;
222 	/** synchronizes access to dial gateways */
223 	switch_mutex_t *dial_gateways_mutex;
224 	/** console command aliases */
225 	switch_hash_t *cmd_aliases;
226 	/** global console */
227 	struct rayo_client *console;
228 	/** XMPP context */
229 	struct xmpp_stream_context *xmpp_context;
230 	/** number of message threads */
231 	int num_message_threads;
232 	/** message delivery queue */
233 	switch_queue_t *msg_queue;
234 	/** in progress offer queue */
235 	switch_queue_t *offer_queue;
236 	/** shutdown flag */
237 	int shutdown;
238 	/** prevents context shutdown until all threads are finished */
239 	switch_thread_rwlock_t *shutdown_rwlock;
240 	/** if true, URI is put in from/to of offer if available */
241 	int offer_uri;
242 	/** if true, pause inbound calling if all clients are offline */
243 	int pause_when_offline;
244 	/** flag to reduce log noise */
245 	int offline_logged;
246 	/** if true, channel variables are added to offer */
247 	int add_variables_to_offer;
248 	/** if true, channel variables are added to answered, ringing, end events */
249 	int add_variables_to_events;
250 	/** How to distribute offers to clients */
251 	int offer_algorithm;
252 	/** How long to wait for offer response before retrying */
253 	int offer_timeout_us;
254 } globals;
255 
256 /**
257  * An outbound dial gateway
258  */
259 struct dial_gateway {
260 	/** URI prefix to match */
261 	const char *uri_prefix;
262 	/** dial prefix to match */
263 	const char *dial_prefix;
264 	/** number of digits to strip from dialstring */
265 	int strip;
266 };
267 
268 static void rayo_call_send(struct rayo_actor *call, struct rayo_message *msg);
269 static void rayo_server_send(struct rayo_actor *server, struct rayo_message *msg);
270 static void rayo_mixer_send(struct rayo_actor *mixer, struct rayo_message *msg);
271 static void rayo_component_send(struct rayo_actor *component, struct rayo_message *msg);
272 static void rayo_client_send(struct rayo_actor *client, struct rayo_message *msg);
273 static void rayo_console_client_send(struct rayo_actor *client, struct rayo_message *msg);
274 
275 static void on_client_presence(struct rayo_client *rclient, iks *node);
276 
277 typedef switch_bool_t (* rayo_actor_match_fn)(struct rayo_actor *);
278 
279 static switch_bool_t is_call_actor(struct rayo_actor *actor);
280 
281 static void rayo_call_send_end(struct rayo_call *call, switch_event_t *event, int local_hangup, const char *cause_str, const char *cause_q850_str);
282 
283 
284 /**
285  * Entity features returned by service discovery
286  */
287 struct entity_identity {
288 	/** identity category */
289 	const char *category;
290 	/** identity type */
291 	const char *type;
292 };
293 
294 static struct entity_identity rayo_server_identity = { "server", "im" };
295 static const char *rayo_server_features[] = { IKS_NS_XMPP_ENTITY_CAPABILITIES, IKS_NS_XMPP_DISCO, RAYO_NS, RAYO_CPA_NS, RAYO_FAX_NS, 0 };
296 
297 static struct entity_identity rayo_mixer_identity = { "client", "rayo_mixer" };
298 static const char *rayo_mixer_features[] = { 0 };
299 
300 static struct entity_identity rayo_call_identity = { "client", "rayo_call" };
301 static const char *rayo_call_features[] = { 0 };
302 
303 /**
304  * Calculate SHA-1 hash of entity capabilities
305  * @param identity of entity
306  * @param features of identity (NULL terminated)
307  * @return base64 hash (free when done)
308  */
calculate_entity_sha1_ver(struct entity_identity * identity,const char ** features)309 static char *calculate_entity_sha1_ver(struct entity_identity *identity, const char **features)
310 {
311 	int i;
312 	const char *feature;
313 	char ver[SHA_1_HASH_BUF_SIZE + 1] = { 0 };
314 	iksha *sha;
315 
316 	sha = iks_sha_new();
317 	iks_sha_hash(sha, (const unsigned char *)identity->category, strlen(identity->category), 0);
318 	iks_sha_hash(sha, (const unsigned char *)"/", 1, 0);
319 	iks_sha_hash(sha, (const unsigned char *)identity->type, strlen(identity->type), 0);
320 	iks_sha_hash(sha, (const unsigned char *)"//", 2, 0);
321 	i = 0;
322 	while ((feature = features[i++])) {
323 		iks_sha_hash(sha, (const unsigned char *)"<", 1, 0);
324 		iks_sha_hash(sha, (const unsigned char *)feature, strlen(feature), 0);
325 	}
326 	iks_sha_hash(sha, (const unsigned char *)"<", 1, 1);
327 	iks_sha_print_base64(sha, ver);
328 	iks_sha_delete(sha);
329 
330 	return strdup(ver);
331 }
332 
333 /**
334  * @param msg to check
335  * @return true if message was sent by admin client (console)
336  */
is_admin_client_message(struct rayo_message * msg)337 static int is_admin_client_message(struct rayo_message *msg)
338 {
339 	return !zstr(msg->from_jid) && !strcmp(RAYO_JID(globals.console), msg->from_jid);
340 }
341 
342 /**
343  * @param msg to check
344  * @return true if from/to bare JIDs match
345  */
is_internal_message(struct rayo_message * msg)346 static int is_internal_message(struct rayo_message *msg)
347 {
348 	return msg->from && msg->to && (iks_id_cmp(msg->from, msg->to, IKS_ID_PARTIAL) == 0);
349 }
350 
351 /**
352  * Presence status
353  * @param status the presence status
354  * @return the string value of status
355  */
presence_status_to_string(enum presence_status status)356 static const char *presence_status_to_string(enum presence_status status)
357 {
358 	switch(status) {
359 		case PS_OFFLINE: return "OFFLINE";
360 		case PS_ONLINE: return "ONLINE";
361 		case PS_UNKNOWN: return "UNKNOWN";
362 	}
363 	return "UNKNOWN";
364 }
365 
366 /**
367  * Get rayo cause code from FS hangup cause
368  * @param cause FS hangup cause
369  * @return rayo end cause
370  */
switch_cause_to_rayo_cause(switch_call_cause_t cause)371 static const char *switch_cause_to_rayo_cause(switch_call_cause_t cause)
372 {
373 	switch (cause) {
374 		case SWITCH_CAUSE_NONE:
375 		case SWITCH_CAUSE_NORMAL_CLEARING:
376 			return RAYO_END_REASON_HANGUP;
377 
378 		case SWITCH_CAUSE_UNALLOCATED_NUMBER:
379 		case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET:
380 		case SWITCH_CAUSE_NO_ROUTE_DESTINATION:
381 		case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE:
382 			return RAYO_END_REASON_ERROR;
383 
384 		case SWITCH_CAUSE_CALL_AWARDED_DELIVERED:
385 			return RAYO_END_REASON_HANGUP;
386 
387 		case SWITCH_CAUSE_USER_BUSY:
388 			return RAYO_END_REASON_BUSY;
389 
390 		case SWITCH_CAUSE_NO_USER_RESPONSE:
391 		case SWITCH_CAUSE_NO_ANSWER:
392 			return RAYO_END_REASON_TIMEOUT;
393 
394 		case SWITCH_CAUSE_SUBSCRIBER_ABSENT:
395 			return RAYO_END_REASON_ERROR;
396 
397 		case SWITCH_CAUSE_CALL_REJECTED:
398 			return RAYO_END_REASON_REJECT;
399 
400 		case SWITCH_CAUSE_NUMBER_CHANGED:
401 		case SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION:
402 		case SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR:
403 		case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
404 		case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
405 			return RAYO_END_REASON_ERROR;
406 
407 		case SWITCH_CAUSE_FACILITY_REJECTED:
408 			return RAYO_END_REASON_REJECT;
409 
410 		case SWITCH_CAUSE_RESPONSE_TO_STATUS_ENQUIRY:
411 		case SWITCH_CAUSE_NORMAL_UNSPECIFIED:
412 			return RAYO_END_REASON_HANGUP;
413 
414 		case SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION:
415 		case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
416 		case SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE:
417 		case SWITCH_CAUSE_SWITCH_CONGESTION:
418 		case SWITCH_CAUSE_ACCESS_INFO_DISCARDED:
419 		case SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL:
420 		case SWITCH_CAUSE_PRE_EMPTED:
421 		case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED:
422 		case SWITCH_CAUSE_OUTGOING_CALL_BARRED:
423 		case SWITCH_CAUSE_INCOMING_CALL_BARRED:
424 		case SWITCH_CAUSE_BEARERCAPABILITY_NOTAUTH:
425 		case SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL:
426 		case SWITCH_CAUSE_SERVICE_UNAVAILABLE:
427 		case SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL:
428 		case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED:
429 		case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED:
430 		case SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED:
431 		case SWITCH_CAUSE_INVALID_CALL_REFERENCE:
432 		case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION:
433 		case SWITCH_CAUSE_INVALID_MSG_UNSPECIFIED:
434 		case SWITCH_CAUSE_MANDATORY_IE_MISSING:
435 			return RAYO_END_REASON_ERROR;
436 
437 		case SWITCH_CAUSE_MESSAGE_TYPE_NONEXIST:
438 		case SWITCH_CAUSE_WRONG_MESSAGE:
439 		case SWITCH_CAUSE_IE_NONEXIST:
440 		case SWITCH_CAUSE_INVALID_IE_CONTENTS:
441 		case SWITCH_CAUSE_WRONG_CALL_STATE:
442 		case SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE:
443 		case SWITCH_CAUSE_MANDATORY_IE_LENGTH_ERROR:
444 		case SWITCH_CAUSE_PROTOCOL_ERROR:
445 			return RAYO_END_REASON_ERROR;
446 
447 		case SWITCH_CAUSE_INTERWORKING:
448 		case SWITCH_CAUSE_SUCCESS:
449 		case SWITCH_CAUSE_ORIGINATOR_CANCEL:
450 			return RAYO_END_REASON_HANGUP;
451 
452 		case SWITCH_CAUSE_CRASH:
453 		case SWITCH_CAUSE_SYSTEM_SHUTDOWN:
454 		case SWITCH_CAUSE_LOSE_RACE:
455 		case SWITCH_CAUSE_MANAGER_REQUEST:
456 		case SWITCH_CAUSE_BLIND_TRANSFER:
457 		case SWITCH_CAUSE_ATTENDED_TRANSFER:
458 		case SWITCH_CAUSE_ALLOTTED_TIMEOUT:
459 		case SWITCH_CAUSE_USER_CHALLENGE:
460 		case SWITCH_CAUSE_MEDIA_TIMEOUT:
461 		case SWITCH_CAUSE_PICKED_OFF:
462 		case SWITCH_CAUSE_USER_NOT_REGISTERED:
463 		case SWITCH_CAUSE_PROGRESS_TIMEOUT:
464 		case SWITCH_CAUSE_INVALID_GATEWAY:
465 		case SWITCH_CAUSE_GATEWAY_DOWN:
466 		case SWITCH_CAUSE_INVALID_URL:
467 		case SWITCH_CAUSE_INVALID_PROFILE:
468 		case SWITCH_CAUSE_NO_PICKUP:
469 		case SWITCH_CAUSE_SRTP_READ_ERROR:
470 			return RAYO_END_REASON_ERROR;
471 		default:
472 			break;
473 	}
474 	return RAYO_END_REASON_HANGUP;
475 }
476 
477 /**
478  * Add <header> to node
479  * @param node to add <header> to
480  * @param name of header
481  * @param value of header
482  */
add_header(iks * node,const char * name,const char * value)483 static void add_header(iks *node, const char *name, const char *value)
484 {
485 	if (!zstr(name) && !zstr(value)) {
486 		iks *header = iks_insert(node, "header");
487 		iks_insert_attrib(header, "name", name);
488 		iks_insert_attrib(header, "value", value);
489 	}
490 }
491 
492 /**
493  * Add SIP <header>s to node
494  * @param node to add <header> to
495  * @param event source
496  * @param add_variables true if channel variables should be added
497  */
add_headers_to_event(iks * node,switch_event_t * event,int add_variables)498 static void add_headers_to_event(iks *node, switch_event_t *event, int add_variables)
499 {
500 	switch_event_header_t *header;
501 	/* get all variables prefixed with sip_h_ */
502 	for (header = event->headers; header; header = header->next) {
503 		if (!strncmp("variable_sip_h_", header->name, 15)) {
504 			if (!zstr(header->name)) {
505 				add_header(node, header->name + 15, header->value);
506 			}
507 		} else if (add_variables && !strncmp("variable_", header->name, 9)) {
508 			if (!zstr(header->name)) {
509 				char header_name[1024];
510 				snprintf(header_name, 1024, "variable-%s", header->name + 9);
511 				add_header(node, header_name, header->value);
512 			}
513 		}
514 	}
515 }
516 
517 /**
518  * Add SIP <header>s to node
519  * @param node to add <header> to
520  * @param add_variables true if channel variables should be added
521  */
add_channel_headers_to_event(iks * node,switch_channel_t * channel,int add_variables)522 static void add_channel_headers_to_event(iks *node, switch_channel_t *channel, int add_variables)
523 {
524 	switch_event_header_t *var;
525 
526 	/* add all SIP header variables and (if configured) all other variables */
527 	for (var = switch_channel_variable_first(channel); var; var = var->next) {
528 		if (!strncmp("sip_h_", var->name, 6)) {
529 			add_header(node, var->name + 6, var->value);
530 		}
531 		if (add_variables) {
532 			char var_name[1024];
533 			snprintf(var_name, 1024, "variable-%s", var->name);
534 			add_header(node, var_name, var->value);
535 		}
536 	}
537 	switch_channel_variable_last(channel);
538 }
539 
pause_inbound_calling(void)540 static void pause_inbound_calling(void)
541 {
542 	int32_t arg = 1;
543 	switch_mutex_lock(globals.clients_mutex);
544 	switch_core_session_ctl(SCSC_PAUSE_INBOUND, &arg);
545 	if (!globals.offline_logged) {
546 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Pausing inbound calling\n");
547 		globals.offline_logged = 1;
548 	}
549 	switch_mutex_unlock(globals.clients_mutex);
550 }
551 
resume_inbound_calling(void)552 static void resume_inbound_calling(void)
553 {
554 	int32_t arg = 0;
555 	switch_mutex_lock(globals.clients_mutex);
556 	switch_core_session_ctl(SCSC_PAUSE_INBOUND, &arg);
557 	if (globals.offline_logged) {
558 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Resuming inbound calling\n");
559 		globals.offline_logged = 0;
560 	}
561 	switch_mutex_unlock(globals.clients_mutex);
562 }
563 
564 /**
565  * Check online status of rayo client(s) and pause/resume the server
566  */
pause_when_offline(void)567 static void pause_when_offline(void)
568 {
569 	if (globals.pause_when_offline) {
570 		int is_online = 0;
571 		switch_hash_index_t *hi;
572 
573 		switch_mutex_lock(globals.clients_mutex);
574 
575 		for (hi = switch_core_hash_first(globals.clients_roster); hi; hi = switch_core_hash_next(&hi)) {
576 			const void *key;
577 			void *client;
578 			switch_core_hash_this(hi, &key, NULL, &client);
579 			switch_assert(client);
580 			if (RAYO_CLIENT(client)->availability == PS_ONLINE) {
581 				is_online = 1;
582 				break;
583 			}
584 		}
585 		switch_safe_free(hi);
586 
587 		if (is_online) {
588 			resume_inbound_calling();
589 		} else {
590 			pause_inbound_calling();
591 		}
592 
593 		switch_mutex_unlock(globals.clients_mutex);
594 	}
595 }
596 
597 /**
598  * Send event to clients
599  * @param from event sender
600  * @param rayo_event the event to send
601  * @param online_only only send to online clients
602  */
broadcast_event(struct rayo_actor * from,iks * rayo_event,int online_only)603 static void broadcast_event(struct rayo_actor *from, iks *rayo_event, int online_only)
604 {
605 	switch_hash_index_t *hi = NULL;
606 	switch_mutex_lock(globals.clients_mutex);
607 	for (hi = switch_core_hash_first(globals.clients_roster); hi; hi = switch_core_hash_next(&hi)) {
608 		struct rayo_client *rclient;
609 		const void *key;
610 		void *val;
611 		switch_core_hash_this(hi, &key, NULL, &val);
612 		rclient = (struct rayo_client *)val;
613 		switch_assert(rclient);
614 
615 		if (!online_only || rclient->availability == PS_ONLINE) {
616 			iks_insert_attrib(rayo_event, "to", RAYO_JID(rclient));
617 			RAYO_SEND_MESSAGE_DUP(from, RAYO_JID(rclient), rayo_event);
618 		}
619 	}
620 	switch_mutex_unlock(globals.clients_mutex);
621 }
622 
623 /**
624  * Add an outbound dialing gateway
625  * @param uri_prefix to match
626  * @param dial_prefix to use
627  * @param strip number of digits to strip from dialstring
628  */
dial_gateway_add(const char * uri_prefix,const char * dial_prefix,int strip)629 static void dial_gateway_add(const char *uri_prefix, const char *dial_prefix, int strip)
630 {
631 	struct dial_gateway *gateway = switch_core_alloc(globals.pool, sizeof(*gateway));
632 	gateway->uri_prefix = uri_prefix ? switch_core_strdup(globals.pool, uri_prefix) : "";
633 	gateway->dial_prefix = dial_prefix ? switch_core_strdup(globals.pool, dial_prefix) : "";
634 	gateway->strip = strip > 0 ? strip : 0;
635 	switch_core_hash_insert(globals.dial_gateways, uri_prefix, gateway);
636 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "dial-gateway uriprefix = %s, dialprefix = %s, strip = %i\n", uri_prefix, dial_prefix, strip);
637 }
638 
639 /**
640  * Find outbound dial gateway for the specified dialstring
641  */
dial_gateway_find(const char * uri)642 static struct dial_gateway *dial_gateway_find(const char *uri)
643 {
644 	switch_hash_index_t *hi = NULL;
645 	int match_len = 0;
646 	struct dial_gateway *gateway = (struct dial_gateway *)switch_core_hash_find(globals.dial_gateways, "default");
647 
648 	/* find longest prefix match */
649 	switch_mutex_lock(globals.dial_gateways_mutex);
650 	for (hi = switch_core_hash_first(globals.dial_gateways); hi; hi = switch_core_hash_next(&hi)) {
651 		struct dial_gateway *candidate = NULL;
652 		const void *prefix;
653 		int prefix_len = 0;
654 		void *val;
655 		switch_core_hash_this(hi, &prefix, NULL, &val);
656 		candidate = (struct dial_gateway *)val;
657 		switch_assert(candidate);
658 
659 		prefix_len = strlen(prefix);
660 		if (!zstr(prefix) && !strncmp(prefix, uri, prefix_len) && prefix_len > match_len) {
661 			match_len = prefix_len;
662 			gateway = candidate;
663 		}
664 	}
665 	switch_mutex_unlock(globals.dial_gateways_mutex);
666 	return gateway;
667 }
668 
669 /**
670  * Add command handler function
671  * @param name the command name
672  * @param handler the command handler function
673  */
rayo_command_handler_add(const char * name,struct rayo_xmpp_handler * handler)674 static void rayo_command_handler_add(const char *name, struct rayo_xmpp_handler *handler)
675 {
676 	char full_name[1024];
677 	full_name[1023] = '\0';
678 	snprintf(full_name, sizeof(full_name) - 1, "%s:%s:%s", handler->to_type, handler->to_subtype, name);
679 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding command: %s\n", full_name);
680 	switch_core_hash_insert(globals.command_handlers, full_name, handler);
681 }
682 
683 /**
684  * Add command handler function
685  * @param type the actor type
686  * @param subtype the actor subtype
687  * @param name the command name
688  * @param fn the command callback function
689  */
rayo_actor_command_handler_add(const char * type,const char * subtype,const char * name,rayo_actor_xmpp_handler fn)690 void rayo_actor_command_handler_add(const char *type, const char *subtype, const char *name, rayo_actor_xmpp_handler fn)
691 {
692 	struct rayo_xmpp_handler *handler = switch_core_alloc(globals.pool, sizeof (*handler));
693 	handler->to_type = zstr(type) ? "" : switch_core_strdup(globals.pool, type);
694 	handler->to_subtype = zstr(subtype) ? "" : switch_core_strdup(globals.pool, subtype);
695 	handler->fn = fn;
696 	rayo_command_handler_add(name, handler);
697 }
698 
699 /**
700  * Get command handler function from hash
701  * @param hash the hash to search
702  * @param msg the command
703  * @return the command handler function or NULL
704  */
rayo_actor_command_handler_find(struct rayo_actor * actor,struct rayo_message * msg)705 rayo_actor_xmpp_handler rayo_actor_command_handler_find(struct rayo_actor *actor, struct rayo_message *msg)
706 {
707 	iks *iq = msg->payload;
708 	const char *iq_type = iks_find_attrib_soft(iq, "type");
709 	iks *command = iks_first_tag(iq);
710 	const char *name = "";
711 	const char *namespace = "";
712 	struct rayo_xmpp_handler *handler = NULL;
713 	char full_name[1024];
714 
715 	full_name[1023] = '\0';
716 	if (command) {
717 		name = iks_name(command);
718 		namespace = iks_find_attrib_soft(command, "xmlns");
719 		if (zstr(name)) {
720 			name = "";
721 		}
722 	}
723 
724 	snprintf(full_name, sizeof(full_name) - 1, "%s:%s:%s:%s:%s", actor->type, actor->subtype, iq_type, namespace, name);
725 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, looking for %s command\n", RAYO_JID(actor), full_name);
726 	handler = (struct rayo_xmpp_handler *)switch_core_hash_find(globals.command_handlers, full_name);
727 	if (handler) {
728 		return handler->fn;
729 	}
730 
731 	return NULL;
732 }
733 
734 /**
735  * Add event handler function
736  * @param name the event name
737  * @param handler the event handler function
738  */
rayo_event_handler_add(const char * name,struct rayo_xmpp_handler * handler)739 static void rayo_event_handler_add(const char *name, struct rayo_xmpp_handler *handler)
740 {
741 	char full_name[1024];
742 	full_name[1023] = '\0';
743 	snprintf(full_name, sizeof(full_name) - 1, "%s:%s:%s:%s:%s", handler->from_type, handler->from_subtype, handler->to_type, handler->to_subtype, name);
744 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding event: %s\n", full_name);
745 	switch_core_hash_insert(globals.event_handlers, full_name, handler);
746 }
747 
748 /**
749  * Add event handler function
750  * @param from_type the source actor type
751  * @param from_subtype the source actor subtype
752  * @param to_type the destination actor type
753  * @param to_subtype the destination actor subtype
754  * @param name the event name
755  * @param fn the event callback function
756  */
rayo_actor_event_handler_add(const char * from_type,const char * from_subtype,const char * to_type,const char * to_subtype,const char * name,rayo_actor_xmpp_handler fn)757 void rayo_actor_event_handler_add(const char *from_type, const char *from_subtype, const char *to_type, const char *to_subtype, const char *name, rayo_actor_xmpp_handler fn)
758 {
759 	struct rayo_xmpp_handler *handler = switch_core_alloc(globals.pool, sizeof (*handler));
760 	handler->from_type = zstr(from_type) ? "" : switch_core_strdup(globals.pool, from_type);
761 	handler->from_subtype = zstr(from_subtype) ? "" : switch_core_strdup(globals.pool, from_subtype);
762 	handler->to_type = zstr(to_type) ? "" : switch_core_strdup(globals.pool, to_type);
763 	handler->to_subtype = zstr(to_subtype) ? "" : switch_core_strdup(globals.pool, to_subtype);
764 	handler->fn = fn;
765 	rayo_event_handler_add(name, handler);
766 }
767 
768 /**
769  * Get event handler function from hash
770  * @param actor the event destination
771  * @param msg the event
772  * @return the event handler function or NULL
773  */
rayo_actor_event_handler_find(struct rayo_actor * actor,struct rayo_message * msg)774 rayo_actor_xmpp_handler rayo_actor_event_handler_find(struct rayo_actor *actor, struct rayo_message *msg)
775 {
776 	iks *presence = msg->payload;
777 	iks *event = iks_first_tag(presence);
778 	if (event) {
779 		struct rayo_xmpp_handler *handler = NULL;
780 		const char *presence_type = iks_find_attrib_soft(presence, "type");
781 		const char *event_name = iks_name(event);
782 		const char *event_namespace = iks_find_attrib_soft(event, "xmlns");
783 		char full_name[1024];
784 		full_name[1023] = '\0';
785 		if (zstr(event_name)) {
786 			return NULL;
787 		}
788 		snprintf(full_name, sizeof(full_name) - 1, "%s:%s:%s:%s:%s:%s:%s", msg->from_type, msg->from_subtype, actor->type, actor->subtype, presence_type, event_namespace, event_name);
789 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s => %s, looking for %s event handler\n", msg->from_jid, RAYO_JID(actor), full_name);
790 		handler = (struct rayo_xmpp_handler *)switch_core_hash_find(globals.event_handlers, full_name);
791 		if (handler) {
792 			return handler->fn;
793 		}
794 	} else {
795 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s => %s, event missing child element\n", msg->from_jid, RAYO_JID(actor));
796 	}
797 	return NULL;
798 }
799 
800 /**
801  * Clean up a message
802  * @param msg to destroy
803  */
rayo_message_destroy(struct rayo_message * msg)804 void rayo_message_destroy(struct rayo_message *msg)
805 {
806 	if (msg) {
807 		if (msg->payload) {
808 			iks_delete(msg->payload);
809 		}
810 		switch_safe_free(msg->to_jid);
811 		switch_safe_free(msg->from_jid);
812 		switch_safe_free(msg->from_type);
813 		switch_safe_free(msg->from_subtype);
814 		switch_safe_free(msg->file);
815 		free(msg);
816 	}
817 }
818 
819 /**
820  * Remove payload from message
821  */
rayo_message_remove_payload(struct rayo_message * msg)822 iks *rayo_message_remove_payload(struct rayo_message *msg)
823 {
824 	iks *payload = msg->payload;
825 	msg->payload = NULL;
826 	msg->from = NULL;
827 	msg->to = NULL;
828 	return payload;
829 }
830 
831 /**
832  * Thread that delivers internal XMPP messages
833  * @param thread this thread
834  * @param obj unused
835  * @return NULL
836  */
deliver_message_thread(switch_thread_t * thread,void * obj)837 static void *SWITCH_THREAD_FUNC deliver_message_thread(switch_thread_t *thread, void *obj)
838 {
839 	struct rayo_message *msg = NULL;
840 	switch_thread_rwlock_rdlock(globals.shutdown_rwlock);
841 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "New message delivery thread\n");
842 	while (!globals.shutdown) {
843 		if (switch_queue_pop(globals.msg_queue, (void *)&msg) == SWITCH_STATUS_SUCCESS) {
844 			struct rayo_actor *actor = RAYO_LOCATE(msg->to_jid);
845 			if (actor) {
846 				/* deliver to actor */
847 				switch_mutex_lock(actor->mutex);
848 				switch_log_printf(SWITCH_CHANNEL_ID_LOG, msg->file, "", msg->line, "", SWITCH_LOG_DEBUG, "Deliver %s => %s %s\n", msg->from_jid, msg->to_jid, iks_string(iks_stack(msg->payload), msg->payload));
849 				actor->send_fn(actor, msg);
850 				switch_mutex_unlock(actor->mutex);
851 				RAYO_RELEASE(actor);
852 			} else if (!msg->is_reply) {
853 				/* unknown actor */
854 				RAYO_SEND_REPLY(globals.server, msg->from_jid, iks_new_error(msg->payload, STANZA_ERROR_ITEM_NOT_FOUND));
855 			}
856 			rayo_message_destroy(msg);
857 		}
858 	}
859 
860 	/* clean up remaining messages */
861 	while(switch_queue_trypop(globals.msg_queue, (void *)&msg) == SWITCH_STATUS_SUCCESS) {
862 		rayo_message_destroy(msg);
863 	}
864 
865 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Message delivery thread finished\n");
866 	switch_thread_rwlock_unlock(globals.shutdown_rwlock);
867 	return NULL;
868 }
869 
870 /**
871  * Create a new message thread
872  * @param pool to use
873  */
start_deliver_message_thread(switch_memory_pool_t * pool)874 static void start_deliver_message_thread(switch_memory_pool_t *pool)
875 {
876 	switch_thread_t *thread;
877 	switch_threadattr_t *thd_attr = NULL;
878 	switch_threadattr_create(&thd_attr, pool);
879 	switch_threadattr_detach_set(thd_attr, 1);
880 	switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
881 	switch_thread_create(&thread, thd_attr, deliver_message_thread, NULL, pool);
882 }
883 
884 /**
885  * Stop all threads
886  */
stop_all_threads(void)887 static void stop_all_threads(void)
888 {
889 	globals.shutdown = 1;
890 	if (globals.msg_queue) {
891 		switch_queue_interrupt_all(globals.msg_queue);
892 	}
893 	if (globals.offer_queue) {
894 		switch_queue_interrupt_all(globals.offer_queue);
895 	}
896 	if (globals.shutdown_rwlock) {
897 		switch_thread_rwlock_wrlock(globals.shutdown_rwlock);
898 	}
899 }
900 
901 /**
902  * Send message to actor addressed by JID
903  * @param from actor sending the message
904  * @param to destination JID
905  * @param payload the message payload to deliver
906  * @param dup true if payload is to be copied
907  * @param reply true if a reply
908  * @param file file name
909  * @param line line number
910  */
rayo_message_send(struct rayo_actor * from,const char * to,iks * payload,int dup,int reply,const char * file,int line)911 void rayo_message_send(struct rayo_actor *from, const char *to, iks *payload, int dup, int reply, const char *file, int line)
912 {
913 	const char *msg_name;
914 	struct rayo_message *msg = malloc(sizeof(*msg));
915 	switch_assert(msg);
916 	if (dup) {
917 		msg->payload = iks_copy(payload);
918 	} else {
919 		msg->payload = payload;
920 	}
921 	msg->is_reply = reply;
922 	msg->to_jid = strdup(zstr(to) ? "" : to);
923 	if (!zstr(msg->to_jid)) {
924 		msg->to = iks_id_new(iks_stack(msg->payload), msg->to_jid);
925 	}
926 	msg->from_jid = strdup(RAYO_JID(from));
927 	if (!zstr(msg->from_jid)) {
928 		msg->from = iks_id_new(iks_stack(msg->payload), msg->from_jid);
929 	}
930 	msg->from_type = strdup(zstr(from->type) ? "" : from->type);
931 	msg->from_subtype = strdup(zstr(from->subtype) ? "" : from->subtype);
932 	msg->file = strdup(file);
933 	msg->line = line;
934 
935 	/* add timestamp to presence events */
936 	msg_name = iks_name(msg->payload);
937 	if (!zstr(msg_name) && !strcmp("presence", msg_name)) {
938 		/* don't add timestamp if there already is one */
939 		iks *delay = iks_find(msg->payload, "delay");
940 		if (!delay || strcmp("urn:xmpp:delay", iks_find_attrib_soft(delay, "xmlns"))) {
941 			switch_time_exp_t tm;
942 			char timestamp[80];
943 			switch_size_t retsize;
944 			delay = iks_insert(msg->payload, "delay");
945 			iks_insert_attrib(delay, "xmlns", "urn:xmpp:delay");
946 			switch_time_exp_tz(&tm, switch_time_now(), 0);
947 			switch_strftime_nocheck(timestamp, &retsize, sizeof(timestamp), "%Y-%m-%dT%TZ", &tm);
948 			iks_insert_attrib_printf(delay, "stamp", "%s", timestamp);
949 		}
950 	}
951 
952 	if (switch_queue_trypush(globals.msg_queue, msg) != SWITCH_STATUS_SUCCESS) {
953 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "failed to queue message!\n");
954 		rayo_message_destroy(msg);
955 	}
956 }
957 
958 /**
959  * Get access to Rayo actor with JID.
960  * @param jid the JID
961  * @return the actor or NULL.  Call RAYO_RELEASE() when done with pointer.
962  */
rayo_actor_locate(const char * jid,const char * file,int line)963 struct rayo_actor *rayo_actor_locate(const char *jid, const char *file, int line)
964 {
965 	struct rayo_actor *actor = NULL;
966 	switch_mutex_lock(globals.actors_mutex);
967 	if (!strncmp("xmpp:", jid, 5)) {
968 		jid = jid + 5;
969 	}
970 	actor = (struct rayo_actor *)switch_core_hash_find(globals.actors, jid);
971 	if (actor) {
972 		if (!actor->destroy) {
973 			actor->ref_count++;
974 			switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, "", SWITCH_LOG_DEBUG, "Locate (jid) %s: ref count = %i\n", RAYO_JID(actor), actor->ref_count);
975 		} else {
976 			switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, "", SWITCH_LOG_WARNING, "Locate (jid) %s: already marked for destruction!\n", jid);
977 			actor = NULL;
978 		}
979 	}
980 	switch_mutex_unlock(globals.actors_mutex);
981 	return actor;
982 }
983 
984 /**
985  * Get exclusive access to Rayo actor with internal ID
986  * @param id the internal ID
987  * @return the actor or NULL.  Call RAYO_RELEASE() when done with pointer.
988  */
rayo_actor_locate_by_id(const char * id,const char * file,int line)989 struct rayo_actor *rayo_actor_locate_by_id(const char *id, const char *file, int line)
990 {
991 	struct rayo_actor *actor = NULL;
992 	if (!zstr(id)) {
993 		switch_mutex_lock(globals.actors_mutex);
994 		actor = (struct rayo_actor *)switch_core_hash_find(globals.actors_by_id, id);
995 		if (actor) {
996 			if (!actor->destroy) {
997 				actor->ref_count++;
998 				switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, "", SWITCH_LOG_DEBUG, "Locate (id) %s: ref count = %i\n", RAYO_JID(actor), actor->ref_count);
999 			} else {
1000 				switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, "", SWITCH_LOG_WARNING, "Locate (id) %s: already marked for destruction!\n", id);
1001 				actor = NULL;
1002 			}
1003 		}
1004 		switch_mutex_unlock(globals.actors_mutex);
1005 	}
1006 	return actor;
1007 }
1008 
1009 /**
1010  * Destroy a rayo actor
1011  */
rayo_actor_destroy(struct rayo_actor * actor,const char * file,int line)1012 void rayo_actor_destroy(struct rayo_actor *actor, const char *file, int line)
1013 {
1014 	switch_memory_pool_t *pool = actor->pool;
1015 	switch_mutex_lock(globals.actors_mutex);
1016 	if (!actor->destroy) {
1017 		switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, "", SWITCH_LOG_DEBUG, "Destroy %s requested: ref_count = %i\n", RAYO_JID(actor), actor->ref_count);
1018 		switch_core_hash_delete(globals.actors, RAYO_JID(actor));
1019 		if (!zstr(actor->id)) {
1020 			switch_core_hash_delete(globals.actors_by_id, actor->id);
1021 		}
1022 	}
1023 	actor->destroy = 1;
1024 	if (actor->ref_count <= 0) {
1025 		if (actor->ref_count < 0) {
1026 			/* too many unlocks detected! */
1027 			switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, "", SWITCH_LOG_WARNING, "Destroying %s, ref_count = %i\n", RAYO_JID(actor), actor->ref_count);
1028 		} else {
1029 			switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, "", SWITCH_LOG_DEBUG, "Destroying %s\n", RAYO_JID(actor));
1030 		}
1031 		switch_core_hash_delete(globals.destroy_actors, RAYO_JID(actor));
1032 		switch_mutex_unlock(globals.actors_mutex);
1033 		/* safe to destroy parent now */
1034 		if (actor->cleanup_fn) {
1035 			actor->cleanup_fn(actor);
1036 		}
1037 		if (actor->parent) {
1038 			RAYO_RELEASE(actor->parent);
1039 		}
1040 		switch_core_destroy_memory_pool(&pool);
1041 	} else {
1042 		switch_core_hash_insert(globals.destroy_actors, RAYO_JID(actor), actor);
1043 		switch_mutex_unlock(globals.actors_mutex);
1044 	}
1045 }
1046 
1047 /**
1048  * Increment actor ref count - locks from destruction.
1049  */
rayo_actor_retain(struct rayo_actor * actor,const char * file,int line)1050 void rayo_actor_retain(struct rayo_actor *actor, const char *file, int line)
1051 {
1052 	if (actor) {
1053 		switch_mutex_lock(globals.actors_mutex);
1054 		actor->ref_count++;
1055 		switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, "", SWITCH_LOG_DEBUG, "Lock %s: ref count = %i\n", RAYO_JID(actor), actor->ref_count);
1056 		switch_mutex_unlock(globals.actors_mutex);
1057 	}
1058 }
1059 
1060 /**
1061  * Release rayo actor reference
1062  */
rayo_actor_release(struct rayo_actor * actor,const char * file,int line)1063 void rayo_actor_release(struct rayo_actor *actor, const char *file, int line)
1064 {
1065 	if (actor) {
1066 		switch_mutex_lock(globals.actors_mutex);
1067 		actor->ref_count--;
1068 		if (actor->ref_count < 0) {
1069 			/* too many unlocks detected! */
1070 			switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, "", SWITCH_LOG_WARNING, "Release %s: ref count = %i\n", RAYO_JID(actor), actor->ref_count);
1071 		} else {
1072 			switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, "", SWITCH_LOG_DEBUG, "Release %s: ref count = %i\n", RAYO_JID(actor), actor->ref_count);
1073 		}
1074 		if (actor->ref_count <= 0 && actor->destroy) {
1075 			rayo_actor_destroy(actor, file, line);
1076 		}
1077 		switch_mutex_unlock(globals.actors_mutex);
1078 	}
1079 }
1080 
1081 /**
1082  * Get next number in sequence
1083  */
rayo_actor_seq_next(struct rayo_actor * actor)1084 int rayo_actor_seq_next(struct rayo_actor *actor)
1085 {
1086 	int seq;
1087 	switch_mutex_lock(actor->mutex);
1088 	seq = actor->seq++;
1089 	switch_mutex_unlock(actor->mutex);
1090 	return seq;
1091 }
1092 
1093 #define RAYO_CALL_LOCATE(call_uri) rayo_call_locate(call_uri, __FILE__, __LINE__)
1094 /**
1095  * Get access to Rayo call data.  Use to access call data outside channel thread.
1096  * @param call_uri the Rayo XMPP URI
1097  * @return the call or NULL.
1098  */
rayo_call_locate(const char * call_uri,const char * file,int line)1099 static struct rayo_call *rayo_call_locate(const char *call_uri, const char *file, int line)
1100 {
1101 	struct rayo_actor *actor = rayo_actor_locate(call_uri, file, line);
1102 	if (actor && is_call_actor(actor)) {
1103 		return RAYO_CALL(actor);
1104 	} else if (actor) {
1105 		RAYO_RELEASE(actor);
1106 	}
1107 	return NULL;
1108 }
1109 
1110 #define RAYO_CALL_LOCATE_BY_ID(call_uuid) rayo_call_locate_by_id(call_uuid, __FILE__, __LINE__)
1111 /**
1112  * Get access to Rayo call data.  Use to access call data outside channel thread.
1113  * @param call_uuid the FreeSWITCH call UUID
1114  * @return the call or NULL.
1115  */
rayo_call_locate_by_id(const char * call_uuid,const char * file,int line)1116 static struct rayo_call *rayo_call_locate_by_id(const char *call_uuid, const char *file, int line)
1117 {
1118 	struct rayo_actor *actor = rayo_actor_locate_by_id(call_uuid, file, line);
1119 	if (actor && is_call_actor(actor)) {
1120 		return RAYO_CALL(actor);
1121 	} else if (actor) {
1122 		RAYO_RELEASE(actor);
1123 	}
1124 	return NULL;
1125 }
1126 
1127 /**
1128  * Send <end> event to DCP and PCPs
1129  */
rayo_call_send_end(struct rayo_call * call,switch_event_t * event,int local_hangup,const char * cause_str,const char * cause_q850_str)1130 static void rayo_call_send_end(struct rayo_call *call, switch_event_t *event, int local_hangup, const char *cause_str, const char *cause_q850_str)
1131 {
1132 	int no_offered_clients = 1;
1133 	switch_hash_index_t *hi = NULL;
1134 	iks *revent;
1135 	iks *end;
1136 	const char *dcp_jid = rayo_call_get_dcp_jid(call);
1137 
1138 	/* build call end event */
1139 	revent = iks_new_presence("end", RAYO_NS, RAYO_JID(call), "foo");
1140 	iks_insert_attrib(revent, "type", "unavailable");
1141 	end = iks_find(revent, "end");
1142 
1143 	if (local_hangup) {
1144 		iks_insert(end, RAYO_END_REASON_HANGUP_LOCAL);
1145 	} else {
1146 		/* remote hangup... translate to specific rayo reason */
1147 		iks *reason;
1148 		switch_call_cause_t cause = SWITCH_CAUSE_NONE;
1149 		if (!zstr(cause_str)) {
1150 			cause = switch_channel_str2cause(cause_str);
1151 		}
1152 		reason = iks_insert(end, switch_cause_to_rayo_cause(cause));
1153 		if (!zstr(cause_q850_str)) {
1154 			iks_insert_attrib(reason, "platform-code", cause_q850_str);
1155 		}
1156 	}
1157 
1158 	#if 0
1159 	if (event) {
1160 		char *event_str;
1161 		if (switch_event_serialize(event, &event_str, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
1162 			switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_DEBUG, "%s\n", event_str);
1163 			switch_safe_free(event_str);
1164 		}
1165 	}
1166 	#endif
1167 
1168 	/* add signaling headers */
1169 	if (event) {
1170 		add_headers_to_event(end, event, globals.add_variables_to_events);
1171 	}
1172 
1173 	/* send <end> to all offered clients */
1174 	for (hi = switch_core_hash_first(call->pcps); hi; hi = switch_core_hash_next(&hi)) {
1175 		const void *key;
1176 		void *val;
1177 		const char *client_jid = NULL;
1178 		switch_core_hash_this(hi, &key, NULL, &val);
1179 		client_jid = (const char *)key;
1180 		switch_assert(client_jid);
1181 		iks_insert_attrib(revent, "to", client_jid);
1182 		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_DEBUG, "Sending <end> to offered client %s\n", client_jid);
1183 		RAYO_SEND_MESSAGE_DUP(call, client_jid, revent);
1184 		no_offered_clients = 0;
1185 	}
1186 
1187 	if (no_offered_clients && !zstr(dcp_jid)) {
1188 		/* send to DCP only */
1189 		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_DEBUG, "Sending <end> to DCP %s\n", dcp_jid);
1190 		iks_insert_attrib(revent, "to", dcp_jid);
1191 		RAYO_SEND_MESSAGE_DUP(call, dcp_jid, revent);
1192 	}
1193 
1194 	iks_delete(revent);
1195 }
1196 
1197 /**
1198  * Fire <end> event when call is cleaned up completely
1199  */
rayo_call_cleanup(struct rayo_actor * actor)1200 static void rayo_call_cleanup(struct rayo_actor *actor)
1201 {
1202 	struct rayo_call *call = RAYO_CALL(actor);
1203 	switch_event_t *event = call->end_event;
1204 	const char *dcp_jid = rayo_call_get_dcp_jid(call);
1205 
1206 	if (!event || call->dial_request_failed) {
1207 		/* destroyed before FS session was created (in originate, for example) */
1208 		goto done;
1209 	}
1210 
1211 	/* send call unjoined event, if not already sent */
1212 	if (call->joined && call->joined_id) {
1213 		if (!zstr(dcp_jid)) {
1214 			iks *unjoined;
1215 			iks *uevent = iks_new_presence("unjoined", RAYO_NS, RAYO_JID(call), dcp_jid);
1216 			unjoined = iks_find(uevent, "unjoined");
1217 			iks_insert_attrib_printf(unjoined, "call-uri", "%s", call->joined_id);
1218 			RAYO_SEND_MESSAGE(call, dcp_jid, uevent);
1219 		}
1220 	}
1221 
1222 	rayo_call_send_end(call,
1223 		event,
1224 		switch_true(switch_event_get_header(event, "variable_rayo_local_hangup")),
1225 		switch_event_get_header(event, "variable_hangup_cause"),
1226 		switch_event_get_header(event, "variable_hangup_cause_q850"));
1227 
1228 done:
1229 
1230 	/* lost the race: pending join failed... send IQ result to client now. */
1231 	if (call->pending_join_request) {
1232 		iks *request = call->pending_join_request;
1233 		iks *result = iks_new_error_detailed(request, STANZA_ERROR_ITEM_NOT_FOUND, "call ended");
1234 		call->pending_join_request = NULL;
1235 		RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
1236 		iks_delete(call->pending_join_request);
1237 	}
1238 
1239 	if (event) {
1240 		switch_event_destroy(&event);
1241 	}
1242 	if (call->answer_event) {
1243 		switch_event_destroy(&call->answer_event);
1244 	}
1245 	switch_core_hash_destroy(&call->pcps);
1246 	switch_core_hash_destroy(&call->acps);
1247 }
1248 
1249 /**
1250  * @param call the Rayo call
1251  * @return the Rayo call DCP JID
1252  */
rayo_call_get_dcp_jid(struct rayo_call * call)1253 const char *rayo_call_get_dcp_jid(struct rayo_call *call)
1254 {
1255 	return call->dcp_jid;
1256 }
1257 
1258 /**
1259  * @param call the Rayo call
1260  * @return true if joined (or a join is in progress)
1261  */
rayo_call_is_joined(struct rayo_call * call)1262 int rayo_call_is_joined(struct rayo_call *call)
1263 {
1264 	return call->joined || call->pending_join_request;
1265 }
1266 
1267 /**
1268  * @param call to check if faxing
1269  * @return true if faxing is in progress
1270  */
rayo_call_is_faxing(struct rayo_call * call)1271 int rayo_call_is_faxing(struct rayo_call *call)
1272 {
1273 	return call->faxing;
1274 }
1275 
1276 /**
1277  * Set faxing flag
1278  * @param call the call to flag
1279  * @param faxing true if faxing is in progress
1280  */
rayo_call_set_faxing(struct rayo_call * call,int faxing)1281 void rayo_call_set_faxing(struct rayo_call *call, int faxing)
1282 {
1283 	call->faxing = faxing;
1284 }
1285 
1286 #define RAYO_MIXER_LOCATE(mixer_name) rayo_mixer_locate(mixer_name, __FILE__, __LINE__)
1287 /**
1288  * Get access to Rayo mixer data.
1289  * @param mixer_name the mixer name
1290  * @return the mixer or NULL. Call RAYO_RELEASE() when done with mixer pointer.
1291  */
rayo_mixer_locate(const char * mixer_name,const char * file,int line)1292 static struct rayo_mixer *rayo_mixer_locate(const char *mixer_name, const char *file, int line)
1293 {
1294 	struct rayo_actor *actor = rayo_actor_locate_by_id(mixer_name, file, line);
1295 	if (actor && !strcmp(RAT_MIXER, actor->type)) {
1296 		return RAYO_MIXER(actor);
1297 	} else if (actor) {
1298 		RAYO_RELEASE(actor);
1299 	}
1300 	return NULL;
1301 }
1302 
1303 /**
1304  * Default message handler - drops messages
1305  */
rayo_actor_send_ignore(struct rayo_actor * to,struct rayo_message * msg)1306 void rayo_actor_send_ignore(struct rayo_actor *to, struct rayo_message *msg)
1307 {
1308 	switch_log_printf(SWITCH_CHANNEL_ID_LOG, msg->file, "", msg->line, "", SWITCH_LOG_WARNING, "%s, dropping unexpected message to %s.\n", msg->from_jid, RAYO_JID(to));
1309 }
1310 
1311 #define RAYO_ACTOR_INIT(actor, pool, type, subtype, id, jid, cleanup, send) rayo_actor_init(actor, pool, type, subtype, id, jid, cleanup, send, NULL, __FILE__, __LINE__)
1312 #define RAYO_ACTOR_INIT_PARENT(actor, pool, type, subtype, id, jid, cleanup, send, parent) rayo_actor_init(actor, pool, type, subtype, id, jid, cleanup, send, parent, __FILE__, __LINE__)
1313 
1314 /**
1315  * Initialize a rayo actor
1316  * @param actor to initialize
1317  * @param pool to use
1318  * @param type of actor (MIXER, CALL, SERVER, COMPONENT)
1319  * @param subtype of actor (input/output/prompt)
1320  * @param id internal ID
1321  * @param jid external ID
1322  * @param cleanup function
1323  * @param send sent message handler
1324  * @param parent of actor
1325  * @param file that called this function
1326  * @param line that called this function
1327  * @return the actor or NULL if JID conflict
1328  */
rayo_actor_init(struct rayo_actor * actor,switch_memory_pool_t * pool,const char * type,const char * subtype,const char * id,const char * jid,rayo_actor_cleanup_fn cleanup,rayo_actor_send_fn send,struct rayo_actor * parent,const char * file,int line)1329 static struct rayo_actor *rayo_actor_init(struct rayo_actor *actor, switch_memory_pool_t *pool, const char *type, const char *subtype, const char *id, const char *jid, rayo_actor_cleanup_fn cleanup, rayo_actor_send_fn send, struct rayo_actor *parent, const char *file, int line)
1330 {
1331 	char *domain;
1332 	actor->type = switch_core_strdup(pool, type);
1333 	actor->subtype = switch_core_strdup(pool, subtype);
1334 	actor->pool = pool;
1335 	if (!zstr(id)) {
1336 		actor->id = switch_core_strdup(pool, id);
1337 	}
1338 	/* TODO validate JID with regex */
1339 	if (!zstr(jid)) {
1340 		RAYO_JID(actor) = switch_core_strdup(pool, jid);
1341 		if (!(domain = strrchr(RAYO_JID(actor), '@'))) {
1342 			RAYO_DOMAIN(actor) = RAYO_JID(actor);
1343 		} else if (!zstr(++domain)) {
1344 			RAYO_DOMAIN(actor) = switch_core_strdup(pool, domain);
1345 			/* strip resource from domain if it exists */
1346 			domain = strrchr(RAYO_DOMAIN(actor), '/');
1347 			if (domain) {
1348 				*domain = '\0';
1349 			}
1350 		}
1351 	}
1352 	actor->seq = 1;
1353 	actor->ref_count = 1;
1354 	actor->destroy = 0;
1355 	actor->cleanup_fn = cleanup;
1356 	if (send == NULL) {
1357 		actor->send_fn = rayo_actor_send_ignore;
1358 	} else {
1359 		actor->send_fn = send;
1360 	}
1361 
1362 	actor->parent = parent;
1363 	if (!actor->parent) {
1364 		switch_mutex_init(&actor->mutex, SWITCH_MUTEX_NESTED, pool);
1365 	} else {
1366 		/* inherit mutex from parent */
1367 		actor->mutex = actor->parent->mutex;
1368 
1369 		/* prevent parent destruction */
1370 		RAYO_RETAIN(actor->parent);
1371 	}
1372 
1373 	/* add to hash of actors, so commands can route to call */
1374 	switch_mutex_lock(globals.actors_mutex);
1375 	if (!zstr(jid)) {
1376 		if (switch_core_hash_find(globals.actors, RAYO_JID(actor))) {
1377 			/* duplicate JID, give up! */
1378 			switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, "", SWITCH_LOG_NOTICE, "JID conflict! %s\n", RAYO_JID(actor));
1379 			switch_mutex_unlock(globals.actors_mutex);
1380 			if (actor->parent) {
1381 				/* unlink from parent */
1382 				RAYO_RELEASE(actor->parent);
1383 				actor->parent = NULL;
1384 			}
1385 			return NULL;
1386 		}
1387 		switch_core_hash_insert(globals.actors, RAYO_JID(actor), actor);
1388 	}
1389 	if (!zstr(id)) {
1390 		if (switch_core_hash_find(globals.actors_by_id, actor->id)) {
1391 			/* duplicate ID - only log for now... */
1392 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "ID conflict! %s\n", actor->id);
1393 		}
1394 		switch_core_hash_insert(globals.actors_by_id, actor->id, actor);
1395 	}
1396 	switch_mutex_unlock(globals.actors_mutex);
1397 
1398 	switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, "", SWITCH_LOG_DEBUG, "Init %s\n", RAYO_JID(actor));
1399 
1400 	return actor;
1401 }
1402 
1403 /**
1404  * Initialize rayo call
1405  * @return the call or NULL if JID conflict
1406  */
rayo_call_init(struct rayo_call * call,switch_memory_pool_t * pool,const char * uuid,const char * file,int line)1407 static struct rayo_call *rayo_call_init(struct rayo_call *call, switch_memory_pool_t *pool, const char *uuid, const char *file, int line)
1408 {
1409 	char *call_jid;
1410 	char uuid_id_buf[SWITCH_UUID_FORMATTED_LENGTH + 1];
1411 
1412 	if (zstr(uuid)) {
1413 		switch_uuid_str(uuid_id_buf, sizeof(uuid_id_buf));
1414 		uuid = uuid_id_buf;
1415 	}
1416 	call_jid = switch_mprintf("%s@%s", uuid, RAYO_JID(globals.server));
1417 
1418 	call = RAYO_CALL(rayo_actor_init(RAYO_ACTOR(call), pool, RAT_CALL, "", uuid, call_jid, rayo_call_cleanup, rayo_call_send, NULL, file, line));
1419 	if (call) {
1420 		call->dcp_jid = "";
1421 		call->idle_start_time = switch_micro_time_now();
1422 		call->joined = 0;
1423 		call->joined_id = NULL;
1424 		call->ringing_sent = 0;
1425 		call->pending_join_request = NULL;
1426 		call->dial_request_id = NULL;
1427 		call->end_event = NULL;
1428 		call->dial_request_failed = 0;
1429 		call->rayo_app_started = 0;
1430 		call->answer_event = NULL;
1431 		switch_core_hash_init(&call->pcps);
1432 		switch_core_hash_init(&call->acps);
1433 		call->num_acps = 0;
1434 	}
1435 
1436 	switch_safe_free(call_jid);
1437 
1438 	return call;
1439 }
1440 
1441 #define rayo_call_create(uuid) _rayo_call_create(uuid, __FILE__, __LINE__)
1442 /**
1443  * Create Rayo call
1444  * @param uuid uuid to assign call, if NULL one is picked
1445  * @param file file that called this function
1446  * @param line number of file that called this function
1447  * @return the call, or NULL if JID conflict
1448  */
_rayo_call_create(const char * uuid,const char * file,int line)1449 static struct rayo_call *_rayo_call_create(const char *uuid, const char *file, int line)
1450 {
1451 	switch_memory_pool_t *pool;
1452 	struct rayo_call *call;
1453 	switch_core_new_memory_pool(&pool);
1454 	call = switch_core_alloc(pool, sizeof(*call));
1455 	call = rayo_call_init(call, pool, uuid, file, line);
1456 	if (!call) {
1457 		switch_core_destroy_memory_pool(&pool);
1458 	}
1459 	return call;
1460 }
1461 
1462 /**
1463  * Mixer destructor
1464  */
rayo_mixer_cleanup(struct rayo_actor * actor)1465 static void rayo_mixer_cleanup(struct rayo_actor *actor)
1466 {
1467 	struct rayo_mixer *mixer = RAYO_MIXER(actor);
1468 	switch_core_hash_destroy(&mixer->members);
1469 	switch_core_hash_destroy(&mixer->subscribers);
1470 }
1471 
1472 /**
1473  * Initialize mixer
1474  * @return the mixer or NULL if JID conflict
1475  */
rayo_mixer_init(struct rayo_mixer * mixer,switch_memory_pool_t * pool,const char * name,const char * file,int line)1476 static struct rayo_mixer *rayo_mixer_init(struct rayo_mixer *mixer, switch_memory_pool_t *pool, const char *name, const char *file, int line)
1477 {
1478 	char *mixer_jid = switch_mprintf("%s@%s", name, RAYO_JID(globals.server));
1479 	mixer = RAYO_MIXER(rayo_actor_init(RAYO_ACTOR(mixer), pool, RAT_MIXER, "", name, mixer_jid, rayo_mixer_cleanup, rayo_mixer_send, NULL, file, line));
1480 	if (mixer) {
1481 		switch_core_hash_init(&mixer->members);
1482 		switch_core_hash_init(&mixer->subscribers);
1483 	}
1484 	switch_safe_free(mixer_jid);
1485 	return mixer;
1486 }
1487 
1488 #define rayo_mixer_create(name) _rayo_mixer_create(name, __FILE__, __LINE__)
1489 /**
1490  * Create Rayo mixer
1491  * @param name of this mixer
1492  * @return the mixer or NULL if JID conflict
1493  */
_rayo_mixer_create(const char * name,const char * file,int line)1494 static struct rayo_mixer *_rayo_mixer_create(const char *name, const char *file, int line)
1495 {
1496 	switch_memory_pool_t *pool;
1497 	struct rayo_mixer *mixer = NULL;
1498 	switch_core_new_memory_pool(&pool);
1499 	mixer = rayo_mixer_init(switch_core_alloc(pool, sizeof(*mixer)), pool, name, file, line);
1500 	if (!mixer) {
1501 		switch_core_destroy_memory_pool(&pool);
1502 	}
1503 	return mixer;
1504 }
1505 
1506 /**
1507  * Initialize Rayo component
1508  * @param type of this component
1509  * @param subtype of this component
1510  * @param id internal ID of this component
1511  * @param parent the parent that owns this component
1512  * @param client_jid the client that created this component
1513  * @param cleanup optional cleanup function
1514  * @param file file that called this function
1515  * @param line line number that called this function
1516  * @return the component or NULL if JID conflict
1517  */
_rayo_component_init(struct rayo_component * component,switch_memory_pool_t * pool,const char * type,const char * subtype,const char * id,struct rayo_actor * parent,const char * client_jid,rayo_actor_cleanup_fn cleanup,const char * file,int line)1518 struct rayo_component *_rayo_component_init(struct rayo_component *component, switch_memory_pool_t *pool, const char *type, const char *subtype, const char *id, struct rayo_actor *parent, const char *client_jid, rayo_actor_cleanup_fn cleanup, const char *file, int line)
1519 {
1520 	char *ref = switch_mprintf("%s-%d", subtype, rayo_actor_seq_next(parent));
1521 	char *jid = switch_mprintf("%s/%s", RAYO_JID(parent), ref);
1522 	if (zstr(id)) {
1523 		id = jid;
1524 	}
1525 
1526 	component = RAYO_COMPONENT(rayo_actor_init(RAYO_ACTOR(component), pool, type, subtype, id, jid, cleanup, rayo_component_send, parent, file, line));
1527 	if (component) {
1528 		component->client_jid = switch_core_strdup(pool, client_jid);
1529 		component->ref = switch_core_strdup(pool, ref);
1530 	}
1531 
1532 	switch_safe_free(ref);
1533 	switch_safe_free(jid);
1534 	return component;
1535 }
1536 
1537 /**
1538  * Send XMPP message to client
1539  */
rayo_client_send(struct rayo_actor * client,struct rayo_message * msg)1540 void rayo_client_send(struct rayo_actor *client, struct rayo_message *msg)
1541 {
1542 	xmpp_stream_context_send(globals.xmpp_context, RAYO_CLIENT(client)->route, msg->payload);
1543 }
1544 
1545 /**
1546  * Cleanup rayo client
1547  */
rayo_client_cleanup(struct rayo_actor * actor)1548 static void rayo_client_cleanup(struct rayo_actor *actor)
1549 {
1550 	/* remove session from map */
1551 	switch_mutex_lock(globals.clients_mutex);
1552 	if (!zstr(RAYO_JID(actor))) {
1553 		switch_core_hash_delete(globals.clients_roster, RAYO_JID(actor));
1554 		if (RAYO_CLIENT(actor)->peer_server) {
1555 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Removing %s from peer server %s\n", RAYO_JID(actor), RAYO_JID(RAYO_CLIENT(actor)->peer_server));
1556 			switch_core_hash_delete(RAYO_CLIENT(actor)->peer_server->clients, RAYO_JID(actor));
1557 		}
1558 	}
1559 	switch_mutex_unlock(globals.clients_mutex);
1560 
1561 	pause_when_offline();
1562 }
1563 
1564 /**
1565  * Initialize rayo client
1566  * @param pool the memory pool for this client
1567  * @param jid for this client
1568  * @param route to this client
1569  * @param availability of client
1570  * @param send message transmission function
1571  * @param peer_server NULL if locally connected client
1572  * @return the new client or NULL if JID conflict
1573  */
rayo_client_init(struct rayo_client * client,switch_memory_pool_t * pool,const char * jid,const char * route,enum presence_status availability,rayo_actor_send_fn send,struct rayo_peer_server * peer_server)1574 static struct rayo_client *rayo_client_init(struct rayo_client *client, switch_memory_pool_t *pool, const char *jid, const char *route, enum presence_status availability, rayo_actor_send_fn send, struct rayo_peer_server *peer_server)
1575 {
1576 	client = RAYO_CLIENT(RAYO_ACTOR_INIT(RAYO_ACTOR(client), pool, RAT_CLIENT, "", jid, jid, rayo_client_cleanup, send));
1577 	if (client) {
1578 		client->availability = availability;
1579 		client->peer_server = peer_server;
1580 		client->last_probe = 0;
1581 		if (route) {
1582 			client->route = switch_core_strdup(pool, route);
1583 		}
1584 
1585 		/* make client available for offers */
1586 		switch_mutex_lock(globals.clients_mutex);
1587 		switch_core_hash_insert(globals.clients_roster, RAYO_JID(client), client);
1588 		if (peer_server) {
1589 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding %s to peer server %s\n", RAYO_JID(client), RAYO_JID(peer_server));
1590 			switch_core_hash_insert(peer_server->clients, RAYO_JID(client), client);
1591 		}
1592 		switch_mutex_unlock(globals.clients_mutex);
1593 	}
1594 
1595 	pause_when_offline();
1596 
1597 	return client;
1598 }
1599 
1600 /**
1601  * Create a new Rayo client
1602  * @param jid for this client
1603  * @param route to this client
1604  * @param availability of client
1605  * @param send message transmission function
1606  * @param peer_server NULL if locally connected client
1607  * @return the new client or NULL
1608  */
rayo_client_create(const char * jid,const char * route,enum presence_status availability,rayo_actor_send_fn send,struct rayo_peer_server * peer_server)1609 static struct rayo_client *rayo_client_create(const char *jid, const char *route, enum presence_status availability, rayo_actor_send_fn send, struct rayo_peer_server *peer_server)
1610 {
1611 	switch_memory_pool_t *pool;
1612 	struct rayo_client *rclient = NULL;
1613 
1614 	switch_core_new_memory_pool(&pool);
1615 	if (!(rclient = switch_core_alloc(pool, sizeof(*rclient)))) {
1616 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error\n");
1617 		return NULL;
1618 	}
1619 	rclient = rayo_client_init(rclient, pool, jid, route, availability, send, peer_server);
1620 	if (!rclient) {
1621 		switch_core_destroy_memory_pool(&pool);
1622 	}
1623 	return rclient;
1624 }
1625 
1626 /**
1627  * Send XMPP message to peer server
1628  */
rayo_peer_server_send(struct rayo_actor * server,struct rayo_message * msg)1629 void rayo_peer_server_send(struct rayo_actor *server, struct rayo_message *msg)
1630 {
1631 	xmpp_stream_context_send(globals.xmpp_context, RAYO_JID(server), msg->payload);
1632 }
1633 
1634 /**
1635  * Destroy peer server and its associated clients
1636  */
rayo_peer_server_cleanup(struct rayo_actor * actor)1637 static void rayo_peer_server_cleanup(struct rayo_actor *actor)
1638 {
1639 	switch_hash_index_t *hi = NULL;
1640 	struct rayo_peer_server *rserver = RAYO_PEER_SERVER(actor);
1641 
1642 	/* a little messy... client will remove itself from the peer server when it is destroyed,
1643 	 * however, there is no guarantee the client will actually be destroyed now so
1644 	 * the server must remove the client.
1645 	 */
1646 	switch_mutex_lock(globals.clients_mutex);
1647 	while ((hi = switch_core_hash_first_iter(rserver->clients, hi))) {
1648 		const void *key;
1649 		void *client;
1650 		switch_core_hash_this(hi, &key, NULL, &client);
1651 		switch_assert(client);
1652 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Removing %s from peer server %s\n", RAYO_JID(client), RAYO_JID(rserver));
1653 		switch_core_hash_delete(rserver->clients, key);
1654 		RAYO_CLIENT(client)->peer_server = NULL;
1655 		RAYO_RELEASE(client);
1656 		RAYO_DESTROY(client);
1657 	}
1658 	switch_core_hash_destroy(&rserver->clients);
1659 	switch_mutex_unlock(globals.clients_mutex);
1660 }
1661 
1662 /**
1663  * Create a new Rayo peer server
1664  * @param jid of this server
1665  * @return the peer server
1666  */
rayo_peer_server_create(const char * jid)1667 static struct rayo_peer_server *rayo_peer_server_create(const char *jid)
1668 {
1669 	switch_memory_pool_t *pool;
1670 	struct rayo_peer_server *rserver = NULL;
1671 
1672 	switch_core_new_memory_pool(&pool);
1673 	if (!(rserver = switch_core_alloc(pool, sizeof(*rserver)))) {
1674 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error\n");
1675 		return NULL;
1676 	}
1677 	rserver = RAYO_PEER_SERVER(RAYO_ACTOR_INIT(RAYO_ACTOR(rserver), pool, RAT_PEER_SERVER, "", jid, jid, rayo_peer_server_cleanup, rayo_peer_server_send));
1678 	if (rserver) {
1679 		switch_core_hash_init(&rserver->clients);
1680 	} else {
1681 		switch_core_destroy_memory_pool(&pool);
1682 	}
1683 	return rserver;
1684 }
1685 
1686 /**
1687  * Check if message sender has control of offered call.
1688  * @param call the Rayo call
1689  * @param msg the message
1690  * @return 1 if sender has call control, 0 if sender does not have control
1691  */
has_call_control(struct rayo_call * call,struct rayo_message * msg)1692 static int has_call_control(struct rayo_call *call, struct rayo_message *msg)
1693 {
1694 	return (!strcmp(rayo_call_get_dcp_jid(call), msg->from_jid) || is_internal_message(msg) || is_admin_client_message(msg));
1695 }
1696 
1697 /**
1698  * Check if message sender has control of offered call. Take control if nobody else does.
1699  * @param call the Rayo call
1700  * @param session the session
1701  * @param msg the message
1702  * @return 1 if sender has call control
1703  */
take_call_control(struct rayo_call * call,switch_core_session_t * session,struct rayo_message * msg)1704 static int take_call_control(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg)
1705 {
1706 	int control = 0;
1707 
1708 	/* nobody in charge */
1709 	if (zstr(call->dcp_jid)) {
1710 		/* was offered to this session? */
1711 		if (!zstr(msg->from_jid) && switch_core_hash_find(call->pcps, msg->from_jid)) {
1712 			/* take charge */
1713 			call->dcp_jid = switch_core_strdup(RAYO_POOL(call), msg->from_jid);
1714 			switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_dcp_jid", rayo_call_get_dcp_jid(call));
1715 			control = 1;
1716 			switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_INFO, "%s has control of call\n", rayo_call_get_dcp_jid(call));
1717 		}
1718 	} else if (has_call_control(call, msg)) {
1719 		control = 1;
1720 	}
1721 
1722 	if (!control) {
1723 		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_INFO, "%s does not have control of call\n", msg->from_jid);
1724 	}
1725 
1726 	return control;
1727 }
1728 
1729 /**
1730  * Check Rayo server command for errors.
1731  * @param server the server
1732  * @param msg the command
1733  * @return 1 if OK
1734  */
rayo_server_command_ok(struct rayo_actor * server,struct rayo_message * msg)1735 static iks *rayo_server_command_ok(struct rayo_actor *server, struct rayo_message *msg)
1736 {
1737 	iks *node = msg->payload;
1738 	iks *response = NULL;
1739 	int bad = zstr(iks_find_attrib(node, "id"));
1740 
1741 	if (bad) {
1742 		response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST);
1743 	}
1744 
1745 	return response;
1746 }
1747 
1748 /**
1749  * Check Rayo call command for errors.
1750  * @param call the Rayo call
1751  * @param session the session
1752  * @param msg the command
1753  * @return 1 if OK
1754  */
rayo_call_command_ok(struct rayo_call * call,switch_core_session_t * session,struct rayo_message * msg)1755 static iks *rayo_call_command_ok(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg)
1756 {
1757 	iks *node = msg->payload;
1758 	iks *response = NULL;
1759 	int bad = zstr(iks_find_attrib(node, "id"));
1760 
1761 	if (bad) {
1762 		response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST);
1763 	} else if (!take_call_control(call, session, msg)) {
1764 		response = iks_new_error(node, STANZA_ERROR_CONFLICT);
1765 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, %s conflict\n", msg->from_jid, RAYO_JID(call));
1766 	}
1767 
1768 	return response;
1769 }
1770 
1771 /**
1772  * Check Rayo component command for errors.
1773  * @param component the component
1774  * @param msg the command
1775  * @return 0 if error
1776  */
rayo_component_command_ok(struct rayo_component * component,struct rayo_message * msg)1777 static iks *rayo_component_command_ok(struct rayo_component *component, struct rayo_message *msg)
1778 {
1779 	iks *node = msg->payload;
1780 	iks *response = NULL;
1781 	char *from = iks_find_attrib(node, "from");
1782 	int bad = zstr(iks_find_attrib(node, "id"));
1783 
1784 	if (bad) {
1785 		response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST);
1786 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, %s bad request\n", msg->from_jid, RAYO_JID(component));
1787 	} else if (strcmp(component->client_jid, from) && !is_admin_client_message(msg) && !is_internal_message(msg)) {
1788 		/* does not have control of this component */
1789 		response = iks_new_error(node, STANZA_ERROR_CONFLICT);
1790 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, %s conflict\n", msg->from_jid, RAYO_JID(component));
1791 	}
1792 
1793 	return response;
1794 }
1795 
1796 /**
1797  * Handle server message
1798  */
rayo_server_send(struct rayo_actor * server,struct rayo_message * msg)1799 void rayo_server_send(struct rayo_actor *server, struct rayo_message *msg)
1800 {
1801 	iks *response = NULL;
1802 	rayo_actor_xmpp_handler handler = NULL;
1803 	iks *iq = msg->payload;
1804 
1805 	if (!strcmp("presence", iks_name(iq))) {
1806 		/* this is a hack - message from internal console */
1807 		struct rayo_actor *client = RAYO_LOCATE(msg->from_jid);
1808 		if (client) {
1809 			if (!strcmp(RAT_CLIENT, client->type)) {
1810 				on_client_presence(RAYO_CLIENT(client), iq);
1811 			}
1812 			RAYO_RELEASE(client);
1813 		}
1814 		return;
1815 	}
1816 
1817 	/* is this a command a server supports? */
1818 	handler = rayo_actor_command_handler_find(server, msg);
1819 	if (!handler) {
1820 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, no handler function for command to %s\n", msg->from_jid, RAYO_JID(server));
1821 		if (!msg->is_reply) {
1822 			RAYO_SEND_REPLY(server, msg->from_jid, iks_new_error(iq, STANZA_ERROR_FEATURE_NOT_IMPLEMENTED));
1823 		}
1824 		return;
1825 	}
1826 
1827 	/* is the command valid? */
1828 	if (!(response = rayo_server_command_ok(server, msg))) {
1829 		response = handler(server, msg, NULL);
1830 	}
1831 
1832 	if (response) {
1833 		if (!msg->is_reply) {
1834 			RAYO_SEND_REPLY(server, msg->from_jid, response);
1835 		} else {
1836 			iks_delete(response);
1837 		}
1838 	}
1839 }
1840 
1841 /**
1842  * Handle call message
1843  */
rayo_call_send(struct rayo_actor * call,struct rayo_message * msg)1844 void rayo_call_send(struct rayo_actor *call, struct rayo_message *msg)
1845 {
1846 	rayo_actor_xmpp_handler handler = NULL;
1847 	iks *stanza = msg->payload;
1848 	switch_core_session_t *session;
1849 	iks *response = NULL;
1850 
1851 	if (!strcmp("message", iks_name(stanza))) {
1852 		const char *type = iks_find_attrib_soft(stanza, "type");
1853 
1854 		if (!strcmp("normal", type)) {
1855 			const char *body = iks_find_cdata(stanza, "body");
1856 			if (!zstr(body)) {
1857 				switch_event_t *event;
1858 				if (switch_event_create(&event, SWITCH_EVENT_SEND_MESSAGE) == SWITCH_STATUS_SUCCESS) {
1859 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "content-type", "text/plain");
1860 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "uuid", rayo_call_get_uuid(RAYO_CALL(call)));
1861 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", iks_find_cdata(stanza, "subject"));
1862 					switch_event_add_body(event, "%s", body);
1863 					switch_event_fire(&event);
1864 				}
1865 			} else if (!msg->is_reply) {
1866 				RAYO_SEND_REPLY(call, msg->from_jid, iks_new_error_detailed(stanza, STANZA_ERROR_BAD_REQUEST, "missing body"));
1867 			}
1868 		} else if (!msg->is_reply) {
1869 			RAYO_SEND_REPLY(call, msg->from_jid, iks_new_error(stanza, STANZA_ERROR_FEATURE_NOT_IMPLEMENTED));
1870 		}
1871 		return;
1872 	}
1873 
1874 	/* is this a command a call supports? */
1875 	handler = rayo_actor_command_handler_find(call, msg);
1876 	if (!handler) {
1877 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, no handler function for command\n", RAYO_JID(call));
1878 		if (!msg->is_reply) {
1879 			RAYO_SEND_REPLY(call, msg->from_jid, iks_new_error(stanza, STANZA_ERROR_FEATURE_NOT_IMPLEMENTED));
1880 		}
1881 		return;
1882 	}
1883 
1884 	/* is the session still available? */
1885 	session = switch_core_session_locate(rayo_call_get_uuid(RAYO_CALL(call)));
1886 	if (!session) {
1887 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, session not found\n", RAYO_JID(call));
1888 		if (!msg->is_reply) {
1889 			RAYO_SEND_REPLY(call, msg->from_jid, iks_new_error(stanza, STANZA_ERROR_ITEM_NOT_FOUND));
1890 		}
1891 		return;
1892 	}
1893 
1894 	/* is the command valid? */
1895 	if (!(response = rayo_call_command_ok(RAYO_CALL(call), session, msg))) {
1896 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, executing command\n", RAYO_JID(call));
1897 		response = handler(call, msg, session);
1898 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, done executing command\n", RAYO_JID(call));
1899 	}
1900 	switch_core_session_rwunlock(session);
1901 
1902 	if (response) {
1903 		if (!msg->is_reply) {
1904 			RAYO_SEND_REPLY(call, msg->from_jid, response);
1905 		} else {
1906 			iks_delete(response);
1907 		}
1908 	}
1909 }
1910 
1911 /**
1912  * Handle mixer message
1913  */
rayo_mixer_send(struct rayo_actor * mixer,struct rayo_message * msg)1914 void rayo_mixer_send(struct rayo_actor *mixer, struct rayo_message *msg)
1915 {
1916 	rayo_actor_xmpp_handler handler = NULL;
1917 	iks *iq = msg->payload;
1918 	iks *response = NULL;
1919 
1920 	/* is this a command a mixer supports? */
1921 	handler = rayo_actor_command_handler_find(mixer, msg);
1922 	if (!handler) {
1923 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, no handler function for command\n", RAYO_JID(mixer));
1924 		if (!msg->is_reply) {
1925 			RAYO_SEND_REPLY(mixer, msg->from_jid, iks_new_error(iq, STANZA_ERROR_FEATURE_NOT_IMPLEMENTED));
1926 		}
1927 		return;
1928 	}
1929 
1930 	/* execute the command */
1931 	response = handler(mixer, msg, NULL);
1932 	if (response) {
1933 		if (!msg->is_reply) {
1934 			RAYO_SEND_REPLY(mixer, msg->from_jid, response);
1935 		} else {
1936 			iks_delete(response);
1937 		}
1938 	}
1939 }
1940 
1941 /**
1942  * Handle mixer message
1943  */
rayo_component_send(struct rayo_actor * component,struct rayo_message * msg)1944 void rayo_component_send(struct rayo_actor *component, struct rayo_message *msg)
1945 {
1946 	rayo_actor_xmpp_handler handler = NULL;
1947 	iks *xml_msg = msg->payload;
1948 	iks *response = NULL;
1949 
1950 	if (!strcmp("iq", iks_name(xml_msg))) {
1951 		/* is this a command a component supports? */
1952 		handler = rayo_actor_command_handler_find(component, msg);
1953 		if (!handler) {
1954 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, no component handler function for command\n", RAYO_JID(component));
1955 			if (!msg->is_reply) {
1956 				RAYO_SEND_REPLY(component, msg->from_jid, iks_new_error(xml_msg, STANZA_ERROR_FEATURE_NOT_IMPLEMENTED));
1957 			}
1958 			return;
1959 		}
1960 
1961 		/* is the command valid? */
1962 		if (!(response = rayo_component_command_ok(RAYO_COMPONENT(component), msg))) {
1963 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, executing command\n", RAYO_JID(component));
1964 			response = handler(component, msg, NULL);
1965 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, done executing command\n", RAYO_JID(component));
1966 		}
1967 
1968 		if (response) {
1969 			if (!msg->is_reply) {
1970 				RAYO_SEND_REPLY(component, msg->from_jid, response);
1971 			} else {
1972 				iks_delete(response);
1973 			}
1974 			return;
1975 		}
1976 	} else if (!strcmp("presence", iks_name(xml_msg))) {
1977 		/* is this an event the component wants? */
1978 		handler = rayo_actor_event_handler_find(component, msg);
1979 		if (!handler) {
1980 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, no component handler function for event\n", RAYO_JID(component));
1981 			return;
1982 		}
1983 
1984 		/* forward the event */
1985 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, forwarding event\n", RAYO_JID(component));
1986 		response = handler(component, msg, NULL);
1987 		if (response) {
1988 			if (!msg->is_reply) {
1989 				RAYO_SEND_REPLY(component, msg->from_jid, response);
1990 			} else {
1991 				iks_delete(response);
1992 			}
1993 		}
1994 	}
1995 }
1996 
1997 /**
1998  * Add signaling headers to channel -- only works on SIP
1999  * @param session the channel
2000  * @param iq_cmd the request containing <header>
2001  * @param type header type
2002  */
add_signaling_headers(switch_core_session_t * session,iks * iq_cmd,const char * type)2003 static void add_signaling_headers(switch_core_session_t *session, iks *iq_cmd, const char *type)
2004 {
2005 	switch_channel_t *channel = switch_core_session_get_channel(session);
2006 	iks *header = NULL;
2007 	for (header = iks_find(iq_cmd, "header"); header; header = iks_next_tag(header)) {
2008 		if (!strcmp("header", iks_name(header))) {
2009 			const char *name = iks_find_attrib_soft(header, "name");
2010 			const char *value = iks_find_attrib_soft(header, "value");
2011 			if (!zstr(name) && !zstr(value)) {
2012 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Adding header: %s: %s\n", name, value);
2013 				switch_channel_set_variable_name_printf(channel, value, "%s%s", type, name);
2014 			}
2015 		}
2016 	}
2017 }
2018 
2019 /**
2020  * Handle <iq><accept> request
2021  * @param call the Rayo call
2022  * @param session the session
2023  * @param node the <iq> node
2024  */
on_rayo_accept(struct rayo_actor * call,struct rayo_message * msg,void * session_data)2025 static iks *on_rayo_accept(struct rayo_actor *call, struct rayo_message *msg, void *session_data)
2026 {
2027 	iks *node = msg->payload;
2028 	switch_core_session_t *session = (switch_core_session_t *)session_data;
2029 	iks *response = NULL;
2030 
2031 	/* send ringing */
2032 	add_signaling_headers(session, iks_find(node, "accept"), RAYO_SIP_RESPONSE_HEADER);
2033 	switch_channel_pre_answer(switch_core_session_get_channel(session));
2034 	response = iks_new_iq_result(node);
2035 	return response;
2036 }
2037 
2038 /**
2039  * Handle <iq><answer> request
2040  * @param call the Rayo call
2041  * @param session the session
2042  * @param node the <iq> node
2043  */
on_rayo_answer(struct rayo_actor * call,struct rayo_message * msg,void * session_data)2044 static iks *on_rayo_answer(struct rayo_actor *call, struct rayo_message *msg, void *session_data)
2045 {
2046 	iks *node = msg->payload;
2047 	switch_core_session_t *session = (switch_core_session_t *)session_data;
2048 	iks *response = NULL;
2049 
2050 	/* send answer to call */
2051 	add_signaling_headers(session, iks_find(node, "answer"), RAYO_SIP_RESPONSE_HEADER);
2052 	switch_channel_answer(switch_core_session_get_channel(session));
2053 	response = iks_new_iq_result(node);
2054 	return response;
2055 }
2056 
2057 /**
2058  * Handle <iq><redirect> request
2059  * @param call the Rayo call
2060  * @param session the session
2061  * @param node the <iq> node
2062  */
on_rayo_redirect(struct rayo_actor * call,struct rayo_message * msg,void * session_data)2063 static iks *on_rayo_redirect(struct rayo_actor *call, struct rayo_message *msg, void *session_data)
2064 {
2065 	iks *node = msg->payload;
2066 	switch_core_session_t *session = (switch_core_session_t *)session_data;
2067 	switch_channel_t *channel = switch_core_session_get_channel(session);
2068 	iks *response = NULL;
2069 	iks *redirect = iks_find(node, "redirect");
2070 	char *redirect_to = iks_find_attrib(redirect, "to");
2071 
2072 	if (zstr(redirect_to)) {
2073 		response = iks_new_error_detailed(node, STANZA_ERROR_BAD_REQUEST, "Missing redirect to attrib");
2074 	} else if (switch_channel_test_flag(channel, CF_ANSWERED)) {
2075 		/* call is answered- must deflect */
2076 		switch_core_session_message_t msg = { 0 };
2077 		add_signaling_headers(session, redirect, RAYO_SIP_REQUEST_HEADER);
2078 		msg.from = __FILE__;
2079 		msg.string_arg = switch_core_session_strdup(session, redirect_to);
2080 		msg.message_id = SWITCH_MESSAGE_INDICATE_DEFLECT;
2081 		switch_core_session_receive_message(session, &msg);
2082 		response = iks_new_iq_result(node);
2083 	} else if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
2084 		/* Inbound call not answered - redirect */
2085 		switch_core_session_message_t msg = { 0 };
2086 		add_signaling_headers(session, redirect, RAYO_SIP_RESPONSE_HEADER);
2087 		msg.from = __FILE__;
2088 		msg.string_arg = switch_core_session_strdup(session, redirect_to);
2089 		msg.message_id = SWITCH_MESSAGE_INDICATE_REDIRECT;
2090 		switch_core_session_receive_message(session, &msg);
2091 		response = iks_new_iq_result(node);
2092 	} else {
2093 		response = iks_new_error_detailed(node, STANZA_ERROR_UNEXPECTED_REQUEST, "Call must be answered");
2094 	}
2095 	return response;
2096 }
2097 
2098 /**
2099  * Handle <iq><hangup> or <iq><reject> request
2100  * @param call the Rayo call
2101  * @param session the session
2102  * @param node the <iq> node
2103  */
on_rayo_hangup(struct rayo_actor * call,struct rayo_message * msg,void * session_data)2104 static iks *on_rayo_hangup(struct rayo_actor *call, struct rayo_message *msg, void *session_data)
2105 {
2106 	iks *node = msg->payload;
2107 	switch_core_session_t *session = (switch_core_session_t *)session_data;
2108 	iks *response = NULL;
2109 	iks *hangup = iks_first_tag(node);
2110 	iks *reason = iks_first_tag(hangup);
2111 	int hangup_cause = RAYO_CAUSE_HANGUP;
2112 
2113 	/* get hangup cause */
2114 	if (!reason && !strcmp("hangup", iks_name(hangup))) {
2115 		/* no reason in <hangup> */
2116 		hangup_cause = RAYO_CAUSE_HANGUP;
2117 	} else if (reason && !strcmp("reject", iks_name(hangup))) {
2118 		char *reason_name = iks_name(reason);
2119 		/* reason required for <reject> */
2120 		if (!strcmp("busy", reason_name)) {
2121 			hangup_cause = RAYO_CAUSE_BUSY;
2122 		} else if (!strcmp("decline", reason_name)) {
2123 			hangup_cause = RAYO_CAUSE_DECLINE;
2124 		} else if (!strcmp("error", reason_name)) {
2125 			hangup_cause = RAYO_CAUSE_ERROR;
2126 		} else {
2127 			response = iks_new_error_detailed(node, STANZA_ERROR_BAD_REQUEST, "invalid reject reason");
2128 		}
2129 	} else {
2130 		response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST);
2131 	}
2132 
2133 	/* do hangup */
2134 	if (!response) {
2135 		switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_local_hangup", "true");
2136 		add_signaling_headers(session, hangup, RAYO_SIP_REQUEST_HEADER);
2137 		add_signaling_headers(session, hangup, RAYO_SIP_RESPONSE_HEADER);
2138 		switch_ivr_kill_uuid(rayo_call_get_uuid(call), hangup_cause);
2139 		response = iks_new_iq_result(node);
2140 	}
2141 
2142 	return response;
2143 }
2144 
2145 /**
2146  * Join calls together
2147  * @param call the call that joins
2148  * @param session the session
2149  * @param msg the rayo join message
2150  * @param call_uri to join
2151  * @param media mode (direct/bridge)
2152  * @return the response
2153  */
join_call(struct rayo_call * call,switch_core_session_t * session,struct rayo_message * msg,const char * call_uri,const char * media)2154 static iks *join_call(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *call_uri, const char *media)
2155 {
2156 	iks *node = msg->payload;
2157 	iks *response = NULL;
2158 	/* take call out of media path if media = "direct" */
2159 	int do_direct = !strcmp("direct", media);
2160 
2161 	/* check if joining to rayo call */
2162 	struct rayo_call *b_call = RAYO_CALL_LOCATE(call_uri);
2163 	if (b_call) {
2164 		if (!call->rayo_app_started) {
2165 			/* A-leg not under rayo control yet */
2166 			response = iks_new_error_detailed(node, STANZA_ERROR_UNEXPECTED_REQUEST, "a-leg is not ready to join");
2167 		} else if (!b_call->rayo_app_started) {
2168 			/* B-leg not under rayo control yet */
2169 			response = iks_new_error_detailed(node, STANZA_ERROR_UNEXPECTED_REQUEST, "b-leg is not ready to join");
2170 		} else if (!has_call_control(b_call, msg)) {
2171 			/* not allowed to join to this call */
2172 			response = iks_new_error(node, STANZA_ERROR_NOT_ALLOWED);
2173 		} else if (b_call->joined) {
2174 			/* don't support multiple joined calls */
2175 			response = iks_new_error_detailed(node, STANZA_ERROR_CONFLICT, "multiple joined calls not supported");
2176 		} else {
2177 			/* bridge this call to call-uri */
2178 			if (do_direct) {
2179 				switch_channel_set_flag(switch_core_session_get_channel(session), CF_BYPASS_MEDIA_AFTER_BRIDGE);
2180 			} else {
2181 				switch_channel_clear_flag(switch_core_session_get_channel(session), CF_BYPASS_MEDIA_AFTER_BRIDGE);
2182 				switch_channel_pre_answer(switch_core_session_get_channel(session));
2183 			}
2184 			call->pending_join_request = iks_copy(node);
2185 			if (switch_ivr_uuid_bridge(rayo_call_get_uuid(call), rayo_call_get_uuid(b_call)) != SWITCH_STATUS_SUCCESS) {
2186 				iks *request = call->pending_join_request;
2187 				iks *result = iks_new_error(request, STANZA_ERROR_SERVICE_UNAVAILABLE);
2188 				call->pending_join_request = NULL;
2189 				RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
2190 				iks_delete(call->pending_join_request);
2191 			}
2192 		}
2193 		RAYO_RELEASE(b_call);
2194 	} else {
2195 		/* not a rayo call */
2196 		response = iks_new_error_detailed(node, STANZA_ERROR_SERVICE_UNAVAILABLE, "b-leg is gone");
2197 	}
2198 	return response;
2199 }
2200 
2201 /**
2202  * Execute command on session's conference
2203  * @param session to execute conference API on
2204  * @param conf_name of conference
2205  * @param command to send to conference
2206  * @param node IQ request
2207  * @return response on failure
2208  */
exec_conference_api(switch_core_session_t * session,const char * conf_name,const char * command,iks * node)2209 static iks *exec_conference_api(switch_core_session_t *session, const char *conf_name, const char *command, iks *node)
2210 {
2211 	iks *response = NULL;
2212 	switch_stream_handle_t stream = { 0 };
2213 	const char *conf_member_id = switch_channel_get_variable(switch_core_session_get_channel(session), "conference_member_id");
2214 	SWITCH_STANDARD_STREAM(stream);
2215 	switch_api_execute("conference", switch_core_session_sprintf(session, "%s %s %s", conf_name, command, conf_member_id), NULL, &stream);
2216 	if (!zstr(stream.data) && strncmp("OK", stream.data, 2)) {
2217 		response = iks_new_error_detailed_printf(node, STANZA_ERROR_SERVICE_UNAVAILABLE, "%s", stream.data);
2218 	}
2219 	switch_safe_free(stream.data);
2220 	return response;
2221 }
2222 
2223 /**
2224  * Execute conference app on session
2225  * @param session to execute conference API on
2226  * @param command to send to conference (conference name, member flags, etc)
2227  * @param node IQ request
2228  * @return response on failure
2229  */
exec_conference_app(switch_core_session_t * session,const char * command,iks * node)2230 static iks *exec_conference_app(switch_core_session_t *session, const char *command, iks *node)
2231 {
2232 	iks *response = NULL;
2233 	switch_event_t *execute_event = NULL;
2234 	switch_channel_t *channel = switch_core_session_get_channel(session);
2235 
2236 	/* conference requires local media on channel */
2237 	if (!switch_channel_media_ready(channel) && switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
2238 		/* shit */
2239 		response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to start media");
2240 		return response;
2241 	}
2242 
2243 	/* send execute conference event to session */
2244 	if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
2245 		switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute");
2246 		switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", "conference");
2247 		switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", command);
2248 		//switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event_uuid", uuid);
2249 		switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true");
2250 		if (!switch_channel_test_flag(channel, CF_PROXY_MODE)) {
2251 			switch_channel_set_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA);
2252 		}
2253 
2254 		if (switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) {
2255 			response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to join mixer (queue event failed)");
2256 			if (execute_event) {
2257 				switch_event_destroy(&execute_event);
2258 			}
2259 			return response;
2260 		}
2261 	}
2262 	return response;
2263 }
2264 
2265 /**
2266  * Join call to a mixer
2267  * @param call the call that joins
2268  * @param session the session
2269  * @param msg the join request
2270  * @param mixer_name the mixer to join
2271  * @param direction the media direction
2272  * @return the response
2273  */
join_mixer(struct rayo_call * call,switch_core_session_t * session,struct rayo_message * msg,const char * mixer_name,const char * direction)2274 static iks *join_mixer(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *mixer_name, const char *direction)
2275 {
2276 	iks *node = msg->payload;
2277 	iks *response = NULL;
2278 
2279 	if (!call->rayo_app_started) {
2280 		/* A-leg not under rayo control yet */
2281 		response = iks_new_error_detailed(node, STANZA_ERROR_UNEXPECTED_REQUEST, "call is not ready to join");
2282 	} else if (call->joined_id) {
2283 		/* adjust join conference params */
2284 		if (!strcmp("duplex", direction)) {
2285 			if ((response = exec_conference_api(session, mixer_name, "unmute", node)) ||
2286 				(response = exec_conference_api(session, mixer_name, "undeaf", node))) {
2287 				return response;
2288 			}
2289 		} else if (!strcmp("recv", direction)) {
2290 			if ((response = exec_conference_api(session, mixer_name, "mute", node)) ||
2291 				(response = exec_conference_api(session, mixer_name, "undeaf", node))) {
2292 				return response;
2293 			}
2294 		} else {
2295 			if ((response = exec_conference_api(session, mixer_name, "unmute", node)) ||
2296 				(response = exec_conference_api(session, mixer_name, "deaf", node))) {
2297 				return response;
2298 			}
2299 		}
2300 		response = iks_new_iq_result(node);
2301 	} else {
2302 		/* join new conference */
2303 		const char *conf_args = switch_core_session_sprintf(session, "%s@%s", mixer_name, globals.mixer_conf_profile);
2304 		if (!strcmp("send", direction)) {
2305 			conf_args = switch_core_session_sprintf(session, "%s+flags{deaf}", conf_args);
2306 		} else if (!strcmp("recv", direction)) {
2307 			conf_args = switch_core_session_sprintf(session, "%s+flags{mute}", conf_args);
2308 		}
2309 
2310 		call->pending_join_request = iks_copy(node);
2311 		response = exec_conference_app(session, conf_args, node);
2312 		if (response) {
2313 			iks_delete(call->pending_join_request);
2314 			call->pending_join_request = NULL;
2315 		}
2316 	}
2317 	return response;
2318 }
2319 
2320 /**
2321  * Handle <iq><join> request
2322  * @param call the Rayo call
2323  * @param session the session
2324  * @param msg the rayo join message
2325  */
on_rayo_join(struct rayo_actor * call,struct rayo_message * msg,void * session_data)2326 static iks *on_rayo_join(struct rayo_actor *call, struct rayo_message *msg, void *session_data)
2327 {
2328 	switch_core_session_t *session = (switch_core_session_t *)session_data;
2329 	iks *response = NULL;
2330 	iks *join = iks_find(msg->payload, "join");
2331 	const char *join_id;
2332 	const char *mixer_name;
2333 	const char *call_uri;
2334 
2335 	/* validate input attributes */
2336 	if (!VALIDATE_RAYO_JOIN(join)) {
2337 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Bad join attrib\n");
2338 		response = iks_new_error(msg->payload, STANZA_ERROR_BAD_REQUEST);
2339 		goto done;
2340 	}
2341 	mixer_name = iks_find_attrib(join, "mixer-name");
2342 	call_uri = iks_find_attrib(join, "call-uri");
2343 
2344 	if (!zstr(mixer_name)) {
2345 		join_id = mixer_name;
2346 	} else {
2347 		join_id = call_uri;
2348 	}
2349 
2350 	/* can't join both mixer and call */
2351 	if (!zstr(mixer_name) && !zstr(call_uri)) {
2352 		response = iks_new_error_detailed(msg->payload, STANZA_ERROR_BAD_REQUEST, "mixer-name and call-uri are mutually exclusive");
2353 		goto done;
2354 	}
2355 
2356 	/* need to join *something* */
2357 	if (zstr(mixer_name) && zstr(call_uri)) {
2358 		response = iks_new_error_detailed(msg->payload, STANZA_ERROR_BAD_REQUEST, "mixer-name or call-uri is required");
2359 		goto done;
2360 	}
2361 
2362 	if ((RAYO_CALL(call)->joined == JOINED_CALL) ||
2363 		(RAYO_CALL(call)->joined == JOINED_MIXER && strcmp(RAYO_CALL(call)->joined_id, join_id))) {
2364 		/* already joined */
2365 		response = iks_new_error_detailed(msg->payload, STANZA_ERROR_CONFLICT, "call is already joined");
2366 		goto done;
2367 	}
2368 
2369 	if (rayo_call_is_faxing(RAYO_CALL(call))) {
2370 		/* can't join a call while it's faxing */
2371 		response = iks_new_error_detailed(msg->payload, STANZA_ERROR_UNEXPECTED_REQUEST, "fax is in progress");
2372 		goto done;
2373 	}
2374 
2375 	if (RAYO_CALL(call)->pending_join_request) {
2376 		/* don't allow concurrent join requests */
2377 		response = iks_new_error_detailed(msg->payload, STANZA_ERROR_UNEXPECTED_REQUEST, "(un)join request is pending");
2378 		goto done;
2379 	}
2380 
2381 	if (!zstr(mixer_name)) {
2382 		/* join conference */
2383 		response = join_mixer(RAYO_CALL(call), session, msg, mixer_name, iks_find_attrib(join, "direction"));
2384 	} else {
2385 		/* bridge calls */
2386 		response = join_call(RAYO_CALL(call), session, msg, call_uri, iks_find_attrib(join, "media"));
2387 	}
2388 
2389 done:
2390 	return response;
2391 }
2392 
2393 /**
2394  * unjoin call to a bridge
2395  * @param call the call that unjoined
2396  * @param session the session
2397  * @param msg the unjoin request
2398  * @param call_uri the b-leg xmpp URI
2399  * @return the response
2400  */
unjoin_call(struct rayo_call * call,switch_core_session_t * session,struct rayo_message * msg,const char * call_uri)2401 static iks *unjoin_call(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *call_uri)
2402 {
2403 	iks *node = msg->payload;
2404 	iks *response = NULL;
2405 
2406 	if (!strcmp(call_uri, call->joined_id)) {
2407 		/* unbridge call */
2408 		call->pending_join_request = iks_copy(node);
2409 		switch_ivr_park_session(session);
2410 	} else {
2411 		/* not bridged or wrong b-leg URI */
2412 		response = iks_new_error_detailed_printf(node, STANZA_ERROR_SERVICE_UNAVAILABLE, "expected URI: %s", call->joined_id);
2413 	}
2414 
2415 	return response;
2416 }
2417 
2418 /**
2419  * unjoin call to a mixer
2420  * @param call the call that unjoined
2421  * @param session the session
2422  * @param msg the unjoin request
2423  * @param mixer_name the mixer name
2424  * @return the response
2425  */
unjoin_mixer(struct rayo_call * call,switch_core_session_t * session,struct rayo_message * msg,const char * mixer_name)2426 static iks *unjoin_mixer(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *mixer_name)
2427 {
2428 	switch_channel_t *channel = switch_core_session_get_channel(session);
2429 	const char *conf_member_id = switch_channel_get_variable(channel, "conference_member_id");
2430 	const char *conf_name = switch_channel_get_variable(channel, "conference_name");
2431 	iks *node = msg->payload;
2432 	iks *response = NULL;
2433 
2434 	/* not conferenced, or wrong conference */
2435 	if (zstr(conf_name) || strcmp(mixer_name, conf_name)) {
2436 		response = iks_new_error_detailed_printf(node, STANZA_ERROR_SERVICE_UNAVAILABLE, "not joined to %s", mixer_name);
2437 		goto done;
2438 	} else if (zstr(conf_member_id)) {
2439 		/* shouldn't happen */
2440 		response = iks_new_error_detailed(node, STANZA_ERROR_SERVICE_UNAVAILABLE, "channel doesn't have conference member ID");
2441 		goto done;
2442 	}
2443 
2444 	/* kick the member */
2445 	response = exec_conference_api(session, mixer_name, "hup", node);
2446 	if (!response) {
2447 		/* ack command */
2448 		response = iks_new_iq_result(node);
2449 	}
2450 
2451 done:
2452 
2453 	return response;
2454 }
2455 
2456 /**
2457  * Handle <iq><unjoin> request
2458  * @param call the Rayo call
2459  * @param session the session
2460  * @param node the <iq> node
2461  */
on_rayo_unjoin(struct rayo_actor * call,struct rayo_message * msg,void * session_data)2462 static iks *on_rayo_unjoin(struct rayo_actor *call, struct rayo_message *msg, void *session_data)
2463 {
2464 	switch_core_session_t *session = (switch_core_session_t *)session_data;
2465 	iks *response = NULL;
2466 	iks *unjoin = iks_find(msg->payload, "unjoin");
2467 	const char *call_uri = iks_find_attrib(unjoin, "call-uri");
2468 	const char *mixer_name = iks_find_attrib(unjoin, "mixer-name");
2469 
2470 	if (!zstr(call_uri) && !zstr(mixer_name)) {
2471 		response = iks_new_error(msg->payload, STANZA_ERROR_BAD_REQUEST);
2472 	} else if (RAYO_CALL(call)->pending_join_request) {
2473 		/* need to let pending request finish first */
2474 		response = iks_new_error_detailed(msg->payload, STANZA_ERROR_UNEXPECTED_REQUEST, "(un)join request is pending");
2475 	} else if (!RAYO_CALL(call)->joined) {
2476 		/* not joined to anything */
2477 		response = iks_new_error_detailed(msg->payload, STANZA_ERROR_SERVICE_UNAVAILABLE, "not joined to anything");
2478 	} else if (RAYO_CALL(call)->joined == JOINED_MIXER && !zstr(call_uri)) {
2479 		/* joined to mixer, not call */
2480 		response = iks_new_error_detailed(msg->payload, STANZA_ERROR_SERVICE_UNAVAILABLE, "not joined to call");
2481 	} else if (RAYO_CALL(call)->joined == JOINED_CALL && !zstr(mixer_name)) {
2482 		/* joined to call, not mixer */
2483 		response = iks_new_error_detailed(msg->payload, STANZA_ERROR_SERVICE_UNAVAILABLE, "not joined to mixer");
2484 	} else if (!zstr(call_uri)) {
2485 		response = unjoin_call(RAYO_CALL(call), session, msg, call_uri);
2486 	} else if (!zstr(mixer_name)) {
2487 		response = unjoin_mixer(RAYO_CALL(call), session, msg, mixer_name);
2488 	} else {
2489 		/* unjoin everything */
2490 		if (RAYO_CALL(call)->joined == JOINED_MIXER) {
2491 			response = unjoin_mixer(RAYO_CALL(call), session, msg, RAYO_CALL(call)->joined_id);
2492 		} else if (RAYO_CALL(call)->joined == JOINED_CALL) {
2493 			response = unjoin_call(RAYO_CALL(call), session, msg, RAYO_CALL(call)->joined_id);
2494 		} else {
2495 			/* shouldn't happen */
2496 			response = iks_new_error(msg->payload, STANZA_ERROR_INTERNAL_SERVER_ERROR);
2497 		}
2498 	}
2499 
2500 	return response;
2501 }
2502 
2503 /**
2504  * @return 1 if display name is valid
2505  */
is_valid_display_name(char * display)2506 static int is_valid_display_name(char *display)
2507 {
2508 	if (zstr(display)) {
2509 		return 0;
2510 	}
2511 	return 1;
2512 }
2513 
2514 /**
2515  * @return 1 if SIP URI is valid
2516  */
is_valid_sip_uri(char * uri)2517 static int is_valid_sip_uri(char *uri)
2518 {
2519 	/* just some basic checks to prevent failure when passing URI as caller ID */
2520 	if (zstr(uri) || strchr(uri, '<') || strchr(uri, '>')) {
2521 		return 0;
2522 	}
2523 	return 1;
2524 }
2525 
2526 #define RAYO_URI_SCHEME_UNKNOWN 0
2527 #define RAYO_URI_SCHEME_TEL 1
2528 #define RAYO_URI_SCHEME_SIP 2
2529 
2530 /**
2531  * Parse dial "from" parameter
2532  * @param pool to use
2533  * @param from the parameter to parse
2534  * @param uri the URI
2535  * @param display the display name
2536  * @return scheme
2537  */
parse_dial_from(switch_memory_pool_t * pool,const char * from,char ** uri,char ** display)2538 static int parse_dial_from(switch_memory_pool_t *pool, const char *from, char **uri, char **display)
2539 {
2540 	if (!zstr(from)) {
2541 		char *l_display = switch_core_strdup(pool, from);
2542 		char *l_uri;
2543 
2544 		*display = NULL;
2545 		*uri = NULL;
2546 
2547 		/* TODO regex would be better */
2548 
2549 		/* split display-name and URI */
2550 		l_uri = strrchr(l_display, ' ');
2551 		if (l_uri) {
2552 			*l_uri++ = '\0';
2553 			if (!zstr(l_display)) {
2554 				/* remove "" from display-name */
2555 				if (l_display[0] == '"') {
2556 					int len;
2557 					*l_display++ = '\0';
2558 					len = strlen(l_display);
2559 					if (len < 2 || l_display[len - 1] != '"') {
2560 						return RAYO_URI_SCHEME_UNKNOWN;
2561 					}
2562 					l_display[len - 1] = '\0';
2563 				}
2564 				if (!is_valid_display_name(l_display)) {
2565 					return RAYO_URI_SCHEME_UNKNOWN;
2566 				}
2567 				*display = l_display;
2568 			}
2569 		} else {
2570 			l_uri = l_display;
2571 		}
2572 		if (zstr(l_uri)) {
2573 			return RAYO_URI_SCHEME_UNKNOWN;
2574 		}
2575 
2576 		/* remove <> from URI */
2577 		if (l_uri[0] == '<') {
2578 			int len;
2579 			*l_uri++ = '\0';
2580 			len = strlen(l_uri);
2581 			if (len < 2 || l_uri[len - 1] != '>') {
2582 				return RAYO_URI_SCHEME_UNKNOWN;
2583 			}
2584 			l_uri[len - 1] = '\0';
2585 			if (zstr(l_uri)) {
2586 				return RAYO_URI_SCHEME_UNKNOWN;
2587 			}
2588 		}
2589 		*uri = l_uri;
2590 
2591 		/* figure out URI scheme and validate it */
2592 		if (!strncmp("sip:", l_uri, 4) || !strncmp("sips:", l_uri, 5)) {
2593 			/* validate SIP URI */
2594 			if (is_valid_sip_uri(l_uri)) {
2595 				return RAYO_URI_SCHEME_SIP;
2596 			}
2597 		} else if (!strncmp("tel:", l_uri, 4)) {
2598 			l_uri += 4;
2599 			*uri = l_uri;
2600 		}
2601 		if (!zstr(l_uri)) {
2602 			return RAYO_URI_SCHEME_TEL;
2603 		}
2604 	}
2605 	return RAYO_URI_SCHEME_UNKNOWN;
2606 }
2607 
2608 struct dial_thread_data {
2609 	switch_memory_pool_t *pool;
2610 	iks *node;
2611 };
2612 
2613 
2614 /**
2615  * Thread that handles originating new calls
2616  * @param thread this thread
2617  * @param obj the Rayo client
2618  * @return NULL
2619  */
rayo_dial_thread(switch_thread_t * thread,void * user)2620 static void *SWITCH_THREAD_FUNC rayo_dial_thread(switch_thread_t *thread, void *user)
2621 {
2622 	struct dial_thread_data *dtdata = (struct dial_thread_data *)user;
2623 	iks *iq = dtdata->node;
2624 	iks *dial = iks_find(iq, "dial");
2625 	iks *response = NULL;
2626 	const char *dcp_jid = iks_find_attrib(iq, "from");
2627 	const char *dial_to = iks_find_attrib(dial, "to");
2628 	char *dial_to_dup = NULL;
2629 	const char *dial_from = iks_find_attrib(dial, "from");
2630 	const char *dial_timeout_ms = iks_find_attrib(dial, "timeout");
2631 	const char *requested_call_uri = iks_find_attrib(dial, "uri");
2632 	const char *uuid = NULL;
2633 	switch_event_t *originate_vars = NULL;
2634 	struct dial_gateway *gateway = NULL;
2635 	struct rayo_call *call = NULL;
2636 	uint32_t dial_timeout_sec = 0;
2637 
2638 	/* TODO dial_to needs validation */
2639 
2640 	/* Check if optional URI is valid. */
2641 	if (!zstr(requested_call_uri)) {
2642 
2643 		/* Split node and domain from URI */
2644 		char *requested_call_uri_dup = switch_core_strdup(dtdata->pool, requested_call_uri);
2645 		char *requested_call_uri_domain = strchr(requested_call_uri_dup, '@');
2646 		if (requested_call_uri_domain) {
2647 			*requested_call_uri_domain = '\0';
2648 			requested_call_uri_domain++;
2649 		}
2650 
2651 		/* is domain missing */
2652 		if (zstr(requested_call_uri_domain)) {
2653 			response = iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "Bad uri");
2654 			goto done;
2655 		}
2656 
2657 		/* is domain correct? */
2658 		if (strcmp(requested_call_uri_domain, RAYO_JID(globals.server))) {
2659 			response = iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "Bad uri (invalid domain)");
2660 			goto done;
2661 		}
2662 
2663 		/* is node identifier missing? */
2664 		if (zstr(requested_call_uri_dup)) {
2665 			response = iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "Bad uri (missing node)");
2666 			goto done;
2667 		}
2668 
2669 		/* strip optional xmpp: from node identifier */
2670 		if (!strncasecmp("xmpp:", requested_call_uri_dup, 5)) {
2671 			requested_call_uri_dup += 5;
2672 			if (zstr(requested_call_uri_dup)) {
2673 				response = iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "Bad uri (missing node)");
2674 				goto done;
2675 			}
2676 		}
2677 
2678 		/* success! */
2679 		uuid = requested_call_uri_dup;
2680 	}
2681 
2682 	/* create call and link to DCP */
2683 	call = rayo_call_create(uuid);
2684 	if (!call) {
2685 		response = iks_new_error(iq, STANZA_ERROR_CONFLICT);
2686 		goto done;
2687 	}
2688 	call->dcp_jid = switch_core_strdup(RAYO_POOL(call), dcp_jid);
2689 	call->dial_request_id = switch_core_strdup(RAYO_POOL(call), iks_find_attrib_soft(iq, "id"));
2690 	switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_INFO, "%s has control of call\n", dcp_jid);
2691 	uuid = switch_core_strdup(dtdata->pool, rayo_call_get_uuid(call));
2692 
2693 	/* create container for origination variables */
2694 	if (switch_event_create_plain(&originate_vars, SWITCH_EVENT_CHANNEL_DATA) != SWITCH_STATUS_SUCCESS) {
2695 		abort();
2696 	}
2697 
2698 	/* add dialstring vars to origination variables */
2699 	if (*dial_to == '{') {
2700 		dial_to_dup = switch_core_strdup(dtdata->pool, dial_to);
2701 		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_DEBUG, "dial: parsing dialstring channel variables\n");
2702 		switch_event_create_brackets(dial_to_dup, '{', '}', ',', &originate_vars, (char **)&dial_to, SWITCH_FALSE);
2703 	}
2704 
2705 	/* set originate channel variables */
2706 	switch_event_add_header_string(originate_vars, SWITCH_STACK_BOTTOM, "origination_uuid", rayo_call_get_uuid(call));
2707 	switch_event_add_header_string(originate_vars, SWITCH_STACK_BOTTOM, "rayo_dcp_jid", dcp_jid);
2708 	switch_event_add_header_string(originate_vars, SWITCH_STACK_BOTTOM, "rayo_call_jid", RAYO_JID(call));
2709 
2710 	if (!zstr(dial_from)) {
2711 		char *from_uri = NULL;
2712 		char *from_display;
2713 		int scheme = parse_dial_from(dtdata->pool, dial_from, &from_uri, &from_display);
2714 		if (scheme == RAYO_URI_SCHEME_UNKNOWN) {
2715 			response = iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "Bad from URI");
2716 			goto done;
2717 		} else if (scheme == RAYO_URI_SCHEME_SIP) {
2718 			/* SIP URI */
2719 			if (!zstr(from_uri)) {
2720 				switch_event_add_header_string(originate_vars, SWITCH_STACK_BOTTOM, "sip_from_uri", from_uri);
2721 				switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_DEBUG, "dial: sip_from_uri=%s\n", from_uri);
2722 			}
2723 			if (!zstr(from_display)) {
2724 				switch_event_add_header_string(originate_vars, SWITCH_STACK_BOTTOM, "sip_from_display", from_display);
2725 				switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_DEBUG, "dial: sip_from_display=%s\n", from_display);
2726 			}
2727 		}
2728 		if (!zstr(from_uri)) {
2729 			switch_event_add_header_string(originate_vars, SWITCH_STACK_BOTTOM, "origination_caller_id_number", from_uri);
2730 			switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_DEBUG, "dial: origination_caller_id_number=%s\n", from_uri);
2731 		}
2732 		if (!zstr(from_display)) {
2733 			switch_event_add_header_string(originate_vars, SWITCH_STACK_BOTTOM, "origination_caller_id_name", from_display);
2734 			switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_DEBUG, "dial: origination_caller_id_name=%s\n", from_display);
2735 		} else if (scheme == RAYO_URI_SCHEME_TEL && !zstr(from_uri)) {
2736 			/* set caller ID name to same as number if telephone number and a name wasn't specified */
2737 			switch_event_add_header_string(originate_vars, SWITCH_STACK_BOTTOM, "origination_caller_id_name", from_uri);
2738 			switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_DEBUG, "dial: origination_caller_id_name=%s\n", from_uri);
2739 		}
2740 	}
2741 	if (!zstr(dial_timeout_ms) && switch_is_number(dial_timeout_ms)) {
2742 		dial_timeout_sec = round((double)atoi(dial_timeout_ms) / 1000.0);
2743 	}
2744 
2745 	/* set outbound signaling headers - only works on SIP */
2746 	{
2747 		iks *header = NULL;
2748 		for (header = iks_find(dial, "header"); header; header = iks_next_tag(header)) {
2749 			if (!strcmp("header", iks_name(header))) {
2750 				const char *name = iks_find_attrib_soft(header, "name");
2751 				const char *value = iks_find_attrib_soft(header, "value");
2752 				if (!zstr(name) && !zstr(value)) {
2753 					char *header_name = switch_core_sprintf(dtdata->pool, "%s%s", RAYO_SIP_REQUEST_HEADER, name);
2754 					switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_DEBUG, "dial: Adding SIP header: %s: %s\n", name, value);
2755 					switch_event_add_header_string(originate_vars, SWITCH_STACK_BOTTOM, header_name, value);
2756 				}
2757 			}
2758 		}
2759 	}
2760 
2761 	/* build dialstring and dial call */
2762 	gateway = dial_gateway_find(dial_to);
2763 	if (gateway) {
2764 		iks *join = iks_find(dial, "join");
2765 		const char *dial_to_stripped = dial_to + gateway->strip;
2766 		switch_core_session_t *called_session = NULL;
2767 		switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
2768 		const char *dialstring = NULL;
2769 
2770 		if (join) {
2771 			/* check join args */
2772 			const char *call_uri = iks_find_attrib(join, "call-uri");
2773 			const char *mixer_name = iks_find_attrib(join, "mixer-name");
2774 
2775 			if (!zstr(call_uri) && !zstr(mixer_name)) {
2776 				/* can't join both */
2777 				response = iks_new_error(iq, STANZA_ERROR_BAD_REQUEST);
2778 				goto done;
2779 			} else if (zstr(call_uri) && zstr(mixer_name)) {
2780 				/* nobody to join to? */
2781 				response = iks_new_error(iq, STANZA_ERROR_BAD_REQUEST);
2782 				goto done;
2783 			} else if (!zstr(call_uri)) {
2784 				/* bridge */
2785 				struct rayo_call *peer_call = RAYO_CALL_LOCATE(call_uri);
2786 				/* is peer call available? */
2787 				if (!peer_call) {
2788 					response = iks_new_error_detailed(iq, STANZA_ERROR_SERVICE_UNAVAILABLE, "peer call not found");
2789 					goto done;
2790 				} else if (peer_call->joined) {
2791 					response = iks_new_error_detailed(iq, STANZA_ERROR_SERVICE_UNAVAILABLE, "peer call already joined");
2792 					RAYO_RELEASE(peer_call);
2793 					goto done;
2794 				}
2795 				switch_event_add_header(originate_vars, SWITCH_STACK_BOTTOM, "rayo_origination_args", "bridge %s", rayo_call_get_uuid(peer_call));
2796 				RAYO_RELEASE(peer_call);
2797 			} else {
2798 				/* conference */
2799 				switch_event_add_header(originate_vars, SWITCH_STACK_BOTTOM, "rayo_origination_args", "conference %s@%s", mixer_name, globals.mixer_conf_profile);
2800 			}
2801 		}
2802 
2803 		dialstring = switch_core_sprintf(dtdata->pool, "%s%s", gateway->dial_prefix, dial_to_stripped);
2804 		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_DEBUG, "dial: Using dialstring: %s\n", dialstring);
2805 
2806 		/* <iq><ref> response will be sent when originate event is received- otherwise error is returned */
2807 		if (switch_ivr_originate(NULL, &called_session, &cause, dialstring, dial_timeout_sec, NULL, NULL, NULL, NULL, originate_vars, SOF_NONE, NULL, NULL) == SWITCH_STATUS_SUCCESS && called_session) {
2808 			/* start APP */
2809 			switch_caller_extension_t *extension = NULL;
2810 			switch_channel_t *called_channel = switch_core_session_get_channel(called_session);
2811 			switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "dial: Call originated\n");
2812 			if ((extension = switch_caller_extension_new(called_session, "rayo", NULL)) == 0) {
2813 				switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_CRIT, "Memory Error!\n");
2814 				abort();
2815 			}
2816 			switch_caller_extension_add_application(called_session, extension, "rayo", NULL);
2817 			switch_channel_set_caller_extension(called_channel, extension);
2818 			switch_channel_set_state(called_channel, CS_EXECUTE);
2819 			switch_core_session_rwunlock(called_session);
2820 		} else {
2821 			switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "dial: Failed to originate call: %s\n", switch_channel_cause2str(cause));
2822 			switch_mutex_lock(RAYO_ACTOR(call)->mutex);
2823 			if (!zstr(call->dial_request_id)) {
2824 				call->dial_request_failed = 1;
2825 				call->dial_request_id = NULL;
2826 
2827 				/* map failure reason to iq error */
2828 				switch (cause) {
2829 					case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
2830 						/* out of sessions, typically */
2831 						response = iks_new_error_detailed(iq, STANZA_ERROR_RESOURCE_CONSTRAINT, "DESTINATION_OUT_OF_ORDER");
2832 						break;
2833 					case SWITCH_CAUSE_SUBSCRIBER_ABSENT:
2834 					case SWITCH_CAUSE_USER_NOT_REGISTERED: {
2835 						/* call session was never created, so we must fake it so that a call error is sent and
2836 						   not a dial error */
2837 						/* send ref response to DCP immediately followed with failure */
2838 						iks *ref;
2839 						iks *ref_response = iks_new("iq");
2840 						iks_insert_attrib(ref_response, "from", RAYO_JID(globals.server));
2841 						iks_insert_attrib(ref_response, "to", dcp_jid);
2842 						iks_insert_attrib(ref_response, "id", iks_find_attrib_soft(iq, "id"));
2843 						iks_insert_attrib(ref_response, "type", "result");
2844 						ref = iks_insert(ref_response, "ref");
2845 						iks_insert_attrib(ref, "xmlns", RAYO_NS);
2846 						iks_insert_attrib_printf(ref, "uri", "xmpp:%s", RAYO_JID(call));
2847 						RAYO_SEND_MESSAGE(globals.server, dcp_jid, ref_response);
2848 
2849 						/* send subscriber-absent call hangup reason */
2850 						rayo_call_send_end(call, NULL, 0, "SUBSCRIBER_ABSENT", "20");
2851 
2852 						/* destroy call */
2853 						RAYO_DESTROY(call);
2854 						RAYO_RELEASE(call);
2855 						break;
2856 					}
2857 					case SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR:
2858 						/* max forwards */
2859 						response = iks_new_error_detailed(iq, STANZA_ERROR_RESOURCE_CONSTRAINT, "EXCHANGE_ROUTING_ERROR");
2860 						break;
2861 					case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED:
2862 						/* unsupported endpoint type */
2863 						response = iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "CHAN_NOT_IMPLEMENTED");
2864 						break;
2865 					case SWITCH_CAUSE_INVALID_URL:
2866 						response = iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "INVALID_URL");
2867 						break;
2868 					case SWITCH_CAUSE_INVALID_GATEWAY:
2869 						response = iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "INVALID_GATEWAY");
2870 						break;
2871 					case SWITCH_CAUSE_INVALID_PROFILE:
2872 						response = iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "INVALID_PROFILE");
2873 						break;
2874 					case SWITCH_CAUSE_SYSTEM_SHUTDOWN:
2875 						response = iks_new_error_detailed(iq, STANZA_ERROR_RESOURCE_CONSTRAINT, "SYSTEM_SHUTDOWN");
2876 						break;
2877 					case SWITCH_CAUSE_GATEWAY_DOWN:
2878 						response = iks_new_error_detailed(iq, STANZA_ERROR_RESOURCE_CONSTRAINT, "GATEWAY_DOWN");
2879 						break;
2880 					case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
2881 						response = iks_new_error_detailed(iq, STANZA_ERROR_RESOURCE_CONSTRAINT, "INVALID_NUMBER_FORMAT");
2882 						break;
2883 					default:
2884 						response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, switch_channel_cause2str(cause));
2885 						break;
2886 				}
2887 			}
2888 			switch_mutex_unlock(RAYO_ACTOR(call)->mutex);
2889 		}
2890 	} else {
2891 		/* will only happen if misconfigured */
2892 		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_CRIT, "dial: No dial gateway found for %s!\n", dial_to);
2893 		call->dial_request_failed = 1;
2894 		call->dial_request_id = NULL;
2895 		response = iks_new_error_detailed_printf(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "dial: No dial gateway found for %s!\n", dial_to);
2896 		goto done;
2897 	}
2898 
2899 done:
2900 
2901 	/* response when error */
2902 	if (response) {
2903 		/* send response to client */
2904 		RAYO_SEND_REPLY(globals.server, iks_find_attrib(response, "to"), response);
2905 
2906 		/* destroy call */
2907 		if (call) {
2908 			RAYO_DESTROY(call);
2909 			RAYO_RELEASE(call);
2910 		}
2911 	}
2912 
2913 	iks_delete(iq);
2914 
2915 	if (originate_vars) {
2916 		switch_event_destroy(&originate_vars);
2917 	}
2918 
2919 	{
2920 		switch_memory_pool_t *pool = dtdata->pool;
2921 		switch_core_destroy_memory_pool(&pool);
2922 	}
2923 
2924 	return NULL;
2925 }
2926 
2927 /**
2928  * Dial a new call
2929  * @param server handling the call
2930  * @param msg the request
2931  */
on_rayo_dial(struct rayo_actor * server,struct rayo_message * msg,void * data)2932 static iks *on_rayo_dial(struct rayo_actor *server, struct rayo_message *msg, void *data)
2933 {
2934 	iks *node = msg->payload;
2935 	switch_thread_t *thread;
2936 	switch_threadattr_t *thd_attr = NULL;
2937 	iks *dial = iks_find(node, "dial");
2938 	iks *response = NULL;
2939 	const char *dial_to = iks_find_attrib(dial, "to");
2940 
2941 	if (zstr(dial_to)) {
2942 		response = iks_new_error_detailed(node, STANZA_ERROR_BAD_REQUEST, "missing dial to attribute");
2943 	} else if (strchr(dial_to, ' ')) {
2944 		response = iks_new_error_detailed(node, STANZA_ERROR_BAD_REQUEST, "malformed dial string");
2945 	} else {
2946 		switch_memory_pool_t *pool;
2947 		struct dial_thread_data *dtdata = NULL;
2948 		switch_core_new_memory_pool(&pool);
2949 		dtdata = switch_core_alloc(pool, sizeof(*dtdata));
2950 		dtdata->pool = pool;
2951 		dtdata->node = iks_copy(node);
2952 
2953 		iks_insert_attrib(dtdata->node, "from", msg->from_jid); /* save DCP jid in case it isn't specified */
2954 
2955 		/* start dial thread */
2956 		switch_threadattr_create(&thd_attr, pool);
2957 		switch_threadattr_detach_set(thd_attr, 1);
2958 		switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
2959 		switch_thread_create(&thread, thd_attr, rayo_dial_thread, dtdata, pool);
2960 	}
2961 
2962 	return response;
2963 }
2964 
2965 struct exec_thread_data {
2966 	switch_memory_pool_t *pool;
2967 	iks *node;
2968 };
2969 
2970 /**
2971  * Thread that handles executing server APIs
2972  * @param thread this thread
2973  * @param user the API request
2974  * @return NULL
2975  */
rayo_exec_thread(switch_thread_t * thread,void * user)2976 static void *SWITCH_THREAD_FUNC rayo_exec_thread(switch_thread_t *thread, void *user)
2977 {
2978 	struct exec_thread_data *etdata = (struct exec_thread_data *)user;
2979 	iks *response = NULL;
2980 	iks *exec = iks_find(etdata->node, "exec");
2981 	const char *api = iks_find_attrib(exec, "api");
2982 	const char *args = iks_find_attrib_soft(exec, "args");
2983 	switch_stream_handle_t stream = { 0 };
2984 	SWITCH_STANDARD_STREAM(stream);
2985 
2986 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "BGAPI EXEC: %s %s\n", api, args);
2987 	if (switch_api_execute(api, args, NULL, &stream) != SWITCH_STATUS_SUCCESS) {
2988 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "BGAPI EXEC FAILURE\n");
2989 		response = iks_new_error_detailed(etdata->node, STANZA_ERROR_BAD_REQUEST, "Failed to execute API");
2990 	} else {
2991 		iks *api_result = NULL;
2992 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "BGAPI EXEC RESULT: %s\n", (char *)stream.data);
2993 		response = iks_new_iq_result(etdata->node);
2994 		api_result = iks_insert(response, "response");
2995 		iks_insert_attrib(api_result, "xmlns", RAYO_NS);
2996 		iks_insert_attrib(api_result, "response", zstr((char *)stream.data) ? "" : (char *)stream.data);
2997 	}
2998 
2999 	RAYO_SEND_REPLY(globals.server, iks_find_attrib(response, "to"), response);
3000 
3001 	switch_safe_free(stream.data);
3002 	{
3003 		switch_memory_pool_t *pool = etdata->pool;
3004 		switch_core_destroy_memory_pool(&pool);
3005 	}
3006 	return NULL;
3007 }
3008 
3009 /**
3010  * Execute an API on the server
3011  * @param server handling the call
3012  * @param msg the request
3013  */
on_rayo_exec(struct rayo_actor * server,struct rayo_message * msg,void * data)3014 static iks *on_rayo_exec(struct rayo_actor *server, struct rayo_message *msg, void *data)
3015 {
3016 	iks *node = msg->payload;
3017 	switch_thread_t *thread;
3018 	switch_threadattr_t *thd_attr = NULL;
3019 	iks *exec = iks_find(node, "exec");
3020 	iks *response = NULL;
3021 	const char *api = iks_find_attrib_soft(exec, "api");
3022 
3023 	if (zstr(api)) {
3024 		response = iks_new_error_detailed(node, STANZA_ERROR_BAD_REQUEST, "missing <exec> api attribute");
3025 	} else {
3026 		struct exec_thread_data *etdata = NULL;
3027 		switch_memory_pool_t *pool = NULL;
3028 		switch_core_new_memory_pool(&pool);
3029 		etdata = switch_core_alloc(pool, sizeof(*etdata));
3030 		etdata->pool = pool;
3031 		etdata->node = iks_copy(node);
3032 
3033 		/* start exec thread */
3034 		switch_threadattr_create(&thd_attr, pool);
3035 		switch_threadattr_detach_set(thd_attr, 1);
3036 		switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
3037 		switch_thread_create(&thread, thd_attr, rayo_exec_thread, etdata, pool);
3038 	}
3039 	return response;
3040 }
3041 
3042 /**
3043  * Handle <iq><ping> request
3044  * @param rclient the Rayo client
3045  * @param server the Rayo server
3046  * @param node the <iq> node
3047  * @return NULL
3048  */
on_iq_xmpp_ping(struct rayo_actor * server,struct rayo_message * msg,void * data)3049 static iks *on_iq_xmpp_ping(struct rayo_actor *server, struct rayo_message *msg, void *data)
3050 {
3051 	iks *node = msg->payload;
3052 	iks *pong = iks_new("iq");
3053 	char *from = iks_find_attrib(node, "from");
3054 	char *to = iks_find_attrib(node, "to");
3055 
3056 	if (zstr(from)) {
3057 		from = msg->from_jid;
3058 	}
3059 
3060 	if (zstr(to)) {
3061 		to = RAYO_JID(server);
3062 	}
3063 
3064 	iks_insert_attrib(pong, "type", "result");
3065 	iks_insert_attrib(pong, "from", to);
3066 	iks_insert_attrib(pong, "to", from);
3067 	iks_insert_attrib(pong, "id", iks_find_attrib(node, "id"));
3068 
3069 	return pong;
3070 }
3071 
3072 /**
3073  * Handle service discovery request
3074  * @param rclient the Rayo client
3075  * @param server the Rayo server
3076  * @param node the <iq> node
3077  * @return NULL
3078  */
on_iq_get_xmpp_disco(struct rayo_actor * server,struct rayo_message * msg,void * data)3079 static iks *on_iq_get_xmpp_disco(struct rayo_actor *server, struct rayo_message *msg, void *data)
3080 {
3081 	iks *node = msg->payload;
3082 	iks *response = NULL;
3083 	iks *x;
3084 	iks *feature;
3085 	iks *identity;
3086 	int i = 0;
3087 	const char *feature_string;
3088 	response = iks_new_iq_result(node);
3089 	x = iks_insert(response, "query");
3090 	iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_DISCO);
3091 	identity = iks_insert(x, "identity");
3092 	iks_insert_attrib(identity, "category", rayo_server_identity.category);
3093 	iks_insert_attrib(identity, "type", rayo_server_identity.type);
3094 	i = 0;
3095 	while((feature_string = rayo_server_features[i++])) {
3096 		feature = iks_insert(x, "feature");
3097 		iks_insert_attrib(feature, "var", feature_string);
3098 	}
3099 
3100 	/* TODO The response MUST also include features for the application formats and transport methods supported by
3101 	 * the responding entity, as described in the relevant specifications.
3102 	 */
3103 
3104 	return response;
3105 }
3106 
3107 /**
3108  * Handle message from client
3109  * @param rclient that sent the command
3110  * @param message the message
3111  */
on_client_message(struct rayo_client * rclient,iks * message)3112 static void on_client_message(struct rayo_client *rclient, iks *message)
3113 {
3114 	const char *to = iks_find_attrib(message, "to");
3115 
3116 	/* must be directed to a client */
3117 	if (zstr(to)) {
3118 		return;
3119 	}
3120 
3121 	/* assume client source */
3122 	if (zstr(iks_find_attrib(message, "from"))) {
3123 		iks_insert_attrib(message, "from", RAYO_JID(rclient));
3124 	}
3125 
3126 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, recv message, availability = %s\n", RAYO_JID(rclient), presence_status_to_string(rclient->availability));
3127 
3128 	RAYO_SEND_MESSAGE_DUP(rclient, to, message);
3129 }
3130 
3131 /**
3132  * Handle <presence> message from a client
3133  * @param rclient the client
3134  * @param node the presence message
3135  */
on_client_presence(struct rayo_client * rclient,iks * node)3136 static void on_client_presence(struct rayo_client *rclient, iks *node)
3137 {
3138 	char *type = iks_find_attrib(node, "type");
3139 	enum presence_status status = PS_UNKNOWN;
3140 
3141 	/*
3142 	   From RFC-6121:
3143 	   Entity is available when <presence/> received.
3144 	   Entity is unavailable when <presence type='unavailable'/> is received.
3145 
3146 	   From Rayo-XEP:
3147 	   Entity is available when <presence to='foo' from='bar'><show>chat</show></presence> is received.
3148 	   Entity is unavailable when <presence to='foo' from='bar'><show>dnd</show></presence> is received.
3149 	*/
3150 
3151 	/* figure out if online/offline */
3152 	if (zstr(type)) {
3153 		/* <presence><show>chat</show></presence> */
3154 		char *status_str = iks_find_cdata(node, "show");
3155 		if (!zstr(status_str)) {
3156 			if (!strcmp("chat", status_str)) {
3157 				status = PS_ONLINE;
3158 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s got chat presence\n", RAYO_JID(rclient));
3159 			} else if (!strcmp("dnd", status_str)) {
3160 				status = PS_OFFLINE;
3161 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s got dnd presence\n", RAYO_JID(rclient));
3162 			}
3163 		} else {
3164 			/* <presence/> */
3165 			status = PS_ONLINE;
3166 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s got empty presence\n", RAYO_JID(rclient));
3167 		}
3168 	} else if (!strcmp("unavailable", type)) {
3169 		status = PS_OFFLINE;
3170 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s got unavailable presence\n", RAYO_JID(rclient));
3171 	} else if (!strcmp("error", type)) {
3172 		/* TODO presence error */
3173 	} else if (!strcmp("probe", type)) {
3174 		/* TODO presence probe */
3175 	} else if (!strcmp("subscribe", type)) {
3176 		/* TODO presence subscribe */
3177 	} else if (!strcmp("subscribed", type)) {
3178 		/* TODO presence subscribed */
3179 	} else if (!strcmp("unsubscribe", type)) {
3180 		/* TODO presence unsubscribe */
3181 	} else if (!strcmp("unsubscribed", type)) {
3182 		/* TODO presence unsubscribed */
3183 	}
3184 
3185 	if (status == PS_ONLINE && rclient->availability != PS_ONLINE) {
3186 		rclient->availability = PS_ONLINE;
3187 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s is ONLINE\n", RAYO_JID(rclient));
3188 	} else if (status == PS_OFFLINE && rclient->availability != PS_OFFLINE) {
3189 		rclient->availability = PS_OFFLINE;
3190 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s is OFFLINE\n", RAYO_JID(rclient));
3191 	}
3192 
3193 	/* destroy if not a local client (connected via peer_server) and is OFFLINE */
3194 	if (rclient->peer_server && rclient->availability == PS_OFFLINE) {
3195 		RAYO_DESTROY(rclient);
3196 		RAYO_RELEASE(rclient);
3197 	}
3198 
3199 	pause_when_offline();
3200 }
3201 
3202 /**
3203  * Handle command from client
3204  * @param rclient that sent the command
3205  * @param iq the command
3206  */
rayo_client_command_recv(struct rayo_client * rclient,iks * iq)3207 static void rayo_client_command_recv(struct rayo_client *rclient, iks *iq)
3208 {
3209 	iks *command = iks_first_tag(iq);
3210 	const char *to = iks_find_attrib(iq, "to");
3211 
3212 	/* assume server destination */
3213 	if (zstr(to)) {
3214 		to = RAYO_JID(globals.server);
3215 		iks_insert_attrib(iq, "to", to);
3216 	}
3217 
3218 	/* assume client source */
3219 	if (zstr(iks_find_attrib(iq, "from"))) {
3220 		iks_insert_attrib(iq, "from", RAYO_JID(rclient));
3221 	}
3222 
3223 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, recv iq, availability = %s\n", RAYO_JID(rclient), presence_status_to_string(rclient->availability));
3224 
3225 	if (command) {
3226 		RAYO_SEND_MESSAGE_DUP(rclient, to, iq);
3227 	} else {
3228 		const char *type = iks_find_attrib_soft(iq, "type");
3229 		if (strcmp("error", type) && strcmp("result", type)) {
3230 			RAYO_SEND_REPLY(globals.server, RAYO_JID(rclient), iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "empty IQ request"));
3231 		}
3232 	}
3233 }
3234 
3235 /**
3236  * Send event to mixer subscribers
3237  * @param mixer the mixer
3238  * @param rayo_event the event to send
3239  */
broadcast_mixer_event(struct rayo_mixer * mixer,iks * rayo_event)3240 static void broadcast_mixer_event(struct rayo_mixer *mixer, iks *rayo_event)
3241 {
3242 	switch_hash_index_t *hi = NULL;
3243 	switch_mutex_lock(RAYO_ACTOR(mixer)->mutex);
3244 	for (hi = switch_core_hash_first(mixer->subscribers); hi; hi = switch_core_hash_next(&hi)) {
3245 		const void *key;
3246 		void *val;
3247 		struct rayo_mixer_subscriber *subscriber;
3248 		switch_core_hash_this(hi, &key, NULL, &val);
3249 		subscriber = (struct rayo_mixer_subscriber *)val;
3250 		switch_assert(subscriber);
3251 		iks_insert_attrib(rayo_event, "to", subscriber->jid);
3252 		RAYO_SEND_MESSAGE_DUP(mixer, subscriber->jid, rayo_event);
3253 	}
3254 	switch_mutex_unlock(RAYO_ACTOR(mixer)->mutex);
3255 }
3256 
3257 /**
3258  * Handle mixer delete member event
3259  */
on_mixer_delete_member_event(struct rayo_mixer * mixer,switch_event_t * event)3260 static void on_mixer_delete_member_event(struct rayo_mixer *mixer, switch_event_t *event)
3261 {
3262 	iks *delete_member_event, *x;
3263 	const char *uuid = switch_event_get_header(event, "Unique-ID");
3264 	struct rayo_call *call;
3265 	struct rayo_mixer_member *member;
3266 	struct rayo_mixer_subscriber *subscriber;
3267 
3268 	/* not a rayo mixer */
3269 	if (!mixer) {
3270 		return;
3271 	}
3272 
3273 	/* remove member from mixer */
3274 	switch_mutex_lock(RAYO_ACTOR(mixer)->mutex);
3275 	member = (struct rayo_mixer_member *)switch_core_hash_find(mixer->members, uuid);
3276 	if (!member) {
3277 		/* not a member */
3278 		switch_mutex_unlock(RAYO_ACTOR(mixer)->mutex);
3279 		return;
3280 	}
3281 	switch_core_hash_delete(mixer->members, uuid);
3282 	switch_mutex_unlock(RAYO_ACTOR(mixer)->mutex);
3283 
3284 	/* flag call as available to join another mixer */
3285 	call = RAYO_CALL_LOCATE_BY_ID(uuid);
3286 	if (call) {
3287 		switch_mutex_lock(RAYO_ACTOR(call)->mutex);
3288 		call->joined = 0;
3289 		call->joined_id = NULL;
3290 		switch_mutex_unlock(RAYO_ACTOR(call)->mutex);
3291 		RAYO_RELEASE(call);
3292 	}
3293 
3294 	/* send mixer unjoined event to member DCP */
3295 	delete_member_event = iks_new_presence("unjoined", RAYO_NS, member->jid, member->dcp_jid);
3296 	x = iks_find(delete_member_event, "unjoined");
3297 	iks_insert_attrib(x, "mixer-name", rayo_mixer_get_name(mixer));
3298 	RAYO_SEND_MESSAGE(mixer, member->dcp_jid, delete_member_event);
3299 
3300 	/* broadcast member unjoined event to subscribers */
3301 	delete_member_event = iks_new_presence("unjoined", RAYO_NS, RAYO_JID(mixer), "");
3302 	x = iks_find(delete_member_event, "unjoined");
3303 	iks_insert_attrib_printf(x, "call-uri", "xmpp:%s@%s", uuid, RAYO_JID(globals.server));
3304 	broadcast_mixer_event(mixer, delete_member_event);
3305 	iks_delete(delete_member_event);
3306 
3307 	/* remove member DCP as subscriber to mixer */
3308 	switch_mutex_lock(RAYO_ACTOR(mixer)->mutex);
3309 	subscriber = (struct rayo_mixer_subscriber *)switch_core_hash_find(mixer->subscribers, member->dcp_jid);
3310 	if (subscriber) {
3311 		subscriber->ref_count--;
3312 		if (subscriber->ref_count <= 0) {
3313 			switch_core_hash_delete(mixer->subscribers, member->dcp_jid);
3314 		}
3315 	}
3316 	switch_mutex_unlock(RAYO_ACTOR(mixer)->mutex);
3317 }
3318 
3319 /**
3320  * Handle mixer destroy event
3321  */
on_mixer_destroy_event(struct rayo_mixer * mixer,switch_event_t * event)3322 static void on_mixer_destroy_event(struct rayo_mixer *mixer, switch_event_t *event)
3323 {
3324 	if (mixer) {
3325 		iks *presence;
3326 
3327 		/* notify online clients of mixer destruction */
3328 		presence = iks_new("presence");
3329 		iks_insert_attrib(presence, "from", RAYO_JID(mixer));
3330 		iks_insert_attrib(presence, "type", "unavailable");
3331 		broadcast_event(RAYO_ACTOR(mixer), presence, 1);
3332 		iks_delete(presence);
3333 
3334 		/* remove from hash and destroy */
3335 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, destroying mixer: %s\n", RAYO_JID(mixer), rayo_mixer_get_name(mixer));
3336 		RAYO_RELEASE(mixer); /* release original lock */
3337 		RAYO_DESTROY(mixer);
3338 	} else {
3339 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "destroy: NULL mixer\n");
3340 	}
3341 }
3342 
3343 /**
3344  * Handle mixer add member event
3345  */
on_mixer_add_member_event(struct rayo_mixer * mixer,switch_event_t * event)3346 static void on_mixer_add_member_event(struct rayo_mixer *mixer, switch_event_t *event)
3347 {
3348 	iks *add_member_event = NULL, *x;
3349 	const char *uuid = switch_event_get_header(event, "Unique-ID");
3350 	struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(uuid);
3351 	struct rayo_mixer *lmixer = NULL;
3352 
3353 	if (!mixer) {
3354 		char *ver;
3355 		iks *presence, *c;
3356 
3357 		/* new mixer */
3358 		const char *mixer_name = switch_event_get_header(event, "Conference-Name");
3359 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "creating mixer: %s\n", mixer_name);
3360 		mixer = rayo_mixer_create(mixer_name);
3361 		if (mixer) {
3362 			/* notify online clients of mixer presence */
3363 			ver = calculate_entity_sha1_ver(&rayo_mixer_identity, rayo_mixer_features);
3364 
3365 			presence = iks_new_presence("c", IKS_NS_XMPP_ENTITY_CAPABILITIES, RAYO_JID(mixer), "");
3366 			c = iks_find(presence, "c");
3367 			iks_insert_attrib(c, "hash", "sha-1");
3368 			iks_insert_attrib(c, "node", RAYO_MIXER_NS);
3369 			iks_insert_attrib(c, "ver", ver);
3370 			free(ver);
3371 
3372 			broadcast_event(RAYO_ACTOR(mixer), presence, 1);
3373 		} else {
3374 			/* must have lost the race to another add member event...  there should be a mixer with mixer_name already */
3375 			mixer = lmixer = RAYO_MIXER_LOCATE(mixer_name);
3376 			if (!mixer) {
3377 				/* this is unexpected */
3378 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "failed to find mixer: %s\n", mixer_name);
3379 				return;
3380 			}
3381 		}
3382 	}
3383 
3384 	if (call) {
3385 		struct rayo_mixer_member *member = NULL;
3386 		/* add member DCP as subscriber to mixer */
3387 		struct rayo_mixer_subscriber *subscriber;
3388 		switch_mutex_lock(RAYO_ACTOR(mixer)->mutex);
3389 		subscriber = (struct rayo_mixer_subscriber *)switch_core_hash_find(mixer->subscribers, call->dcp_jid);
3390 		if (!subscriber) {
3391 			subscriber = switch_core_alloc(RAYO_POOL(mixer), sizeof(*subscriber));
3392 			subscriber->ref_count = 0;
3393 			subscriber->jid = switch_core_strdup(RAYO_POOL(mixer), call->dcp_jid);
3394 			switch_core_hash_insert(mixer->subscribers, call->dcp_jid, subscriber);
3395 		}
3396 		subscriber->ref_count++;
3397 
3398 		/* add call as member of mixer */
3399 		member = switch_core_alloc(RAYO_POOL(mixer), sizeof(*member));
3400 		member->jid = switch_core_strdup(RAYO_POOL(mixer), RAYO_JID(call));
3401 		member->dcp_jid = subscriber->jid;
3402 		switch_core_hash_insert(mixer->members, uuid, member);
3403 
3404 		switch_mutex_unlock(RAYO_ACTOR(mixer)->mutex);
3405 
3406 		switch_mutex_lock(RAYO_ACTOR(call)->mutex);
3407 		call->joined = JOINED_MIXER;
3408 		call->joined_id = switch_core_strdup(RAYO_POOL(call), rayo_mixer_get_name(mixer));
3409 
3410 		/* send IQ result to client now. */
3411 		if (call->pending_join_request) {
3412 			iks *request = call->pending_join_request;
3413 			iks *result = iks_new_iq_result(request);
3414 			iks *ref = iks_insert(result, "ref");
3415 			iks_insert_attrib(ref, "xmlns", RAYO_NS);
3416 			iks_insert_attrib_printf(ref, "uri", "xmpp:%s", RAYO_JID(mixer));
3417 			call->pending_join_request = NULL;
3418 			RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
3419 			iks_delete(request);
3420 		}
3421 		switch_mutex_unlock(RAYO_ACTOR(call)->mutex);
3422 
3423 		/* send mixer joined event to member DCP */
3424 		add_member_event = iks_new_presence("joined", RAYO_NS, RAYO_JID(call), call->dcp_jid);
3425 		x = iks_find(add_member_event, "joined");
3426 		iks_insert_attrib(x, "mixer-name", rayo_mixer_get_name(mixer));
3427 		RAYO_SEND_MESSAGE(call, call->dcp_jid, add_member_event);
3428 
3429 		RAYO_RELEASE(call);
3430 	}
3431 
3432 	/* broadcast member joined event to subscribers */
3433 	add_member_event = iks_new_presence("joined", RAYO_NS, RAYO_JID(mixer), "");
3434 	x = iks_find(add_member_event, "joined");
3435 	iks_insert_attrib_printf(x, "call-uri", "xmpp:%s@%s", uuid, RAYO_JID(globals.server));
3436 	broadcast_mixer_event(mixer, add_member_event);
3437 	iks_delete(add_member_event);
3438 
3439 	if (lmixer) {
3440 		RAYO_RELEASE(lmixer);
3441 	}
3442 }
3443 
3444 /**
3445  * Receives mixer events from FreeSWITCH core and routes them to the proper Rayo client(s).
3446  * @param event received from FreeSWITCH core.  It will be destroyed by the core after this function returns.
3447  */
route_mixer_event(switch_event_t * event)3448 static void route_mixer_event(switch_event_t *event)
3449 {
3450 	const char *action = switch_event_get_header(event, "Action");
3451 	const char *profile = switch_event_get_header(event, "Conference-Profile-Name");
3452 	const char *mixer_name = switch_event_get_header(event, "Conference-Name");
3453 	struct rayo_mixer *mixer = NULL;
3454 
3455 	if (strcmp(profile, globals.mixer_conf_profile)) {
3456 		/* don't care about other conferences */
3457 		goto done;
3458 	}
3459 
3460 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "looking for mixer: %s\n", mixer_name);
3461 	mixer = RAYO_MIXER_LOCATE(mixer_name);
3462 
3463 	if (!strcmp("add-member", action)) {
3464 		on_mixer_add_member_event(mixer, event);
3465 	} else if (!strcmp("conference-destroy", action)) {
3466 		on_mixer_destroy_event(mixer, event);
3467 	} else if (!strcmp("del-member", action)) {
3468 		on_mixer_delete_member_event(mixer, event);
3469 	}
3470 	/* TODO speaking events */
3471 
3472 done:
3473 	RAYO_RELEASE(mixer);
3474 }
3475 
3476 /**
3477  * Handle call originate event - create rayo call and send <iq><ref> to client.
3478  * @param rclient The Rayo client
3479  * @param event the originate event
3480  */
on_call_originate_event(struct rayo_client * rclient,switch_event_t * event)3481 static void on_call_originate_event(struct rayo_client *rclient, switch_event_t *event)
3482 {
3483 	const char *uuid = switch_event_get_header(event, "Unique-ID");
3484 	struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(uuid);
3485 
3486 	if (call) {
3487 		iks *response, *ref;
3488 
3489 		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_ID(call)), SWITCH_LOG_DEBUG, "Got originate event\n");
3490 
3491 		switch_mutex_lock(RAYO_ACTOR(call)->mutex);
3492 		if (!zstr(call->dial_request_id)) {
3493 			/* send response to DCP */
3494 			response = iks_new("iq");
3495 			iks_insert_attrib(response, "from", RAYO_JID(globals.server));
3496 			iks_insert_attrib(response, "to", rayo_call_get_dcp_jid(call));
3497 			iks_insert_attrib(response, "id", call->dial_request_id);
3498 			iks_insert_attrib(response, "type", "result");
3499 			ref = iks_insert(response, "ref");
3500 			iks_insert_attrib(ref, "xmlns", RAYO_NS);
3501 
3502 			iks_insert_attrib_printf(ref, "uri", "xmpp:%s", RAYO_JID(call));
3503 			RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), response);
3504 			call->dial_request_id = NULL;
3505 		}
3506 		switch_mutex_unlock(RAYO_ACTOR(call)->mutex);
3507 	}
3508 	RAYO_RELEASE(call);
3509 }
3510 
3511 /**
3512  * Handle call end event
3513  * @param event the hangup event
3514  */
on_call_end_event(switch_event_t * event)3515 static void on_call_end_event(switch_event_t *event)
3516 {
3517 	struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(switch_event_get_header(event, "Unique-ID"));
3518 
3519 	if (call) {
3520 #if 0
3521 		char *event_str;
3522 		if (switch_event_serialize(event, &event_str, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
3523 			switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_DEBUG, "%s\n", event_str);
3524 			switch_safe_free(event_str);
3525 		}
3526 #endif
3527 		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_ID(call)), SWITCH_LOG_DEBUG, "Got channel destroy event\n");
3528 
3529 		switch_mutex_lock(RAYO_ACTOR(call)->mutex);
3530 		if (zstr(call->dial_request_id) && !call->dial_request_failed) {
3531 			switch_event_dup(&call->end_event, event);
3532 			RAYO_DESTROY(call);
3533 			RAYO_RELEASE(call); /* decrement ref from creation */
3534 		}
3535 		switch_mutex_unlock(RAYO_ACTOR(call)->mutex);
3536 		RAYO_RELEASE(call); /* decrement this ref */
3537 	}
3538 }
3539 
3540 /**
3541  * Handle call answer event
3542  * @param rclient the Rayo client
3543  * @param event the answer event
3544  */
on_call_answer_event(struct rayo_client * rclient,switch_event_t * event)3545 static void on_call_answer_event(struct rayo_client *rclient, switch_event_t *event)
3546 {
3547 	struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(switch_event_get_header(event, "Unique-ID"));
3548 	if (call) {
3549 		switch_mutex_lock(RAYO_ACTOR(call)->mutex);
3550 		if (call->rayo_app_started) {
3551 			iks *revent = iks_new_presence("answered", RAYO_NS,
3552 				switch_event_get_header(event, "variable_rayo_call_jid"),
3553 				switch_event_get_header(event, "variable_rayo_dcp_jid"));
3554 			add_headers_to_event(iks_find(revent, "answered"), event, globals.add_variables_to_events);
3555 			RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent);
3556 		} else if (!call->answer_event) {
3557 			/* delay sending this event until the rayo APP has started */
3558 			switch_event_dup(&call->answer_event, event);
3559 		}
3560 		switch_mutex_unlock(RAYO_ACTOR(call)->mutex);
3561 		RAYO_RELEASE(call);
3562 	}
3563 }
3564 
3565 /**
3566  * Handle call ringing event
3567  * @param rclient the Rayo client
3568  * @param event the ringing event
3569  */
on_call_ringing_event(struct rayo_client * rclient,switch_event_t * event)3570 static void on_call_ringing_event(struct rayo_client *rclient, switch_event_t *event)
3571 {
3572 	const char *call_direction = switch_event_get_header(event, "Call-Direction");
3573 	if (call_direction && !strcmp(call_direction, "outbound")) {
3574 		struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(switch_event_get_header(event, "Unique-ID"));
3575 		if (call) {
3576 			switch_mutex_lock(RAYO_ACTOR(call)->mutex);
3577 			if (!call->ringing_sent) {
3578 				iks *revent = iks_new_presence("ringing", RAYO_NS,
3579 					switch_event_get_header(event, "variable_rayo_call_jid"),
3580 					switch_event_get_header(event, "variable_rayo_dcp_jid"));
3581 				add_headers_to_event(iks_find(revent, "ringing"), event, globals.add_variables_to_events);
3582 				call->ringing_sent = 1;
3583 				RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent);
3584 			}
3585 			switch_mutex_unlock(RAYO_ACTOR(call)->mutex);
3586 			RAYO_RELEASE(call);
3587 		}
3588 	}
3589 }
3590 
3591 /**
3592  * Handle call bridge event
3593  * @param rclient the Rayo client
3594  * @param event the bridge event
3595  */
on_call_bridge_event(struct rayo_client * rclient,switch_event_t * event)3596 static void on_call_bridge_event(struct rayo_client *rclient, switch_event_t *event)
3597 {
3598 	const char *a_uuid = switch_event_get_header(event, "Unique-ID");
3599 	const char *b_uuid = switch_event_get_header(event, "Bridge-B-Unique-ID");
3600 	struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(a_uuid);
3601 	struct rayo_call *b_call;
3602 
3603 	if (call) {
3604 		iks *revent;
3605 		iks *joined;
3606 
3607 		call->joined = JOINED_CALL;
3608 		call->joined_id = switch_core_sprintf(RAYO_POOL(call), "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server));
3609 
3610 		/* send IQ result to client now. */
3611 		if (call->pending_join_request) {
3612 			iks *request = call->pending_join_request;
3613 			iks *result = iks_new_iq_result(request);
3614 			call->pending_join_request = NULL;
3615 			RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
3616 			iks_delete(request);
3617 		}
3618 
3619 		b_call = RAYO_CALL_LOCATE_BY_ID(b_uuid);
3620 		if (b_call) {
3621 			b_call->joined = JOINED_CALL;
3622 			b_call->joined_id = switch_core_sprintf(RAYO_POOL(b_call), "xmpp:%s@%s", a_uuid, RAYO_JID(globals.server));
3623 
3624 			/* send IQ result to client now. */
3625 			if (b_call->pending_join_request) {
3626 				iks *request = b_call->pending_join_request;
3627 				iks *result = iks_new_iq_result(request);
3628 				b_call->pending_join_request = NULL;
3629 				RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
3630 				iks_delete(request);
3631 			}
3632 
3633 			/* send B-leg event */
3634 			revent = iks_new_presence("joined", RAYO_NS, RAYO_JID(b_call), rayo_call_get_dcp_jid(b_call));
3635 			joined = iks_find(revent, "joined");
3636 			iks_insert_attrib_printf(joined, "call-uri", "%s", b_call->joined_id);
3637 
3638 			RAYO_SEND_MESSAGE(b_call, rayo_call_get_dcp_jid(b_call), revent);
3639 			RAYO_RELEASE(b_call);
3640 		}
3641 
3642 		/* send A-leg event */
3643 		revent = iks_new_presence("joined", RAYO_NS,
3644 			switch_event_get_header(event, "variable_rayo_call_jid"),
3645 			switch_event_get_header(event, "variable_rayo_dcp_jid"));
3646 		joined = iks_find(revent, "joined");
3647 		iks_insert_attrib_printf(joined, "call-uri", "%s", call->joined_id);
3648 
3649 		RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent);
3650 
3651 		RAYO_RELEASE(call);
3652 	}
3653 }
3654 
3655 /**
3656  * Handle call park event - this is fired after unjoining a call
3657  * @param rclient the Rayo client
3658  * @param event the unbridge event
3659  */
on_call_park_event(struct rayo_client * rclient,switch_event_t * event)3660 static void on_call_park_event(struct rayo_client *rclient, switch_event_t *event)
3661 {
3662 	const char *a_uuid = switch_event_get_header(event, "Unique-ID");
3663 	struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(a_uuid);
3664 
3665 	if (call) {
3666 		if (call->joined) {
3667 			iks *revent;
3668 			iks *unjoined;
3669 			const char *joined_id = call->joined_id;
3670 
3671 			call->joined = 0;
3672 			call->joined_id = NULL;
3673 
3674 			/* send IQ result to client now. */
3675 			if (call->pending_join_request) {
3676 				iks *request = call->pending_join_request;
3677 				iks *result = iks_new_iq_result(request);
3678 				call->pending_join_request = NULL;
3679 				RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
3680 				iks_delete(request);
3681 			}
3682 
3683 			/* send A-leg event */
3684 			revent = iks_new_presence("unjoined", RAYO_NS,
3685 				switch_event_get_header(event, "variable_rayo_call_jid"),
3686 				switch_event_get_header(event, "variable_rayo_dcp_jid"));
3687 			unjoined = iks_find(revent, "unjoined");
3688 			iks_insert_attrib_printf(unjoined, "call-uri", "%s", joined_id);
3689 			RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent);
3690 		}
3691 		RAYO_RELEASE(call);
3692 	}
3693 }
3694 
3695 /**
3696  * Handle call execute application event
3697  * @param rclient the Rayo client
3698  * @param event the execute event
3699  */
on_call_execute_event(struct rayo_client * rclient,switch_event_t * event)3700 static void on_call_execute_event(struct rayo_client *rclient, switch_event_t *event)
3701 {
3702 	struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(switch_event_get_header(event, "Unique-ID"));
3703 	if (call) {
3704 		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_ID(call)), SWITCH_LOG_DEBUG, "Application %s execute\n", switch_event_get_header(event, "Application"));
3705 		RAYO_RELEASE(call);
3706 	}
3707 }
3708 
3709 /**
3710  * Handle call execute application complete event
3711  * @param rclient the Rayo client
3712  * @param event the execute complete event
3713  */
on_call_execute_complete_event(struct rayo_client * rclient,switch_event_t * event)3714 static void on_call_execute_complete_event(struct rayo_client *rclient, switch_event_t *event)
3715 {
3716 	struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(switch_event_get_header(event, "Unique-ID"));
3717 	if (call) {
3718 		const char *app = switch_event_get_header(event, "Application");
3719 		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_ID(call)), SWITCH_LOG_DEBUG, "Application %s execute complete: %s \n",
3720 			app,
3721 			switch_event_get_header(event, "Application-Response"));
3722 		RAYO_RELEASE(call);
3723 	}
3724 }
3725 
3726 /**
3727  * Handle events to deliver to client connection
3728  * @param rclient the Rayo client connection to receive the event
3729  * @param event the event.
3730  */
rayo_client_handle_event(struct rayo_client * rclient,switch_event_t * event)3731 static void rayo_client_handle_event(struct rayo_client *rclient, switch_event_t *event)
3732 {
3733 	if (event) {
3734 		switch (event->event_id) {
3735 		case SWITCH_EVENT_CHANNEL_ORIGINATE:
3736 			on_call_originate_event(rclient, event);
3737 			break;
3738 		case SWITCH_EVENT_CHANNEL_PROGRESS:
3739 		case SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA:
3740 			on_call_ringing_event(rclient, event);
3741 			break;
3742 		case SWITCH_EVENT_CHANNEL_ANSWER:
3743 			on_call_answer_event(rclient, event);
3744 			break;
3745 		case SWITCH_EVENT_CHANNEL_BRIDGE:
3746 			on_call_bridge_event(rclient, event);
3747 			break;
3748 		case SWITCH_EVENT_CHANNEL_PARK:
3749 			on_call_park_event(rclient, event);
3750 			break;
3751 		case SWITCH_EVENT_CHANNEL_EXECUTE:
3752 			on_call_execute_event(rclient, event);
3753 			break;
3754 		case SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE:
3755 			on_call_execute_complete_event(rclient, event);
3756 			break;
3757 		default:
3758 			/* don't care */
3759 			break;
3760 		}
3761 	}
3762 }
3763 
3764 /**
3765  * Receives events from FreeSWITCH core and routes them to the proper Rayo client.
3766  * @param event received from FreeSWITCH core.  It will be destroyed by the core after this function returns.
3767  */
route_call_event(switch_event_t * event)3768 static void route_call_event(switch_event_t *event)
3769 {
3770 	char *uuid = switch_event_get_header(event, "unique-id");
3771 	char *dcp_jid = switch_event_get_header(event, "variable_rayo_dcp_jid");
3772 	char *event_subclass = switch_event_get_header(event, "Event-Subclass");
3773 
3774 	switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "got event %s %s\n", switch_event_name(event->event_id), zstr(event_subclass) ? "" : event_subclass);
3775 
3776 	/* this event is for a rayo client */
3777 	if (!zstr(dcp_jid)) {
3778 		struct rayo_actor *actor;
3779 		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "%s rayo event %s\n", dcp_jid, switch_event_name(event->event_id));
3780 
3781 		actor = RAYO_LOCATE(dcp_jid);
3782 		if (actor && !strcmp(RAT_CLIENT, actor->type)) {
3783 			/* route to client */
3784 			rayo_client_handle_event(RAYO_CLIENT(actor), event);
3785 		} else {
3786 			/* TODO orphaned call... maybe allow events to queue so they can be delivered on reconnect? */
3787 			switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Orphaned call event %s to %s\n", switch_event_name(event->event_id), dcp_jid);
3788 		}
3789 		RAYO_RELEASE(actor);
3790 	}
3791 }
3792 
3793 /**
3794  * Create server.
3795  * @param domain the domain name
3796  * @return the domain
3797  */
rayo_server_create(const char * domain)3798 static struct rayo_actor *rayo_server_create(const char *domain)
3799 {
3800 	switch_memory_pool_t *pool;
3801 	struct rayo_actor *new_server = NULL;
3802 
3803 	switch_core_new_memory_pool(&pool);
3804 	new_server = switch_core_alloc(pool, sizeof(*new_server));
3805 	RAYO_ACTOR_INIT(RAYO_ACTOR(new_server), pool, RAT_SERVER, "", domain, domain, NULL, rayo_server_send);
3806 
3807 	return new_server;
3808 }
3809 
3810 /**
3811  * Create an offer for a call
3812  * @param call the call
3813  * @param session the session
3814  * @return the offer
3815  */
rayo_create_offer(struct rayo_call * call,switch_core_session_t * session)3816 static iks *rayo_create_offer(struct rayo_call *call, switch_core_session_t *session)
3817 {
3818 	switch_channel_t *channel = switch_core_session_get_channel(session);
3819 	switch_caller_profile_t *profile = switch_channel_get_caller_profile(channel);
3820 	iks *presence = iks_new("presence");
3821 	iks *c = iks_insert(presence, "c");
3822 	iks *offer = iks_insert(presence, "offer");
3823 	const char *val;
3824 	char *ver;
3825 
3826 	/* <presence> */
3827 	iks_insert_attrib(presence, "from", RAYO_JID(call));
3828 
3829 	/* <c> */
3830 	ver = calculate_entity_sha1_ver(&rayo_call_identity, rayo_call_features);
3831 	iks_insert_attrib(c, "xmlns", IKS_NS_XMPP_ENTITY_CAPABILITIES);
3832 	iks_insert_attrib(c, "hash", "sha-1");
3833 	iks_insert_attrib(c, "node", RAYO_CALL_NS);
3834 	iks_insert_attrib(c, "ver", ver);
3835 	free(ver);
3836 
3837 	/* <offer> */
3838 	iks_insert_attrib(offer, "xmlns", RAYO_NS);
3839 	if (globals.offer_uri && (val = switch_channel_get_variable(channel, "sip_from_uri"))) {
3840 		/* is a SIP call - pass the URI */
3841 		if (!strchr(val, ':')) {
3842 			iks_insert_attrib_printf(offer, "from", "sip:%s", val);
3843 		} else {
3844 			iks_insert_attrib(offer, "from", val);
3845 		}
3846 	} else {
3847 		/* pass caller ID */
3848 		iks_insert_attrib(offer, "from", profile->caller_id_number);
3849 	}
3850 
3851 	if (globals.offer_uri && (val = switch_channel_get_variable(channel, "sip_to_uri"))) {
3852 		/* is a SIP call - pass the URI */
3853 		if (!strchr(val, ':')) {
3854 			iks_insert_attrib_printf(offer, "to", "sip:%s", val);
3855 		} else {
3856 			iks_insert_attrib(offer, "to", val);
3857 		}
3858 	} else {
3859 		/* pass dialed number */
3860 		iks_insert_attrib(offer, "to", profile->destination_number);
3861 	}
3862 
3863 	add_header(offer, "from", switch_channel_get_variable(channel, "sip_full_from"));
3864 	add_header(offer, "to", switch_channel_get_variable(channel, "sip_full_to"));
3865 	add_header(offer, "via", switch_channel_get_variable(channel, "sip_full_via"));
3866 	add_channel_headers_to_event(offer, channel, globals.add_variables_to_offer);
3867 
3868 	return presence;
3869 }
3870 
3871 /**
3872  * Monitor rayo call activity - detect idle
3873  */
rayo_call_on_read_frame(switch_core_session_t * session,switch_frame_t ** frame,switch_io_flag_t flags,int i)3874 static switch_status_t rayo_call_on_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int i)
3875 {
3876 	switch_channel_t *channel = switch_core_session_get_channel(session);
3877 	struct rayo_call *call = (struct rayo_call *)switch_channel_get_private(channel, "rayo_call_private");
3878 	if (call) {
3879 		switch_time_t now = switch_micro_time_now();
3880 		switch_time_t idle_start = call->idle_start_time;
3881 		int idle_duration_ms = (now - idle_start) / 1000;
3882 		/* detect idle session (rayo-client has stopped controlling call) and terminate call */
3883 		if (rayo_call_is_joined(call) || rayo_call_is_faxing(call) || RAYO_ACTOR(call)->ref_count > 1) {
3884 			call->idle_start_time = now;
3885 		} else if (idle_duration_ms > globals.max_idle_ms) {
3886 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Ending abandoned call.  idle_duration_ms = %i ms\n", idle_duration_ms);
3887 			switch_channel_hangup(channel, RAYO_CAUSE_HANGUP);
3888 		}
3889 	}
3890 	return SWITCH_STATUS_SUCCESS;
3891 }
3892 
3893 /**
3894  * @param rclient to check
3895  * @param offer_filters optional list of username or username@server to match with client JID.
3896  * @param offer_filter_count
3897  * @return 1 if client is online and optional filter(s) match the client.  0 otherwise.
3898  */
should_offer_to_client(struct rayo_client * rclient,char ** offer_filters,int offer_filter_count)3899 static int should_offer_to_client(struct rayo_client *rclient, char **offer_filters, int offer_filter_count)
3900 {
3901 	if (rclient->availability != PS_ONLINE) {
3902 		return 0;
3903 	}
3904 
3905 	if (offer_filter_count == 0) {
3906 		/* online and no filters to match */
3907 		return 1;
3908 	} else {
3909 		/* check if one of the filters matches the client */
3910 		int i;
3911 		const char *client_jid = RAYO_JID(rclient);
3912 		size_t client_jid_len = strlen(client_jid);
3913 		for (i = 0; i < offer_filter_count; i++) {
3914 			char *offer_filter = offer_filters[i];
3915 			if (!zstr(offer_filter)) {
3916 				size_t offer_filter_len = strlen(offer_filter);
3917 				if (strchr(offer_filter, '@')) {
3918 					if (offer_filter_len <= client_jid_len && !strncmp(offer_filter, client_jid, offer_filter_len)) {
3919 						/* username + server match */
3920 						return 1;
3921 					}
3922 				} else if (offer_filter_len < client_jid_len && !strncmp(offer_filter, client_jid, offer_filter_len) && client_jid[offer_filter_len] == '@') {
3923 					/* username match */
3924 					return 1;
3925 				}
3926 			}
3927 		}
3928 	}
3929 	return 0;
3930 }
3931 
3932 /**
3933  * Offered call information
3934  */
3935 struct offered_call_info {
3936 	/** Call JID */
3937 	char *call_jid;
3938 	/** Time this offer expires */
3939 	switch_time_t offer_time;
3940 };
3941 
3942 /**
3943  * Deliver offer message to next available client(s)
3944  */
send_offer_to_clients(struct rayo_call * from_call,switch_core_session_t * session)3945 static int send_offer_to_clients(struct rayo_call *from_call, switch_core_session_t *session)
3946 {
3947 	int i = 0;
3948 	int selection = 0;
3949 	int sent = 0;
3950 	switch_hash_index_t *hi = NULL;
3951 	iks *offer = NULL;
3952 
3953 	if (from_call->num_acps <= 0) {
3954 		return 0;
3955 	}
3956 
3957 	if (globals.offer_algorithm == OFFER_RANDOM) {
3958 		/* pick client at (not really) random */
3959 		selection = rand() % from_call->num_acps;
3960 	} else if (globals.offer_algorithm == OFFER_FIRST) {
3961 		/* send to first client */
3962 		selection = 0;
3963 	} else {
3964 		/* send to all clients */
3965 		selection = -1;
3966 	}
3967 
3968 	for (hi = switch_core_hash_first(from_call->acps); hi; hi = switch_core_hash_next(&hi)) {
3969 		if (i++ == selection || selection == -1) {
3970 			const char *to_client_jid = NULL;
3971 			const void *key;
3972 			void *val;
3973 
3974 			/* get client jid to send to */
3975 			switch_core_hash_this(hi, &key, NULL, &val);
3976 			to_client_jid = (const char *)key;
3977 			switch_assert(to_client_jid);
3978 
3979 			/* send offer to client, remembering jid as PCP */
3980 			if (!offer) {
3981 				offer = rayo_create_offer(from_call, session);
3982 			}
3983 			switch_core_hash_insert(from_call->pcps, to_client_jid, "1");
3984 			iks_insert_attrib(offer, "to", to_client_jid);
3985 			RAYO_SEND_MESSAGE_DUP(from_call, to_client_jid, offer);
3986 
3987 			sent = 1;
3988 			from_call->num_acps--;
3989 
3990 			if (selection != -1) {
3991 				break;
3992 			}
3993 		}
3994 	}
3995 	switch_safe_free(hi);
3996 
3997 	if (sent) {
3998 		/* remove offered client JID(s) from list of available clients */
3999 		hi = NULL;
4000 		for (hi = switch_core_hash_first(from_call->pcps); hi; hi = switch_core_hash_next(&hi)) {
4001 			const char *to_client_jid = NULL;
4002 			const void *key;
4003 			void *val;
4004 
4005 			/* get client jid that was sent offer */
4006 			switch_core_hash_this(hi, &key, NULL, &val);
4007 			to_client_jid = (const char *)key;
4008 			switch_assert(to_client_jid);
4009 
4010 			/* remove client jid from available controlling parties */
4011 			switch_core_hash_delete(from_call->acps, to_client_jid);
4012 		}
4013 		switch_safe_free(hi);
4014 
4015 		/* remember when offer was sent for this call to track timeouts */
4016 		if (globals.offer_timeout_us > 0) {
4017 			struct offered_call_info *offered_call;
4018 			switch_zmalloc(offered_call, sizeof(*offered_call));
4019 			offered_call->offer_time = switch_micro_time_now();
4020 			offered_call->call_jid = strdup(RAYO_JID(from_call));
4021 			if (switch_queue_trypush(globals.offer_queue, offered_call) != SWITCH_STATUS_SUCCESS) {
4022 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to queue offered call info!  Offer timeout won't work on this call\n");
4023 				switch_safe_free(offered_call->call_jid);
4024 				switch_safe_free(offered_call);
4025 			}
4026 		}
4027 	}
4028 
4029 	if (offer) {
4030 		iks_delete(offer);
4031 	}
4032 
4033 	return sent;
4034 }
4035 
4036 /**
4037  * Thread that monitors for timed out offers
4038  * @param thread this thread
4039  * @param obj unused
4040  * @return NULL
4041  */
offer_timeout_thread(switch_thread_t * thread,void * obj)4042 static void *SWITCH_THREAD_FUNC offer_timeout_thread(switch_thread_t *thread, void *obj)
4043 {
4044 	struct offered_call_info *next_offer;
4045 	switch_thread_rwlock_rdlock(globals.shutdown_rwlock);
4046 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "New offer timeout thread\n");
4047 	while (!globals.shutdown) {
4048 		if (switch_queue_pop(globals.offer_queue, (void *)&next_offer) == SWITCH_STATUS_SUCCESS) {
4049 			switch_time_t now = switch_micro_time_now();
4050 			switch_time_t offer_timeout = next_offer->offer_time + globals.offer_timeout_us;
4051 
4052 			/* wait for timeout */
4053 			while (offer_timeout > now && !globals.shutdown) {
4054 				switch_time_t remain = offer_timeout - now;
4055 				remain = remain > 500000 ? 500000 : remain;
4056 				switch_sleep(remain);
4057 				now = switch_micro_time_now();
4058 			}
4059 
4060 			/* check if offer was accepted - it is accepted if the call has a DCP (definitive controlling party) */
4061 			if (!globals.shutdown) {
4062 				struct rayo_call *call = RAYO_CALL_LOCATE(next_offer->call_jid);
4063 				if (call) {
4064 					switch_mutex_lock(RAYO_ACTOR(call)->mutex);
4065 					if (zstr(rayo_call_get_dcp_jid(call))) {
4066 						switch_core_session_t *session = switch_core_session_locate(rayo_call_get_uuid(call));
4067 						if (session) {
4068 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, offer timeout\n", RAYO_JID(call));
4069 							if (!send_offer_to_clients(call, session)) {
4070 								/* nobody to offer to, end call */
4071 								switch_channel_t *channel = switch_core_session_get_channel(session);
4072 								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, no more clients to offer, ending call\n", RAYO_JID(call));
4073 								switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE);
4074 							}
4075 							switch_core_session_rwunlock(session);
4076 						}
4077 					}
4078 					switch_mutex_unlock(RAYO_ACTOR(call)->mutex);
4079 					RAYO_RELEASE(call);
4080 				}
4081 			}
4082 
4083 			switch_safe_free(next_offer->call_jid);
4084 			switch_safe_free(next_offer);
4085 		}
4086 	}
4087 
4088 	/* clean up queue */
4089 	while(switch_queue_trypop(globals.offer_queue, (void *)&next_offer) == SWITCH_STATUS_SUCCESS) {
4090 		switch_safe_free(next_offer->call_jid);
4091 		switch_safe_free(next_offer);
4092 	}
4093 
4094 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Offer timeout thread finished\n");
4095 	switch_thread_rwlock_unlock(globals.shutdown_rwlock);
4096 
4097 	return NULL;
4098 }
4099 
4100 /**
4101  * Create a new offer timeout thread
4102  * @param pool to use
4103  */
start_offer_timeout_thread(switch_memory_pool_t * pool)4104 static void start_offer_timeout_thread(switch_memory_pool_t *pool)
4105 {
4106 	switch_thread_t *thread;
4107 	switch_threadattr_t *thd_attr = NULL;
4108 	switch_threadattr_create(&thd_attr, pool);
4109 	switch_threadattr_detach_set(thd_attr, 1);
4110 	switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
4111 	switch_thread_create(&thread, thd_attr, offer_timeout_thread, NULL, pool);
4112 }
4113 
4114 #define RAYO_USAGE "[client username 1,client username n]"
4115 /**
4116  * Offer call and park channel
4117  */
SWITCH_STANDARD_APP(rayo_app)4118 SWITCH_STANDARD_APP(rayo_app)
4119 {
4120 	int ok = 0;
4121 	switch_channel_t *channel = switch_core_session_get_channel(session);
4122 	struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(switch_core_session_get_uuid(session));
4123 	const char *app = ""; /* optional app to execute */
4124 	const char *app_args = ""; /* app args */
4125 
4126 	/* don't need to keep call reference count incremented in session- call is destroyed after all apps finish */
4127 	if (call) {
4128 		RAYO_RELEASE(call);
4129 	}
4130 
4131 	/* is outbound call already under control? */
4132 	if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
4133 		const char *origination_args = switch_channel_get_variable(channel, "rayo_origination_args");
4134 		/* check origination args */
4135 		if (!zstr(origination_args)) {
4136 			char *argv[2] = { 0 };
4137 			char *args = switch_core_session_strdup(session, origination_args);
4138 			int argc = switch_separate_string(args, ' ', argv, sizeof(argv) / sizeof(argv[0]));
4139 			if (argc) {
4140 				if (!strcmp("conference", argv[0])) {
4141 					app = "conference";
4142 					app_args = argv[1];
4143 				} else if (!strcmp("bridge", argv[0])) {
4144 					app = "intercept";
4145 					app_args = argv[1];
4146 				} else {
4147 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Invalid rayo args: %s\n", data);
4148 					goto done;
4149 				}
4150 			}
4151 		}
4152 		if (!call) {
4153 			/* this scenario can only happen if a call was originated through a mechanism other than <dial>
4154 			   and then the rayo APP was executed to offer control */
4155 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Outbound call that wasn't created with <dial>, will try to offer control\n");
4156 		}
4157 		ok = 1;
4158 	}
4159 
4160 	if (!call) {
4161 		/* offer control */
4162 		switch_hash_index_t *hi = NULL;
4163 		char *clients_to_offer[16] = { 0 };
4164 		int clients_to_offer_count = 0;
4165 
4166 		call = rayo_call_create(switch_core_session_get_uuid(session));
4167 		if (!call) {
4168 			/* nothing that can be done to recover... */
4169 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failed to create call entity!\n");
4170 			switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE);
4171 			return;
4172 		}
4173 
4174 		switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_call_jid", RAYO_JID(call));
4175 
4176 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Offering call for Rayo 3PCC\n");
4177 
4178 		if (!zstr(data)) {
4179 			char *data_dup = switch_core_session_strdup(session, data);
4180 			clients_to_offer_count = switch_separate_string(data_dup, ',', clients_to_offer, sizeof(clients_to_offer) / sizeof(clients_to_offer[0]));
4181 		}
4182 
4183 		/* It is now safe for inbound call to be fully controlled by rayo client */
4184 		if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
4185 			switch_mutex_lock(RAYO_ACTOR(call)->mutex);
4186 			call->rayo_app_started = 1;
4187 			switch_mutex_unlock(RAYO_ACTOR(call)->mutex);
4188 		}
4189 
4190 		/* Offer call to all (or specified) ONLINE clients */
4191 		switch_mutex_lock(globals.clients_mutex);
4192 		for (hi = switch_core_hash_first(globals.clients_roster); hi; hi = switch_core_hash_next(&hi)) {
4193 			struct rayo_client *rclient;
4194 			const void *key;
4195 			void *val;
4196 			switch_core_hash_this(hi, &key, NULL, &val);
4197 			rclient = (struct rayo_client *)val;
4198 			switch_assert(rclient);
4199 
4200 			/* find clients available to take calls */
4201 			if (should_offer_to_client(rclient, clients_to_offer, clients_to_offer_count)) {
4202 				switch_core_hash_insert(call->acps, RAYO_JID(rclient), "1");
4203 				call->num_acps++;
4204 			}
4205 		}
4206 		ok = send_offer_to_clients(call, session);
4207 
4208 		switch_mutex_unlock(globals.clients_mutex);
4209 
4210 		/* nobody to offer to */
4211 		if (!ok) {
4212 			pause_when_offline();
4213 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Rejecting rayo call - there are no online rayo clients to offer call to\n");
4214 			switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE);
4215 		}
4216 	}
4217 
4218 done:
4219 
4220 	if (ok) {
4221 		switch_channel_set_private(switch_core_session_get_channel(session), "rayo_call_private", call);
4222 		switch_channel_set_variable(channel, "hangup_after_bridge", "false");
4223 		switch_channel_set_variable(channel, "transfer_after_bridge", "");
4224 		switch_channel_set_variable(channel, "park_after_bridge", "true");
4225 		switch_channel_set_variable(channel, "hold_hangup_xfer_exten", "park:inline:");
4226 		switch_channel_set_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE, "-1"); /* required so that output mixing works */
4227 		switch_core_event_hook_add_read_frame(session, rayo_call_on_read_frame);
4228 
4229 		if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
4230 			/* At this point, this outbound call might already be under control of a rayo client that is waiting for answer before sending
4231 			  commands.  The answered event might have been sent before we are ready to execute commands, so we delayed sending
4232 			  those events if the rayo APP hadn't started yet.  This delay would have only been a few milliseconds.
4233 			*/
4234 			switch_mutex_lock(RAYO_ACTOR(call)->mutex);
4235 			call->rayo_app_started = 1;
4236 			if (call->answer_event) {
4237 				struct rayo_client *rclient = RAYO_CLIENT(RAYO_LOCATE(rayo_call_get_dcp_jid(call)));
4238 				if (rclient) {
4239 					on_call_answer_event(rclient, call->answer_event);
4240 					switch_event_destroy(&call->answer_event);
4241 					RAYO_RELEASE(rclient);
4242 				}
4243 			}
4244 			switch_mutex_unlock(RAYO_ACTOR(call)->mutex);
4245 
4246 			/* Outbound calls might have a nested join to another call or conference - do that now */
4247 			if (!zstr(app)) {
4248 				switch_core_session_execute_application(session, app, app_args);
4249 			}
4250 		}
4251 
4252 		/* Ready for remote control */
4253 		switch_ivr_park(session, NULL);
4254 	}
4255 }
4256 
4257 /**
4258  * Stream locates client
4259  */
xmpp_stream_client_locate(struct xmpp_stream * stream,const char * jid)4260 static struct rayo_actor *xmpp_stream_client_locate(struct xmpp_stream *stream, const char *jid)
4261 {
4262 	struct rayo_actor *actor = NULL;
4263 	if (xmpp_stream_is_s2s(stream)) {
4264 		actor = RAYO_LOCATE(jid);
4265 		if (!actor) {
4266 			/* previously unknown client - add it */
4267 			struct rayo_peer_server *rserver = RAYO_PEER_SERVER(xmpp_stream_get_private(stream));
4268 			actor = RAYO_ACTOR(rayo_client_create(jid, xmpp_stream_get_jid(stream), PS_UNKNOWN, rayo_client_send, rserver));
4269 			RAYO_RETAIN(actor);
4270 		} else if (strcmp(RAT_CLIENT, actor->type)) {
4271 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, not a client: %s\n", xmpp_stream_get_jid(stream), jid);
4272 			RAYO_RELEASE(actor);
4273 			actor = NULL;
4274 		}
4275 	} else {
4276 		actor = RAYO_ACTOR(xmpp_stream_get_private(stream));
4277 		RAYO_RETAIN(actor);
4278 	}
4279 	return actor;
4280 }
4281 
4282 /**
4283  * Handle stream resource binding
4284  * @param stream the new stream
4285  */
on_xmpp_stream_bind(struct xmpp_stream * stream)4286 static int on_xmpp_stream_bind(struct xmpp_stream *stream)
4287 {
4288 	if (!xmpp_stream_is_s2s(stream)) {
4289 		/* client belongs to stream */
4290 		struct rayo_client *client = rayo_client_create(xmpp_stream_get_jid(stream), xmpp_stream_get_jid(stream), PS_OFFLINE, rayo_client_send, NULL);
4291 		if (client) {
4292 			xmpp_stream_set_private(stream, client);
4293 		} else {
4294 			/* this went really bad... */
4295 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "failed to create client entity!\n");
4296 			return 0;
4297 		}
4298 	}
4299 	return 1;
4300 }
4301 
4302 /**
4303  * Handle new stream creation
4304  * @param stream the new stream
4305  */
on_xmpp_stream_ready(struct xmpp_stream * stream)4306 static int on_xmpp_stream_ready(struct xmpp_stream *stream)
4307 {
4308 	if (xmpp_stream_is_s2s(stream)) {
4309 		if (xmpp_stream_is_incoming(stream)) {
4310 			/* peer server belongs to a s2s inbound stream */
4311 			struct rayo_peer_server *peer = rayo_peer_server_create(xmpp_stream_get_jid(stream));
4312 			if (peer) {
4313 				xmpp_stream_set_private(stream, peer);
4314 			} else {
4315 				/* this went really bad... */
4316 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "failed to create peer server entity!\n");
4317 				return 0;
4318 			}
4319 		} else {
4320 			/* send directed presence to domain */
4321 			iks *presence = iks_new("presence");
4322 			iks *x;
4323 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "sending server presence\n");
4324 
4325 			iks_insert_attrib(presence, "from", RAYO_JID(globals.server));
4326 			iks_insert_attrib(presence, "to", xmpp_stream_get_jid(stream));
4327 			x = iks_insert(presence, "show");
4328 			iks_insert_cdata(x, "chat", 4);
4329 			RAYO_SEND_MESSAGE(globals.server, xmpp_stream_get_jid(stream), presence);
4330 		}
4331 	}
4332 	return 1;
4333 }
4334 
4335 /**
4336  * Checks client availability.  If unknown, client presence is probed.
4337  * @param rclient to check
4338  */
rayo_client_presence_check(struct rayo_client * rclient)4339 static void rayo_client_presence_check(struct rayo_client *rclient)
4340 {
4341 	if (rclient->availability == PS_UNKNOWN) {
4342 		/* for now, set online */
4343 		rclient->availability = PS_ONLINE;
4344 	}
4345 }
4346 
4347 /**
4348  * Handle stream stanza
4349  * @param stream the stream
4350  * @param stanza the stanza to process
4351  */
on_xmpp_stream_recv(struct xmpp_stream * stream,iks * stanza)4352 static void on_xmpp_stream_recv(struct xmpp_stream *stream, iks *stanza)
4353 {
4354 	const char *name = iks_name(stanza);
4355 	if (!strcmp("iq", name)) {
4356 		const char *from = iks_find_attrib_soft(stanza, "from");
4357 		struct rayo_actor *actor = xmpp_stream_client_locate(stream, from);
4358 		if (actor) {
4359 			rayo_client_presence_check(RAYO_CLIENT(actor));
4360 			rayo_client_command_recv(RAYO_CLIENT(actor), stanza);
4361 			RAYO_RELEASE(actor);
4362 		}
4363 	} else if (!strcmp("presence", name)) {
4364 		const char *from = iks_find_attrib_soft(stanza, "from");
4365 		struct rayo_actor *actor = xmpp_stream_client_locate(stream, from);
4366 		if (actor) {
4367 			on_client_presence(RAYO_CLIENT(actor), stanza);
4368 			RAYO_RELEASE(actor);
4369 		}
4370 	} else if (!strcmp("message", name)) {
4371 		const char *from = iks_find_attrib_soft(stanza, "from");
4372 		struct rayo_actor *actor = xmpp_stream_client_locate(stream, from);
4373 		if (actor) {
4374 			rayo_client_presence_check(RAYO_CLIENT(actor));
4375 			on_client_message(RAYO_CLIENT(actor), stanza);
4376 			RAYO_RELEASE(actor);
4377 		}
4378 	}
4379 }
4380 
4381 /**
4382  * Handle stream destruction
4383  */
on_xmpp_stream_destroy(struct xmpp_stream * stream)4384 static void on_xmpp_stream_destroy(struct xmpp_stream *stream)
4385 {
4386 	/* destroy peer server / client associated with this stream */
4387 	void *actor = xmpp_stream_get_private(stream);
4388 	if (actor) {
4389 		RAYO_RELEASE(actor);
4390 		RAYO_DESTROY(actor);
4391 	}
4392 }
4393 
4394 /**
4395  * A command alias
4396  */
4397 struct rayo_cmd_alias {
4398 	/** number of additional arguments for alias */
4399 	int args;
4400 	/** the alias template */
4401 	const char *cmd;
4402 };
4403 
4404 /**
4405  * Add an alias to an API command
4406  * @param alias_name
4407  * @param alias_target
4408  * @param alias_cmd
4409  * @param alias_args
4410  */
rayo_add_cmd_alias(const char * alias_name,const char * alias_target,const char * alias_cmd,const char * alias_args)4411 static void rayo_add_cmd_alias(const char *alias_name, const char *alias_target, const char *alias_cmd, const char *alias_args)
4412 {
4413 	struct rayo_cmd_alias *alias = switch_core_alloc(globals.pool, sizeof(*alias));
4414 	alias->args = 0;
4415 	if (switch_is_number(alias_args)) {
4416 		alias->args = atoi(alias_args);
4417 		if (alias->args < 0) {
4418 			alias->args = 0;
4419 		}
4420 	}
4421 	alias->cmd = alias_cmd;
4422 	switch_core_hash_insert(globals.cmd_aliases, alias_name, alias);
4423 
4424 	/* set up autocomplete of alias */
4425 	if (zstr(alias_target)) {
4426 		alias_target = "all";
4427 	}
4428 	switch_console_set_complete(switch_core_sprintf(globals.pool, "add rayo %s ::rayo::list_%s", alias_name, alias_target));
4429 }
4430 
4431 /**
4432  * Process module XML configuration
4433  * @param pool memory pool to allocate from
4434  * @param config_file to use
4435  * @return SWITCH_STATUS_SUCCESS on successful configuration
4436  */
do_config(switch_memory_pool_t * pool,const char * config_file)4437 static switch_status_t do_config(switch_memory_pool_t *pool, const char *config_file)
4438 {
4439 	switch_xml_t cfg, xml;
4440 	switch_status_t status = SWITCH_STATUS_SUCCESS;
4441 
4442 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Configuring module\n");
4443 	if (!(xml = switch_xml_open_cfg(config_file, &cfg, NULL))) {
4444 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", config_file);
4445 		return SWITCH_STATUS_TERM;
4446 	}
4447 
4448 	/* set defaults */
4449 	globals.max_idle_ms = 30000;
4450 	globals.mixer_conf_profile = "sla";
4451 	globals.num_message_threads = 8;
4452 	globals.offer_uri = 1;
4453 	globals.pause_when_offline = 0;
4454 	globals.add_variables_to_offer = 0;
4455 	globals.add_variables_to_events = 0;
4456 	globals.offer_timeout_us = 5000000;
4457 	globals.offer_algorithm = OFFER_ALL;
4458 
4459 	/* get params */
4460 	{
4461 		switch_xml_t settings = switch_xml_child(cfg, "settings");
4462 		if (settings) {
4463 			switch_xml_t param;
4464 			for (param = switch_xml_child(settings, "param"); param; param = param->next) {
4465 				const char *var = switch_xml_attr_soft(param, "name");
4466 				const char *val = switch_xml_attr_soft(param, "value");
4467 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "param: %s = %s\n", var, val);
4468 				if (!strcasecmp(var, "max-idle-sec")) {
4469 					if (switch_is_number(val)) {
4470 						int max_idle_sec = atoi(val);
4471 						if (max_idle_sec > 0) {
4472 							globals.max_idle_ms = max_idle_sec * 1000;
4473 						}
4474 					}
4475 				} else if (!strcasecmp(var, "mixer-conf-profile")) {
4476 					if (!zstr(val)) {
4477 						globals.mixer_conf_profile = switch_core_strdup(pool, val);
4478 					}
4479 				} else if (!strcasecmp(var, "message-threads")) {
4480 					if (switch_is_number(val)) {
4481 						int num_message_threads = atoi(val);
4482 						if (num_message_threads > 0) {
4483 							globals.num_message_threads = num_message_threads;
4484 						}
4485 					}
4486 				} else if (!strcasecmp(var, "offer-uri")) {
4487 					if (switch_false(val)) {
4488 						globals.offer_uri = 0;
4489 					}
4490 				} else if (!strcasecmp(var, "pause-when-offline")) {
4491 					if (switch_true(val)) {
4492 						globals.pause_when_offline = 1;
4493 					}
4494 				} else if (!strcasecmp(var, "add-variables-to-offer")) {
4495 					if (switch_true(val)) {
4496 						globals.add_variables_to_offer = 1;
4497 					}
4498 				} else if (!strcasecmp(var, "add-variables-to-events")) {
4499 					if (switch_true(val)) {
4500 						globals.add_variables_to_offer = 1;
4501 						globals.add_variables_to_events = 1;
4502 					}
4503 				} else if (!strcasecmp(var, "offer-timeout-ms")) {
4504 					int offer_timeout_ms = 0;
4505 					if (switch_is_number(val) && (offer_timeout_ms = atoi(val)) >= 0  && offer_timeout_ms < 120000) {
4506 						globals.offer_timeout_us = offer_timeout_ms * 1000;
4507 					} else {
4508 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring invalid value for offer-timeout-ms \"%s\"\n", val);
4509 					}
4510 				} else if (!strcasecmp(var, "offer-algorithm")) {
4511 					if (zstr(val)) {
4512 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No value for offer-algorithm\n");
4513 					} else if (!strcasecmp(val, "all")) {
4514 						globals.offer_algorithm = OFFER_ALL;
4515 					} else if (!strcasecmp(val, "first")) {
4516 						globals.offer_algorithm = OFFER_FIRST;
4517 					} else if (!strcasecmp(val, "random")) {
4518 						globals.offer_algorithm = OFFER_RANDOM;
4519 					} else {
4520 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring invalid value for offer-algorithm \"%s\"\n", val);
4521 					}
4522 				} else {
4523 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unsupported param: %s\n", var);
4524 				}
4525 			}
4526 		}
4527 	}
4528 
4529 	/* configure dial gateways */
4530 	{
4531 		switch_xml_t dial_gateways = switch_xml_child(cfg, "dial-gateways");
4532 
4533 		/* set defaults */
4534 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Setting default dial-gateways\n");
4535 		dial_gateway_add("default", "sofia/gateway/outbound/", 0);
4536 		dial_gateway_add("tel:", "sofia/gateway/outbound/", 4);
4537 		dial_gateway_add("user", "", 0);
4538 		dial_gateway_add("sofia", "", 0);
4539 
4540 		if (dial_gateways) {
4541 			switch_xml_t dg;
4542 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Setting configured dial-gateways\n");
4543 			for (dg = switch_xml_child(dial_gateways, "dial-gateway"); dg; dg = dg->next) {
4544 				const char *uri_prefix = switch_xml_attr_soft(dg, "uriprefix");
4545 				const char *dial_prefix = switch_xml_attr_soft(dg, "dialprefix");
4546 				const char *strip_str = switch_xml_attr_soft(dg, "strip");
4547 				int strip = 0;
4548 
4549 				if (!zstr(strip_str) && switch_is_number(strip_str)) {
4550 					strip = atoi(strip_str);
4551 					if (strip < 0) {
4552 						strip = 0;
4553 					}
4554 				}
4555 				if (!zstr(uri_prefix)) {
4556 					dial_gateway_add(uri_prefix, dial_prefix, strip);
4557 				}
4558 			}
4559 		}
4560 	}
4561 
4562 	/* configure domain */
4563 	{
4564 		switch_xml_t domain = switch_xml_child(cfg, "domain");
4565 		if (domain) {
4566 			switch_xml_t l;
4567 			const char *shared_secret = switch_xml_attr_soft(domain, "shared-secret");
4568 			const char *name = switch_xml_attr_soft(domain, "name");
4569 			const char *cert = switch_xml_attr_soft(domain, "cert");
4570 			const char *key = switch_xml_attr_soft(domain, "key");
4571 			if (zstr(name)) {
4572 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing <domain name=\"... failed to configure rayo server\n");
4573 				status = SWITCH_STATUS_FALSE;
4574 				goto done;
4575 			}
4576 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Rayo domain set to %s\n", name);
4577 
4578 			if (zstr(shared_secret)) {
4579 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing shared secret for %s domain.  Server dialback will not work\n", name);
4580 			}
4581 
4582 			globals.xmpp_context = xmpp_stream_context_create(name, shared_secret, on_xmpp_stream_bind, on_xmpp_stream_ready, on_xmpp_stream_recv, on_xmpp_stream_destroy);
4583 			globals.server = rayo_server_create(name);
4584 
4585 			/* set up TLS */
4586 			if (!zstr(cert)) {
4587 				xmpp_stream_context_add_cert(globals.xmpp_context, cert);
4588 			}
4589 			if (!zstr(key)) {
4590 				xmpp_stream_context_add_key(globals.xmpp_context, key);
4591 			}
4592 
4593 			/* configure authorized users for this domain */
4594 			l = switch_xml_child(domain, "users");
4595 			if (l) {
4596 				switch_xml_t u;
4597 				for (u = switch_xml_child(l, "user"); u; u = u->next) {
4598 					const char *user = switch_xml_attr_soft(u, "name");
4599 					const char *password = switch_xml_attr_soft(u, "password");
4600 					xmpp_stream_context_add_user(globals.xmpp_context, user, password);
4601 				}
4602 			}
4603 
4604 			/* get listeners for this domain */
4605 			for (l = switch_xml_child(domain, "listen"); l; l = l->next) {
4606 				const char *address = switch_xml_attr_soft(l, "address");
4607 				const char *port = switch_xml_attr_soft(l, "port");
4608 				const char *type = switch_xml_attr_soft(l, "type");
4609 				const char *acl = switch_xml_attr_soft(l, "acl");
4610 				int is_s2s = 0;
4611 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s listener: %s:%s\n", type, address, port);
4612 				is_s2s = !strcmp("s2s", type);
4613 				if (!is_s2s && strcmp("c2s", type)) {
4614 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Type must be \"c2s\" or \"s2s\"!\n");
4615 					status = SWITCH_STATUS_FALSE;
4616 					goto done;
4617 				}
4618 				if (zstr(address)) {
4619 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing address!\n");
4620 					status = SWITCH_STATUS_FALSE;
4621 					goto done;
4622 				}
4623 				if (!zstr(port) && !switch_is_number(port)) {
4624 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Port must be an integer!\n");
4625 					status = SWITCH_STATUS_FALSE;
4626 					goto done;
4627 				}
4628 				if (xmpp_stream_context_listen(globals.xmpp_context, address, atoi(port), is_s2s, acl) != SWITCH_STATUS_SUCCESS) {
4629 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to create %s listener: %s:%s\n", type, address, port);
4630  				}
4631 			}
4632 
4633 			/* get outbound server connections */
4634 			for (l = switch_xml_child(domain, "connect"); l; l = l->next) {
4635 				const char *domain = switch_xml_attr_soft(l, "domain");
4636 				const char *address = switch_xml_attr_soft(l, "address");
4637 				const char *port = switch_xml_attr_soft(l, "port");
4638 				if (!zstr(port) && !switch_is_number(port)) {
4639 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Outbound server port must be an integer!\n");
4640 					status = SWITCH_STATUS_FALSE;
4641 					goto done;
4642 				}
4643 				if (zstr(address) && zstr(domain)) {
4644 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing outbound server address!\n");
4645 					status = SWITCH_STATUS_FALSE;
4646 					goto done;
4647 				}
4648 				xmpp_stream_context_connect(globals.xmpp_context, domain, address, atoi(port));
4649 			}
4650 		}
4651 	}
4652 
4653 	/* get aliases */
4654 	{
4655 		switch_xml_t aliases = switch_xml_child(cfg, "aliases");
4656 		if (aliases) {
4657 			switch_xml_t alias;
4658 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Setting configured aliases\n");
4659 			for (alias = switch_xml_child(aliases, "alias"); alias; alias = alias->next) {
4660 				const char *alias_name = switch_xml_attr_soft(alias, "name");
4661 				const char *alias_target = switch_xml_attr_soft(alias, "target");
4662 				const char *alias_args = switch_xml_attr_soft(alias, "args");
4663 				if (!zstr(alias_name) && !zstr(alias->txt)) {
4664 					rayo_add_cmd_alias(alias_name, switch_core_strdup(pool, alias_target), switch_core_strdup(pool, alias->txt), switch_core_strdup(pool, alias_args));
4665 				}
4666 			}
4667 		}
4668 	}
4669 
4670 done:
4671 	switch_xml_free(xml);
4672 
4673 	return status;
4674 }
4675 
4676 /**
4677  * Dump rayo actor stats
4678  */
rayo_actor_dump(struct rayo_actor * actor,switch_stream_handle_t * stream)4679 static void rayo_actor_dump(struct rayo_actor *actor, switch_stream_handle_t *stream)
4680 {
4681 	if (!strcmp(RAT_CLIENT, actor->type)) {
4682 		stream->write_function(stream, "TYPE='%s',SUBTYPE='%s',ID='%s',JID='%s',DOMAIN='%s',REFS=%i,STATUS='%s'", actor->type, actor->subtype, actor->id, RAYO_JID(actor), RAYO_DOMAIN(actor), actor->ref_count, presence_status_to_string(RAYO_CLIENT(actor)->availability));
4683 	} else {
4684 		stream->write_function(stream, "TYPE='%s',SUBTYPE='%s',ID='%s',JID='%s',DOMAIN='%s',REFS=%i", actor->type, actor->subtype, actor->id, RAYO_JID(actor), RAYO_DOMAIN(actor), actor->ref_count);
4685 	}
4686 }
4687 
4688 /**
4689  * Dump rayo actors
4690  */
dump_api(const char * cmd,switch_stream_handle_t * stream)4691 static int dump_api(const char *cmd, switch_stream_handle_t *stream)
4692 {
4693 	switch_hash_index_t *hi;
4694 	if (!zstr(cmd)) {
4695 		return 0;
4696 	}
4697 
4698 	stream->write_function(stream, "\nENTITIES\n");
4699 	switch_mutex_lock(globals.actors_mutex);
4700 	for (hi = switch_core_hash_first(globals.actors); hi; hi = switch_core_hash_next(&hi)) {
4701 		struct rayo_actor *actor = NULL;
4702 		const void *key;
4703 		void *val;
4704 		switch_core_hash_this(hi, &key, NULL, &val);
4705 		actor = (struct rayo_actor *)val;
4706 		switch_assert(actor);
4707 		stream->write_function(stream, "        ");
4708 		rayo_actor_dump(actor, stream);
4709 		stream->write_function(stream, "\n");
4710 	}
4711 
4712 	for (hi = switch_core_hash_first(globals.destroy_actors); hi; hi = switch_core_hash_next(&hi)) {
4713 		struct rayo_actor *actor = NULL;
4714 		const void *key;
4715 		void *val;
4716 		switch_core_hash_this(hi, &key, NULL, &val);
4717 		actor = (struct rayo_actor *)val;
4718 		switch_assert(actor);
4719 		stream->write_function(stream, "(DEAD)  ");
4720 		rayo_actor_dump(actor, stream);
4721 		stream->write_function(stream, "\n");
4722 	}
4723 	switch_mutex_unlock(globals.actors_mutex);
4724 
4725 	xmpp_stream_context_dump(globals.xmpp_context, stream);
4726 
4727 	return 1;
4728 }
4729 
4730 /**
4731  * Process response to console command_api
4732  */
rayo_console_client_send(struct rayo_actor * actor,struct rayo_message * msg)4733 void rayo_console_client_send(struct rayo_actor *actor, struct rayo_message *msg)
4734 {
4735 	iks *response = msg->payload;
4736 
4737 	if (response) {
4738 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\nRECV: from %s, %s\n", msg->from_jid, iks_string(iks_stack(response), response));
4739 	} else {
4740 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\nRECV: (null) from %s\n", msg->from_jid);
4741 	}
4742 }
4743 
4744 /**
4745  * Create a new Rayo console client
4746  * @return the new client or NULL
4747  */
rayo_console_client_create(void)4748 static struct rayo_client *rayo_console_client_create(void)
4749 {
4750 	struct rayo_client *client = NULL;
4751 	char *jid = NULL;
4752 	char id[SWITCH_UUID_FORMATTED_LENGTH + 1] = { 0 };
4753 	switch_uuid_str(id, sizeof(id));
4754 	jid = switch_mprintf("%s@%s/console", id, RAYO_JID(globals.server));
4755 	client = rayo_client_create(jid, NULL, PS_OFFLINE, rayo_console_client_send, NULL);
4756 	free(jid);
4757 	return client;
4758 }
4759 
4760 /**
4761  * Send command from console
4762  */
send_console_command(struct rayo_client * client,const char * to,const char * command_str)4763 static void send_console_command(struct rayo_client *client, const char *to, const char *command_str)
4764 {
4765 	iks *command = NULL;
4766 	iksparser *p = iks_dom_new(&command);
4767 
4768 	if (iks_parse(p, command_str, 0, 1) == IKS_OK && command) {
4769 		char *str;
4770 		iks *iq = NULL;
4771 
4772 		/* is command already wrapped in IQ? */
4773 		if (!strcmp(iks_name(command), "iq")) {
4774 			/* command already IQ */
4775 			iq = command;
4776 		} else {
4777 			/* create IQ to wrap command */
4778 			iq = iks_new_within("iq", iks_stack(command));
4779 			iks_insert_node(iq, command);
4780 		}
4781 
4782 		/* fill in command attribs */
4783 		iks_insert_attrib(iq, "to", to);
4784 		if (!iks_find_attrib(iq, "type")) {
4785 			iks_insert_attrib(iq, "type", "set");
4786 		}
4787 		if (!iks_find_attrib(iq, "id")) {
4788 			iks_insert_attrib_printf(iq, "id", "console-%i", RAYO_SEQ_NEXT(client));
4789 		}
4790 		iks_insert_attrib(iq, "from", RAYO_JID(client));
4791 
4792 		/* send command */
4793 		str = iks_string(iks_stack(iq), iq);
4794 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\nSEND: to %s, %s\n", to, str);
4795 		rayo_client_command_recv(client, iq);
4796 		iks_delete(command);
4797 	} else {
4798 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "bad request xml\n");
4799 	}
4800 	iks_parser_delete(p);
4801 }
4802 
4803 /**
4804  * Send command to rayo actor
4805  */
command_api(char * cmd,switch_stream_handle_t * stream)4806 static int command_api(char *cmd, switch_stream_handle_t *stream)
4807 {
4808 	char *argv[2] = { 0 };
4809 	if (!zstr(cmd)) {
4810 		int argc = switch_separate_string(cmd, ' ', argv, sizeof(argv) / sizeof(argv[0]));
4811 		if (argc != 2) {
4812 			return 0;
4813 		}
4814 	} else {
4815 		return 0;
4816 	}
4817 
4818 	/* send command */
4819 	send_console_command(globals.console, argv[0], argv[1]);
4820 	stream->write_function(stream, "+OK\n");
4821 
4822 	return 1;
4823 }
4824 
4825 /**
4826  * Send command to rayo actor
4827  */
alias_api(struct rayo_cmd_alias * alias,char * args,switch_stream_handle_t * stream)4828 static int alias_api(struct rayo_cmd_alias *alias, char *args, switch_stream_handle_t *stream)
4829 {
4830 	char *argv[10] = { 0 };
4831 	int argc, i;
4832 	char *cmd;
4833 	char *jid;
4834 
4835 	if (zstr(alias->cmd)) {
4836 		stream->write_function(stream, "-ERR missing alias template.  Check configuration.\n");
4837 	}
4838 
4839 	if (zstr(args)) {
4840 		stream->write_function(stream, "-ERR no args\n");
4841 		return 1;
4842 	}
4843 
4844 	/* check args */
4845 	argc = switch_separate_string(args, ' ', argv, sizeof(argv) / sizeof(argv[0]));
4846 	if (argc != alias->args + 1) {
4847 		stream->write_function(stream, "-ERR wrong number of args (%i/%i)\n", argc, alias->args + 1);
4848 		return 1;
4849 	}
4850 
4851 	jid = argv[0];
4852 
4853 	/* build command from args */
4854 	cmd = strdup(alias->cmd);
4855 	for (i = 1; i < argc; i++) {
4856 		char *cmd_new;
4857 		char to_replace[12] = { 0 };
4858 		sprintf(to_replace, "$%i", i);
4859 		cmd_new = switch_string_replace(cmd, to_replace, argv[i]);
4860 		free(cmd);
4861 		cmd = cmd_new;
4862 	}
4863 
4864 	/* send command */
4865 	send_console_command(globals.console, jid, cmd);
4866 	stream->write_function(stream, "+OK\n");
4867 	free(cmd);
4868 
4869 	return 1;
4870 }
4871 
4872 /**
4873  * Send message from console
4874  */
send_console_message(struct rayo_client * client,const char * to,const char * type,const char * message_str)4875 static void send_console_message(struct rayo_client *client, const char *to, const char *type, const char *message_str)
4876 {
4877 	iks *message = NULL, *x;
4878 	message = iks_new("message");
4879 	iks_insert_attrib(message, "to", to);
4880 	iks_insert_attrib(message, "from", RAYO_JID(client));
4881 	iks_insert_attrib_printf(message, "id", "console-%i", RAYO_SEQ_NEXT(client));
4882 	iks_insert_attrib(message, "type", type);
4883 	x = iks_insert(message, "body");
4884 	iks_insert_cdata(x, message_str, strlen(message_str));
4885 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\nSEND: to %s, %s\n", to, iks_string(iks_stack(message), message));
4886 	RAYO_SEND_MESSAGE(client, to, message);
4887 }
4888 
4889 /**
4890  * Send message to rayo actor
4891  */
message_api(char * cmd,switch_stream_handle_t * stream)4892 static int message_api(char *cmd, switch_stream_handle_t *stream)
4893 {
4894 	char *argv[3] = { 0 };
4895 	if (!zstr(cmd)) {
4896 		int argc = switch_separate_string(cmd, ' ', argv, sizeof(argv) / sizeof(argv[0]));
4897 		if (argc != 3) {
4898 			return 0;
4899 		}
4900 	} else {
4901 		return 0;
4902 	}
4903 
4904 	/* send message */
4905 	send_console_message(globals.console, argv[0], argv[1], argv[2]);
4906 	stream->write_function(stream, "+OK\n");
4907 
4908 	return 1;
4909 }
4910 
4911 /**
4912  * Send presence from console
4913  */
send_console_presence(struct rayo_client * client,const char * to,int is_online)4914 static void send_console_presence(struct rayo_client *client, const char *to, int is_online)
4915 {
4916 	iks *presence = NULL, *x;
4917 	presence = iks_new("presence");
4918 	iks_insert_attrib(presence, "to", to);
4919 	iks_insert_attrib(presence, "from", RAYO_JID(client));
4920 	iks_insert_attrib_printf(presence, "id", "console-%i", RAYO_SEQ_NEXT(client));
4921 	if (!is_online) {
4922 		iks_insert_attrib(presence, "type", "unavailable");
4923 	}
4924 	x = iks_insert(presence, "show");
4925 	iks_insert_cdata(x, is_online ? "chat" : "dnd", 0);
4926 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\nSEND: to %s, %s\n", to, iks_string(iks_stack(presence), presence));
4927 	RAYO_SEND_MESSAGE(client, to, presence);
4928 }
4929 
4930 /**
4931  * Send console presence
4932  */
presence_api(char * cmd,switch_stream_handle_t * stream)4933 static int presence_api(char *cmd, switch_stream_handle_t *stream)
4934 {
4935 	int is_online = 0;
4936 	char *argv[2] = { 0 };
4937 	if (!zstr(cmd)) {
4938 		int argc = switch_separate_string(cmd, ' ', argv, sizeof(argv) / sizeof(argv[0]));
4939 		if (argc != 2) {
4940 			return 0;
4941 		}
4942 	} else {
4943 		return 0;
4944 	}
4945 
4946 	if (!strcmp("online", argv[1])) {
4947 		is_online = 1;
4948 	} else if (strcmp("offline", argv[1])) {
4949 		return 0;
4950 	}
4951 
4952 	/* send presence */
4953 	send_console_presence(globals.console, argv[0], is_online);
4954 	stream->write_function(stream, "+OK\n");
4955 	return 1;
4956 }
4957 
4958 #define RAYO_API_SYNTAX "status | (<alias> <jid>) | (cmd <jid> <command>) | (msg <jid> <message text>) | (presence <jid> <online|offline>)"
SWITCH_STANDARD_API(rayo_api)4959 SWITCH_STANDARD_API(rayo_api)
4960 {
4961 	struct rayo_cmd_alias *alias;
4962 	char *cmd_dup = NULL;
4963 	char *argv[2] = { 0 };
4964 	int success = 0;
4965 
4966 	if (zstr(cmd) ) {
4967 		goto done;
4968 	}
4969 
4970 	cmd_dup = strdup(cmd);
4971 	switch_separate_string(cmd_dup, ' ', argv, sizeof(argv) / sizeof(argv[0]));
4972 
4973 	/* check if a command alias */
4974 	alias = switch_core_hash_find(globals.cmd_aliases, argv[0]);
4975 
4976 	if (alias) {
4977 		success = alias_api(alias, argv[1], stream);
4978 	} else if (!strcmp("cmd", argv[0])) {
4979 		success = command_api(argv[1], stream);
4980 	} else if (!strcmp("status", argv[0])) {
4981 		success = dump_api(argv[1], stream);
4982 	} else if (!strcmp("msg", argv[0])) {
4983 		success = message_api(argv[1], stream);
4984 	} else if (!strcmp("presence", argv[0])) {
4985 		success = presence_api(argv[1], stream);
4986 	}
4987 
4988 done:
4989 	if (!success) {
4990 		stream->write_function(stream, "-ERR: USAGE %s\n", RAYO_API_SYNTAX);
4991 	}
4992 
4993 	switch_safe_free(cmd_dup);
4994 
4995 	return SWITCH_STATUS_SUCCESS;
4996 }
4997 
4998 /**
4999  * Console auto-completion for actors given validation function
5000  */
list_actors(const char * line,const char * cursor,switch_console_callback_match_t ** matches,rayo_actor_match_fn match)5001 static switch_status_t list_actors(const char *line, const char *cursor, switch_console_callback_match_t **matches, rayo_actor_match_fn match)
5002 {
5003 	switch_hash_index_t *hi;
5004 	void *val;
5005 	const void *vvar;
5006 	switch_console_callback_match_t *my_matches = NULL;
5007 	switch_status_t status = SWITCH_STATUS_FALSE;
5008 	struct rayo_actor *actor;
5009 
5010 	switch_mutex_lock(globals.actors_mutex);
5011 	for (hi = switch_core_hash_first(globals.actors); hi; hi = switch_core_hash_next(&hi)) {
5012 		switch_core_hash_this(hi, &vvar, NULL, &val);
5013 
5014 		actor = (struct rayo_actor *) val;
5015 		if (match(actor)) {
5016 			switch_console_push_match(&my_matches, (const char *) vvar);
5017 		}
5018 	}
5019 	switch_mutex_unlock(globals.actors_mutex);
5020 
5021 	if (my_matches) {
5022 		*matches = my_matches;
5023 		status = SWITCH_STATUS_SUCCESS;
5024 	}
5025 
5026 	return status;
5027 }
5028 
5029 /**
5030  * @return true if internal actor
5031  */
is_internal_actor(struct rayo_actor * actor)5032 static switch_bool_t is_internal_actor(struct rayo_actor *actor)
5033 {
5034 	return strcmp(RAT_CLIENT, actor->type) && strcmp(RAT_PEER_SERVER, actor->type);
5035 }
5036 
5037 /**
5038  * Console auto-completion for all internal actors
5039  */
list_internal(const char * line,const char * cursor,switch_console_callback_match_t ** matches)5040 static switch_status_t list_internal(const char *line, const char *cursor, switch_console_callback_match_t **matches)
5041 {
5042 	return list_actors(line, cursor, matches, is_internal_actor);
5043 }
5044 
5045 /**
5046  * @return true if external actor
5047  */
is_external_actor(struct rayo_actor * actor)5048 static switch_bool_t is_external_actor(struct rayo_actor *actor)
5049 {
5050 	return !strcmp(RAT_CLIENT, actor->type) || !strcmp(RAT_PEER_SERVER, actor->type);
5051 }
5052 
5053 /**
5054  * Console auto-completion for all external actors
5055  */
list_external(const char * line,const char * cursor,switch_console_callback_match_t ** matches)5056 static switch_status_t list_external(const char *line, const char *cursor, switch_console_callback_match_t **matches)
5057 {
5058 	return list_actors(line, cursor, matches, is_external_actor);
5059 }
5060 
5061 /**
5062  * @return true
5063  */
is_any_actor(struct rayo_actor * actor)5064 static switch_bool_t is_any_actor(struct rayo_actor *actor)
5065 {
5066 	return SWITCH_TRUE;
5067 }
5068 
5069 /**
5070  * Console auto-completion for all actors
5071  */
list_all(const char * line,const char * cursor,switch_console_callback_match_t ** matches)5072 static switch_status_t list_all(const char *line, const char *cursor, switch_console_callback_match_t **matches)
5073 {
5074 	return list_actors(line, cursor, matches, is_any_actor);
5075 }
5076 
5077 /**
5078  * @return true if a server
5079  */
is_server_actor(struct rayo_actor * actor)5080 static switch_bool_t is_server_actor(struct rayo_actor *actor)
5081 {
5082 	return !strcmp(RAT_SERVER, actor->type);
5083 }
5084 
5085 /**
5086  * Console auto-completion for all servers
5087  */
list_server(const char * line,const char * cursor,switch_console_callback_match_t ** matches)5088 static switch_status_t list_server(const char *line, const char *cursor, switch_console_callback_match_t **matches)
5089 {
5090 	return list_actors(line, cursor, matches, is_server_actor);
5091 }
5092 
5093 /**
5094  * @return true if a call
5095  */
is_call_actor(struct rayo_actor * actor)5096 static switch_bool_t is_call_actor(struct rayo_actor *actor)
5097 {
5098 	return !strcmp(RAT_CALL, actor->type);
5099 }
5100 
5101 /**
5102  * Console auto-completion for all calls
5103  */
list_call(const char * line,const char * cursor,switch_console_callback_match_t ** matches)5104 static switch_status_t list_call(const char *line, const char *cursor, switch_console_callback_match_t **matches)
5105 {
5106 	return list_actors(line, cursor, matches, is_call_actor);
5107 }
5108 
5109 /**
5110  * @return true if a component
5111  */
is_component_actor(struct rayo_actor * actor)5112 switch_bool_t is_component_actor(struct rayo_actor *actor)
5113 {
5114 	return !strncmp(RAT_COMPONENT, actor->type, strlen(RAT_COMPONENT));
5115 }
5116 
5117 /**
5118  * Console auto-completion for all components
5119  */
list_component(const char * line,const char * cursor,switch_console_callback_match_t ** matches)5120 static switch_status_t list_component(const char *line, const char *cursor, switch_console_callback_match_t **matches)
5121 {
5122 	return list_actors(line, cursor, matches, is_component_actor);
5123 }
5124 
5125 /**
5126  * @return true if a record component
5127  */
is_record_actor(struct rayo_actor * actor)5128 static switch_bool_t is_record_actor(struct rayo_actor *actor)
5129 {
5130 	return is_component_actor(actor) && !strcmp(actor->subtype, "record");
5131 }
5132 
5133 /**
5134  * Console auto-completion for all components
5135  */
list_record(const char * line,const char * cursor,switch_console_callback_match_t ** matches)5136 static switch_status_t list_record(const char *line, const char *cursor, switch_console_callback_match_t **matches)
5137 {
5138 	return list_actors(line, cursor, matches, is_record_actor);
5139 }
5140 
5141 /**
5142  * @return true if an output component
5143  */
is_output_actor(struct rayo_actor * actor)5144 static switch_bool_t is_output_actor(struct rayo_actor *actor)
5145 {
5146 	return is_component_actor(actor) && !strcmp(actor->subtype, "output");
5147 }
5148 
5149 /**
5150  * Console auto-completion for all components
5151  */
list_output(const char * line,const char * cursor,switch_console_callback_match_t ** matches)5152 static switch_status_t list_output(const char *line, const char *cursor, switch_console_callback_match_t **matches)
5153 {
5154 	return list_actors(line, cursor, matches, is_output_actor);
5155 }
5156 
5157 /**
5158  * @return true if an input component
5159  */
is_input_actor(struct rayo_actor * actor)5160 static switch_bool_t is_input_actor(struct rayo_actor *actor)
5161 {
5162 	return is_component_actor(actor) && !strcmp(actor->subtype, "input");
5163 }
5164 
5165 /**
5166  * Console auto-completion for all components
5167  */
list_input(const char * line,const char * cursor,switch_console_callback_match_t ** matches)5168 static switch_status_t list_input(const char *line, const char *cursor, switch_console_callback_match_t **matches)
5169 {
5170 	return list_actors(line, cursor, matches, is_input_actor);
5171 }
5172 
5173 /**
5174  * Shutdown module on load failure or shutdown from FreeSWITCH core
5175  */
do_shutdown(void)5176 static switch_status_t do_shutdown(void)
5177 {
5178 	switch_console_del_complete_func("::rayo::list_all");
5179 	switch_console_del_complete_func("::rayo::list_internal");
5180 	switch_console_del_complete_func("::rayo::list_external");
5181 	switch_console_del_complete_func("::rayo::list_server");
5182 	switch_console_del_complete_func("::rayo::list_call");
5183 	switch_console_del_complete_func("::rayo::list_component");
5184 	switch_console_del_complete_func("::rayo::list_record");
5185 	switch_console_del_complete_func("::rayo::list_output");
5186 	switch_console_del_complete_func("::rayo::list_input");
5187 	switch_console_set_complete("del rayo");
5188 
5189 	/* stop XMPP streams */
5190 	if (globals.xmpp_context) {
5191 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for XMPP threads to stop\n");
5192 		xmpp_stream_context_destroy(globals.xmpp_context);
5193 	}
5194 
5195 	/* stop threads */
5196 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for message and offer timeout threads to stop\n");
5197 	stop_all_threads();
5198 
5199 	if (globals.console) {
5200 		RAYO_RELEASE(globals.console);
5201 		RAYO_DESTROY(globals.console);
5202 		globals.console = NULL;
5203 	}
5204 
5205 	if (globals.server) {
5206 		RAYO_RELEASE(globals.server);
5207 		RAYO_DESTROY(globals.server);
5208 		globals.server = NULL;
5209 	}
5210 
5211 	rayo_components_shutdown();
5212 
5213 	switch_event_unbind_callback(route_call_event);
5214 	switch_event_unbind_callback(on_call_end_event);
5215 	switch_event_unbind_callback(route_mixer_event);
5216 
5217 	if (globals.command_handlers) {
5218 		switch_core_hash_destroy(&globals.command_handlers);
5219 	}
5220 	if (globals.event_handlers) {
5221 		switch_core_hash_destroy(&globals.event_handlers);
5222 	}
5223 	if (globals.clients_roster) {
5224 		switch_core_hash_destroy(&globals.clients_roster);
5225 	}
5226 	if (globals.actors) {
5227 		switch_core_hash_destroy(&globals.actors);
5228 	}
5229 	if (globals.destroy_actors) {
5230 		switch_core_hash_destroy(&globals.destroy_actors);
5231 	}
5232 	if (globals.actors_by_id) {
5233 		switch_core_hash_destroy(&globals.actors_by_id);
5234 	}
5235 	if (globals.dial_gateways) {
5236 		switch_core_hash_destroy(&globals.dial_gateways);
5237 	}
5238 	if (globals.cmd_aliases) {
5239 		switch_core_hash_destroy(&globals.cmd_aliases);
5240 	}
5241 
5242 
5243 	return SWITCH_STATUS_SUCCESS;
5244 }
5245 
5246 /**
5247  * Load module
5248  */
SWITCH_MODULE_LOAD_FUNCTION(mod_rayo_load)5249 SWITCH_MODULE_LOAD_FUNCTION(mod_rayo_load)
5250 {
5251 	switch_api_interface_t *api_interface;
5252 	switch_application_interface_t *app_interface;
5253 
5254 
5255 	if (switch_event_reserve_subclass("rayo::cpa") != SWITCH_STATUS_SUCCESS) {
5256 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", "rayo::cpa");
5257 		return SWITCH_STATUS_TERM;
5258 	}
5259 
5260 
5261 	*module_interface = switch_loadable_module_create_module_interface(pool, modname);
5262 
5263 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading module\n");
5264 
5265 	memset(&globals, 0, sizeof(globals));
5266 	globals.pool = pool;
5267 	switch_core_hash_init(&globals.command_handlers);
5268 	switch_core_hash_init(&globals.event_handlers);
5269 	switch_core_hash_init(&globals.clients_roster);
5270 	switch_mutex_init(&globals.clients_mutex, SWITCH_MUTEX_NESTED, pool);
5271 	switch_core_hash_init(&globals.actors);
5272 	switch_core_hash_init(&globals.destroy_actors);
5273 	switch_core_hash_init(&globals.actors_by_id);
5274 	switch_mutex_init(&globals.actors_mutex, SWITCH_MUTEX_NESTED, pool);
5275 	switch_core_hash_init(&globals.dial_gateways);
5276 	switch_mutex_init(&globals.dial_gateways_mutex, SWITCH_MUTEX_NESTED, pool);
5277 	switch_core_hash_init(&globals.cmd_aliases);
5278 	switch_thread_rwlock_create(&globals.shutdown_rwlock, pool);
5279 	switch_queue_create(&globals.msg_queue, 25000, pool);
5280 	switch_queue_create(&globals.offer_queue, 25000, pool);
5281 	globals.offline_logged = 1;
5282 
5283 	/* server commands */
5284 	rayo_actor_command_handler_add(RAT_SERVER, "", "get:"IKS_NS_XMPP_PING":ping", on_iq_xmpp_ping);
5285 	rayo_actor_command_handler_add(RAT_SERVER, "", "get:"IKS_NS_XMPP_DISCO":query", on_iq_get_xmpp_disco);
5286 	rayo_actor_command_handler_add(RAT_SERVER, "", "set:"RAYO_NS":dial", on_rayo_dial);
5287 	rayo_actor_command_handler_add(RAT_SERVER, "", "set:"RAYO_NS":exec", on_rayo_exec);
5288 
5289 	/* Rayo call commands */
5290 	rayo_actor_command_handler_add(RAT_CALL, "", "set:"RAYO_NS":accept", on_rayo_accept);
5291 	rayo_actor_command_handler_add(RAT_CALL, "", "set:"RAYO_NS":answer", on_rayo_answer);
5292 	rayo_actor_command_handler_add(RAT_CALL, "", "set:"RAYO_NS":redirect", on_rayo_redirect);
5293 	rayo_actor_command_handler_add(RAT_CALL, "", "set:"RAYO_NS":reject", on_rayo_hangup); /* handles both reject and hangup */
5294 	rayo_actor_command_handler_add(RAT_CALL, "", "set:"RAYO_NS":hangup", on_rayo_hangup); /* handles both reject and hangup */
5295 	rayo_actor_command_handler_add(RAT_CALL, "", "set:"RAYO_NS":join", on_rayo_join);
5296 	rayo_actor_command_handler_add(RAT_CALL, "", "set:"RAYO_NS":unjoin", on_rayo_unjoin);
5297 
5298 	switch_event_bind(modname, SWITCH_EVENT_CHANNEL_ORIGINATE, NULL, route_call_event, NULL);
5299 	switch_event_bind(modname, SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA, NULL, route_call_event, NULL);
5300 	switch_event_bind(modname, SWITCH_EVENT_CHANNEL_PROGRESS, NULL, route_call_event, NULL);
5301 	switch_event_bind(modname, SWITCH_EVENT_CHANNEL_ANSWER, NULL, route_call_event, NULL);
5302 	switch_event_bind(modname, SWITCH_EVENT_CHANNEL_BRIDGE, NULL, route_call_event, NULL);
5303 	switch_event_bind(modname, SWITCH_EVENT_CHANNEL_PARK, NULL, route_call_event, NULL);
5304 	switch_event_bind(modname, SWITCH_EVENT_CHANNEL_EXECUTE, NULL, route_call_event, NULL);
5305 	switch_event_bind(modname, SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE, NULL, route_call_event, NULL);
5306 
5307 	switch_event_bind(modname, SWITCH_EVENT_CHANNEL_DESTROY, NULL, on_call_end_event, NULL);
5308 
5309 	switch_event_bind(modname, SWITCH_EVENT_CUSTOM, "conference::maintenance", route_mixer_event, NULL);
5310 
5311 	SWITCH_ADD_APP(app_interface, "rayo", "Offer call control to Rayo client(s)", "", rayo_app, RAYO_USAGE, SAF_SUPPORT_NOMEDIA);
5312 	SWITCH_ADD_API(api_interface, "rayo", "Query rayo status", rayo_api, RAYO_API_SYNTAX);
5313 
5314 	/* set up rayo components */
5315 	if (rayo_components_load(module_interface, pool, RAYO_CONFIG_FILE) != SWITCH_STATUS_SUCCESS) {
5316 		goto error;
5317 	}
5318 
5319 	/* configure / open sockets */
5320 	if(do_config(globals.pool, RAYO_CONFIG_FILE) != SWITCH_STATUS_SUCCESS) {
5321 		goto error;
5322 	}
5323 
5324 	/* create admin client */
5325 	globals.console = rayo_console_client_create();
5326 	if (!globals.console) {
5327 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to create console client entity!\n");
5328 		goto error;
5329 	}
5330 
5331 	/* start up message threads */
5332 	{
5333 		int i;
5334 		for (i = 0; i < globals.num_message_threads; i++) {
5335 			start_deliver_message_thread(pool);
5336 		}
5337 	}
5338 	start_offer_timeout_thread(pool);
5339 
5340 	switch_console_set_complete("add rayo status");
5341 	switch_console_set_complete("add rayo msg ::rayo::list_all");
5342 	switch_console_set_complete("add rayo msg ::rayo::list_all chat");
5343 	switch_console_set_complete("add rayo msg ::rayo::list_all groupchat");
5344 	switch_console_set_complete("add rayo msg ::rayo::list_all headline");
5345 	switch_console_set_complete("add rayo msg ::rayo::list_all normal");
5346 	switch_console_set_complete("add rayo presence ::rayo::list_server online");
5347 	switch_console_set_complete("add rayo presence ::rayo::list_server offline");
5348 	switch_console_add_complete_func("::rayo::list_all", list_all);
5349 	switch_console_add_complete_func("::rayo::list_internal", list_internal);
5350 	switch_console_add_complete_func("::rayo::list_external", list_external);
5351 	switch_console_add_complete_func("::rayo::list_server", list_server);
5352 	switch_console_add_complete_func("::rayo::list_call", list_call);
5353 	switch_console_add_complete_func("::rayo::list_component", list_component);
5354 	switch_console_add_complete_func("::rayo::list_record", list_record);
5355 	switch_console_add_complete_func("::rayo::list_output", list_output);
5356 	switch_console_add_complete_func("::rayo::list_input", list_input);
5357 
5358 	return SWITCH_STATUS_SUCCESS;
5359 
5360  error:
5361 	switch_event_free_subclass("rayo::cpa");
5362 	do_shutdown();
5363 	return SWITCH_STATUS_TERM;
5364 
5365 }
5366 
5367 /**
5368  * Shutdown module.  Notifies threads to stop.
5369  */
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_rayo_shutdown)5370 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_rayo_shutdown)
5371 {
5372 	switch_status_t result;
5373 
5374 	switch_event_free_subclass("rayo::cpa");
5375 	result = do_shutdown();
5376 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Module shutdown\n");
5377 	return result;
5378 }
5379 
5380 /**
5381  * Checks status of connected clients
5382  */
SWITCH_MODULE_RUNTIME_FUNCTION(mod_rayo_runtime)5383 SWITCH_MODULE_RUNTIME_FUNCTION(mod_rayo_runtime)
5384 {
5385 	if (globals.pause_when_offline) {
5386 		switch_thread_rwlock_rdlock(globals.shutdown_rwlock);
5387 		while (!globals.shutdown) {
5388 			switch_sleep(1000 * 1000); /* 1 second */
5389 			pause_when_offline();
5390 		}
5391 		switch_thread_rwlock_unlock(globals.shutdown_rwlock);
5392 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Runtime thread is done\n");
5393 	}
5394 	return SWITCH_STATUS_TERM;
5395 }
5396 
5397 /* For Emacs:
5398  * Local Variables:
5399  * mode:c
5400  * indent-tabs-mode:t
5401  * tab-width:4
5402  * c-basic-offset:4
5403  * End:
5404  * For VIM:
5405  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet
5406  */
5407