1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * This module (mod_gsmopen) has been contributed by:
25  *
26  * Giovanni Maruzzelli <gmaruzz@gmail.com>
27  *
28  * Maintainer: Giovanni Maruzzelli <gmaruzz@gmail.com>
29  *
30  * mod_skypopen.c -- Skype compatible Endpoint Module
31  *
32  */
33 
34 
35 #include "skypopen.h"
36 #define SKYPE_CHAT_PROTO "skype"
37 
38 #ifdef WIN32
39 /***************/
40 // from http://www.openasthra.com/c-tidbits/gettimeofday-function-for-windows/
41 
42 #include <time.h>
43 
44 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
45 #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
46 #else /*  */
47 #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
48 #endif /*  */
49 struct sk_timezone {
50 	int tz_minuteswest;			/* minutes W of Greenwich */
51 	int tz_dsttime;				/* type of dst correction */
52 };
gettimeofday(struct timeval * tv,struct sk_timezone * tz)53 int gettimeofday(struct timeval *tv, struct sk_timezone *tz)
54 {
55 	FILETIME ft;
56 	unsigned __int64 tmpres = 0;
57 	static int tzflag;
58 	if (NULL != tv) {
59 		GetSystemTimeAsFileTime(&ft);
60 		tmpres |= ft.dwHighDateTime;
61 		tmpres <<= 32;
62 		tmpres |= ft.dwLowDateTime;
63 
64 		/*converting file time to unix epoch */
65 		tmpres /= 10;			/*convert into microseconds */
66 		tmpres -= DELTA_EPOCH_IN_MICROSECS;
67 		tv->tv_sec = (long) (tmpres / 1000000UL);
68 		tv->tv_usec = (long) (tmpres % 1000000UL);
69 	}
70 	if (NULL != tz) {
71 		if (!tzflag) {
72 			_tzset();
73 			tzflag++;
74 		}
75 		tz->tz_minuteswest = _timezone / 60;
76 		tz->tz_dsttime = _daylight;
77 	}
78 	return 0;
79 }
80 
81 /***************/
82 #endif /* WIN32 */
83 SWITCH_MODULE_LOAD_FUNCTION(mod_skypopen_load);
84 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypopen_shutdown);
85 SWITCH_MODULE_DEFINITION(mod_skypopen, mod_skypopen_load, mod_skypopen_shutdown, NULL);
86 SWITCH_STANDARD_API(sk_function);
87 /* BEGIN: Changes here */
88 #define SK_SYNTAX "list [full] || console || skype_API_msg || remove < skypeusername | #interface_name | #interface_id > || reload"
89 /* END: Changes heres */
90 SWITCH_STANDARD_API(skypopen_function);
91 #define SKYPOPEN_SYNTAX "interface_name skype_API_msg"
92 
93 SWITCH_STANDARD_API(skypopen_chat_function);
94 #define SKYPOPEN_CHAT_SYNTAX "interface_name remote_skypename TEXT"
95 #define FULL_RELOAD 0
96 #define SOFT_RELOAD 1
97 
98 char *interface_status[] = {	/* should match SKYPOPEN_STATE_xxx in skypopen.h */
99 	"IDLE",
100 	"DOWN",
101 	"RING",
102 	"DIALING",
103 	"BUSY",
104 	"UP",
105 	"RINGING",
106 	"PRERING",
107 	"DOUBLE",
108 	"SELECTD",
109 	"HANG_RQ",
110 	"PREANSW",
111 	"DEAD"
112 };
113 
114 char *skype_callflow[] = {		/* should match CALLFLOW_XXX in skypopen.h */
115 	"IDLE",
116 	"DOWN",
117 	"INC_RNG",
118 	"CALL_DIALING",
119 	"CALL_LINEBUSY",
120 	"CALL_ACTIVE",
121 	"INC_HNG",
122 	"CALL_RLEASD",
123 	"CALL_NOCARR",
124 	"CALL_INFLUX",
125 	"CALL_INCOMING",
126 	"CALL_FAILED",
127 	"CALL_NOSRVC",
128 	"CALL_OUTRESTR",
129 	"CALL_SECFAIL",
130 	"CALL_NOANSWER",
131 	"FNSHED",
132 	"CANCLED",
133 	"FAILED",
134 	"REFUSED",
135 	"RINGING",
136 	"INPROGRS",
137 	"UNPLACD",
138 	"ROUTING",
139 	"EARLYMD",
140 	"INC_CLID",
141 	"RMTEHOLD"
142 };
143 
144 
145 static struct {
146 	int debug;
147 	char *context;
148 	char *dialplan;
149 	char *destination;
150 	char *skype_user;
151 	char *report_incoming_chatmessages;
152 	char *silent_mode;
153 	char *write_silence_when_idle;
154 	char *setsockopt;
155 	int calls;
156 	int real_interfaces;
157 	int next_interface;
158 	private_t SKYPOPEN_INTERFACES[SKYPOPEN_MAX_INTERFACES];
159 	switch_mutex_t *mutex;
160 	private_t *sk_console;
161 	int start_port;
162 
163 	// CLOUDTREE (THomas Hazel)
164 	switch_mutex_t *list_mutex;
165 
166 } globals;
167 
168 switch_endpoint_interface_t *skypopen_endpoint_interface;
169 switch_memory_pool_t *skypopen_module_pool = NULL;
170 int running = 0;
171 
172 // CLOUDTREE (THomas Hazel)
173 #ifndef WIN32
174 struct SkypopenList global_handles_list;
175 extern int xio_error_handler(Display * dpy);
176 extern int X11_errors_handler(Display * dpy, XErrorEvent * err);
177 extern int xio_error_handler2(Display * dpy, XErrorEvent * err);
178 #endif
179 
180 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_context, globals.context);
181 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan);
182 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_destination, globals.destination);
183 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_skype_user, globals.skype_user);
184 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_report_incoming_chatmessages, globals.report_incoming_chatmessages);
185 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_silent_mode, globals.silent_mode);
186 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_write_silence_when_idle, globals.write_silence_when_idle);
187 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_setsockopt, globals.setsockopt);
188 
189 static switch_status_t interface_exists(char *the_interface);
190 /* CLOUDTREE (Thomas Hazel) static*/ switch_status_t remove_interface(char *the_interface, /* CLOUDTREE (Thomas Hazel */ switch_bool_t force);
191 
192 static switch_status_t channel_on_init(switch_core_session_t *session);
193 static switch_status_t channel_on_hangup(switch_core_session_t *session);
194 //static switch_status_t channel_on_reset(switch_core_session_t *session);
195 static switch_status_t channel_on_destroy(switch_core_session_t *session);
196 static switch_status_t channel_on_routing(switch_core_session_t *session);
197 static switch_status_t channel_on_exchange_media(switch_core_session_t *session);
198 static switch_status_t channel_on_consume_media(switch_core_session_t *session);
199 static switch_status_t channel_on_soft_execute(switch_core_session_t *session);
200 static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session,
201 													switch_event_t *var_event,
202 													switch_caller_profile_t *outbound_profile,
203 													switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
204 													switch_call_cause_t *cancel_cause);
205 static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
206 static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
207 static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
208 static switch_status_t skypopen_tech_init(private_t *tech_pvt, switch_core_session_t *session);
209 
skypopen_codec(private_t * tech_pvt,int sample_rate,int codec_ms)210 static switch_status_t skypopen_codec(private_t *tech_pvt, int sample_rate, int codec_ms)
211 {
212 	switch_core_session_t *session = NULL;
213 
214 	if (switch_core_codec_init
215 		(&tech_pvt->read_codec, "L16", NULL, NULL, sample_rate, codec_ms, 1,
216 		 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
217 		ERRORA("skypopen_codec: Can't load codec?\n", SKYPOPEN_P_LOG);
218 		return SWITCH_STATUS_FALSE;
219 	}
220 
221 	if (switch_core_codec_init
222 		(&tech_pvt->write_codec, "L16", NULL, NULL, sample_rate, codec_ms, 1,
223 		 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
224 		ERRORA("skypopen_codec: Can't load codec?\n", SKYPOPEN_P_LOG);
225 		switch_core_codec_destroy(&tech_pvt->read_codec);
226 		return SWITCH_STATUS_FALSE;
227 	}
228 
229 	tech_pvt->read_frame.rate = sample_rate;
230 	tech_pvt->read_frame.codec = &tech_pvt->read_codec;
231 
232 	session = switch_core_session_locate(tech_pvt->session_uuid_str);
233 
234 	if (session) {
235 		switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
236 		switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
237 		switch_core_session_rwunlock(session);
238 	} else {
239 		ERRORA("skypopen_codec: no session\n", SKYPOPEN_P_LOG);
240 		return SWITCH_STATUS_FALSE;
241 	}
242 
243 	DEBUGA_SKYPE("codecs UP\n", SKYPOPEN_P_LOG);
244 	return SWITCH_STATUS_SUCCESS;
245 
246 }
247 
skypopen_tech_init(private_t * tech_pvt,switch_core_session_t * session)248 switch_status_t skypopen_tech_init(private_t *tech_pvt, switch_core_session_t *session)
249 {
250 
251 	switch_assert(tech_pvt != NULL);
252 	switch_assert(session != NULL);
253 	tech_pvt->read_frame.data = tech_pvt->databuf;
254 	tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
255 	switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
256 	switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
257 	switch_core_session_set_private(session, tech_pvt);
258 	switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt->session_uuid_str));
259 	if (!strlen(tech_pvt->session_uuid_str)) {
260 		ERRORA("skypopen_tech_init: no tech_pvt->session_uuid_str\n", SKYPOPEN_P_LOG);
261 		return SWITCH_STATUS_FALSE;
262 	}
263 	if (skypopen_codec(tech_pvt, SAMPLERATE_SKYPOPEN, MS_SKYPOPEN) != SWITCH_STATUS_SUCCESS) {
264 		ERRORA("skypopen_tech_init: skypopen_codec FAILED\n", SKYPOPEN_P_LOG);
265 		return SWITCH_STATUS_FALSE;
266 	}
267 
268 	dtmf_rx_init(&tech_pvt->dtmf_state, NULL, NULL);
269 	dtmf_rx_parms(&tech_pvt->dtmf_state, 0, 10, 10, -99);
270 
271 
272 	DEBUGA_SKYPE("skypopen_tech_init SUCCESS\n", SKYPOPEN_P_LOG);
273 	return SWITCH_STATUS_SUCCESS;
274 }
275 
interface_exists(char * the_interface)276 static switch_status_t interface_exists(char *the_interface)
277 {
278 	int i;
279 	int interface_id;
280 
281 	if (*the_interface == '#') {	/* look by interface id or interface name */
282 		the_interface++;
283 		switch_assert(the_interface);
284 		interface_id = atoi(the_interface);
285 
286 		/* take a number as interface id */
287 		if (interface_id > 0 || (interface_id == 0 && strcmp(the_interface, "0") == 0)) {
288 			if (strlen(globals.SKYPOPEN_INTERFACES[interface_id].name)) {
289 				return SWITCH_STATUS_SUCCESS;
290 			}
291 		} else {
292 			/* interface name */
293 			for (interface_id = 0; interface_id < SKYPOPEN_MAX_INTERFACES; interface_id++) {
294 				if (strcmp(globals.SKYPOPEN_INTERFACES[interface_id].name, the_interface) == 0) {
295 					return SWITCH_STATUS_SUCCESS;
296 					break;
297 				}
298 			}
299 		}
300 	} else {					/* look by skype_user */
301 
302 
303 		for (i = 0; i < SKYPOPEN_MAX_INTERFACES; i++) {
304 			if (strlen(globals.SKYPOPEN_INTERFACES[i].skype_user)) {
305 				if (strcmp(globals.SKYPOPEN_INTERFACES[i].skype_user, the_interface) == 0) {
306 					return SWITCH_STATUS_SUCCESS;
307 				}
308 			}
309 		}
310 	}
311 	return SWITCH_STATUS_FALSE;
312 }
313 
remove_interface(char * the_interface,switch_bool_t force)314 /* CLOUDTREE (Thomas Hazel) static */ switch_status_t remove_interface(char *the_interface, /* CLOUDTREE (Thomas Hazel) */ switch_bool_t force)
315 {
316 	int x = 10;
317 	switch_size_t howmany = 8;
318 	int interface_id = -1;
319 	private_t *tech_pvt = NULL;
320 	switch_status_t status;
321 
322 
323 	if (*the_interface == '#') {	/* remove by interface id or interface name */
324 		the_interface++;
325 		switch_assert(the_interface);
326 		interface_id = atoi(the_interface);
327 
328 		if (interface_id > 0 || (interface_id == 0 && strcmp(the_interface, "0") == 0)) {
329 			/* take a number as interface id */
330 			tech_pvt = &globals.SKYPOPEN_INTERFACES[interface_id];
331 		} else {
332 
333 			for (interface_id = 0; interface_id < SKYPOPEN_MAX_INTERFACES; interface_id++) {
334 				if (strcmp(globals.SKYPOPEN_INTERFACES[interface_id].name, the_interface) == 0) {
335 					tech_pvt = &globals.SKYPOPEN_INTERFACES[interface_id];
336 					break;
337 				}
338 			}
339 		}
340 	} else {					/* remove by skype_user */
341 		for (interface_id = 0; interface_id < SKYPOPEN_MAX_INTERFACES; interface_id++) {
342 			if (strcmp(globals.SKYPOPEN_INTERFACES[interface_id].skype_user, the_interface) == 0) {
343 				tech_pvt = &globals.SKYPOPEN_INTERFACES[interface_id];
344 				break;
345 			}
346 		}
347 	}
348 
349 	if (!tech_pvt) {
350 		DEBUGA_SKYPE("interface '%s' does not exist\n", SKYPOPEN_P_LOG, the_interface);
351 		goto end;
352 	}
353 
354 	if ( /* CLOUDTREE (Thomas Hazel) */ (force == FALSE) && strlen(globals.SKYPOPEN_INTERFACES[interface_id].session_uuid_str)) {
355 		DEBUGA_SKYPE("interface '%s' is busy\n", SKYPOPEN_P_LOG, the_interface);
356 		goto end;
357 	}
358 
359 	globals.SKYPOPEN_INTERFACES[interface_id].running = 0;
360 
361 	tech_pvt->interface_state = SKYPOPEN_STATE_DEAD;
362 
363 	if (globals.SKYPOPEN_INTERFACES[interface_id].skypopen_signaling_thread) {
364 #ifdef WIN32
365 		skypopen_signaling_write(tech_pvt, "DIE");
366 		switch_sleep(20000);
367 		switch_file_write(tech_pvt->SkypopenHandles.fdesc[1], "sciutati", &howmany);	// let's the controldev_thread die
368 #else /* WIN32 */
369 		howmany = write(tech_pvt->SkypopenHandles.fdesc[1], "sciutati", howmany);
370 #endif /* WIN32 */
371 	}
372 
373 	if (globals.SKYPOPEN_INTERFACES[interface_id].skypopen_api_thread) {
374 #ifdef WIN32
375 		if (SendMessage(tech_pvt->SkypopenHandles.win32_hInit_MainWindowHandle, WM_DESTROY, 0, 0) == FALSE) {	// let's the skypopen_api_thread_func die
376 			DEBUGA_SKYPE("got FALSE here, thread probably was already dead. GetLastError returned: %d\n", SKYPOPEN_P_LOG, GetLastError());
377 			globals.SKYPOPEN_INTERFACES[interface_id].skypopen_api_thread = NULL;
378 		}
379 #else
380 		if (tech_pvt->running && tech_pvt->SkypopenHandles.disp) {
381 			XEvent e;
382 			Atom atom1 = XInternAtom(tech_pvt->SkypopenHandles.disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
383 			switch_sleep(20000);
384 			XFlush(tech_pvt->SkypopenHandles.disp);
385 			memset(&e, 0, sizeof(e));
386 			e.xclient.type = ClientMessage;
387 			e.xclient.message_type = atom1;	/*  leading message */
388 			e.xclient.display = tech_pvt->SkypopenHandles.disp;
389 			e.xclient.window = tech_pvt->SkypopenHandles.skype_win;
390 			e.xclient.format = 8;
391 
392 			XSendEvent(tech_pvt->SkypopenHandles.disp, tech_pvt->SkypopenHandles.win, False, 0, &e);
393 			XFlush(tech_pvt->SkypopenHandles.disp);
394 		}
395 #endif
396 	}
397 
398 	while (x) {
399 		x--;
400 		switch_yield(50000);
401 	}
402 
403 #ifndef WIN32
404 	if (tech_pvt->SkypopenHandles.disp) {
405 	}
406 #endif
407 
408 	if (globals.SKYPOPEN_INTERFACES[interface_id].skypopen_signaling_thread) {
409 		switch_thread_join(&status, globals.SKYPOPEN_INTERFACES[interface_id].skypopen_signaling_thread);
410 	}
411 
412 	if (globals.SKYPOPEN_INTERFACES[interface_id].skypopen_api_thread) {
413 		switch_thread_join(&status, globals.SKYPOPEN_INTERFACES[interface_id].skypopen_api_thread);
414 	}
415 
416 	switch_mutex_lock(globals.mutex);
417 	if (globals.sk_console == &globals.SKYPOPEN_INTERFACES[interface_id]) {
418 		DEBUGA_SKYPE("interface '%s' no more console\n", SKYPOPEN_P_LOG, the_interface);
419 		globals.sk_console = NULL;
420 	} else {
421 		DEBUGA_SKYPE("interface '%s' STILL console\n", SKYPOPEN_P_LOG, the_interface);
422 	}
423 	if (strlen(tech_pvt->session_uuid_str)) {
424 
425 	} else {
426 		memset(&globals.SKYPOPEN_INTERFACES[interface_id], '\0', sizeof(private_t));
427 	}
428 	globals.real_interfaces--;
429 	switch_mutex_unlock(globals.mutex);
430 
431 	DEBUGA_SKYPE("interface '%s' deleted successfully\n", SKYPOPEN_P_LOG, the_interface);
432 	globals.SKYPOPEN_INTERFACES[interface_id].running = 1;
433   end:
434 	return SWITCH_STATUS_SUCCESS;
435 }
436 
437 
438 /*
439    State methods they get called when the state changes to the specific state
440    returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
441    so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
442 */
channel_on_init(switch_core_session_t * session)443 static switch_status_t channel_on_init(switch_core_session_t *session)
444 {
445 	switch_channel_t *channel;
446 	private_t *tech_pvt = NULL;
447 
448 	tech_pvt = switch_core_session_get_private(session);
449 	switch_assert(tech_pvt != NULL);
450 
451 	channel = switch_core_session_get_channel(session);
452 	switch_assert(channel != NULL);
453 	memset(tech_pvt->skype_voicemail_id, '\0', sizeof(tech_pvt->skype_voicemail_id));
454 	memset(tech_pvt->skype_voicemail_id_greeting, '\0', sizeof(tech_pvt->skype_voicemail_id_greeting));
455 	switch_channel_set_variable(channel, "skype_user", tech_pvt->skype_user);
456 	switch_mutex_lock(tech_pvt->flag_mutex);
457 	switch_set_flag(tech_pvt, TFLAG_IO);
458 	switch_mutex_unlock(tech_pvt->flag_mutex);
459 
460 	DEBUGA_SKYPE("%s CHANNEL INIT %s\n", SKYPOPEN_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session));
461 	switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt->session_uuid_str));
462 
463 	return SWITCH_STATUS_SUCCESS;
464 }
465 
channel_on_destroy(switch_core_session_t * session)466 static switch_status_t channel_on_destroy(switch_core_session_t *session)
467 {
468 	private_t *tech_pvt = NULL;
469 	switch_status_t status;
470 	int conta;
471 
472 	tech_pvt = switch_core_session_get_private(session);
473 
474 
475 	if (tech_pvt) {
476 		DEBUGA_SKYPE("%s CHANNEL DESTROY %s\n", SKYPOPEN_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session));
477 
478 		if (tech_pvt->interface_state != SKYPOPEN_STATE_DEAD) {
479 			tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
480 		}
481 
482 		switch_mutex_lock(tech_pvt->flag_mutex);
483 		switch_clear_flag(tech_pvt, TFLAG_IO);
484 		switch_clear_flag(tech_pvt, TFLAG_VOICE);
485 		if (switch_test_flag(tech_pvt, TFLAG_PROGRESS)) {
486 			switch_clear_flag(tech_pvt, TFLAG_PROGRESS);
487 		}
488 		switch_mutex_unlock(tech_pvt->flag_mutex);
489 
490 		DEBUGA_SKYPE("audio tcp threads to DIE\n", SKYPOPEN_P_LOG);
491 		conta = 0;
492 		while (tech_pvt->tcp_srv_thread) {
493 			switch_sleep(50000);
494 			conta++;
495 			if (conta == 20) {
496 				ERRORA("tcp_srv_thread is NOT dead, this can LEAK MEMORY\n", SKYPOPEN_P_LOG);
497 				break;
498 			}
499 		}
500 		DEBUGA_SKYPE("audio tcp srv thread DEAD %d\n", SKYPOPEN_P_LOG, conta);
501 		conta = 0;
502 		while (tech_pvt->tcp_cli_thread) {
503 			switch_sleep(50000);
504 			conta++;
505 			if (conta == 20) {
506 				ERRORA("tcp_cli_thread is NOT dead, this can LEAK MEMORY\n", SKYPOPEN_P_LOG);
507 				break;
508 			}
509 		}
510 		DEBUGA_SKYPE("audio tcp cli thread DEAD %d\n", SKYPOPEN_P_LOG, conta);
511 
512 
513 		if (switch_core_codec_ready(&tech_pvt->read_codec)) {
514 			switch_core_codec_destroy(&tech_pvt->read_codec);
515 		}
516 
517 		if (switch_core_codec_ready(&tech_pvt->write_codec)) {
518 			switch_core_codec_destroy(&tech_pvt->write_codec);
519 		}
520 
521 		DEBUGA_SKYPE("codecs DOWN\n", SKYPOPEN_P_LOG);
522 		if (tech_pvt->timer_read.timer_interface && tech_pvt->timer_read.timer_interface->timer_next) {
523 			switch_core_timer_destroy(&tech_pvt->timer_read);
524 		}
525 
526 		if (tech_pvt->timer_read_srv.timer_interface && tech_pvt->timer_read_srv.timer_interface->timer_next) {
527 			switch_core_timer_destroy(&tech_pvt->timer_read_srv);
528 		}
529 
530 		if (tech_pvt->timer_write.timer_interface && tech_pvt->timer_write.timer_interface->timer_next) {
531 			switch_core_timer_destroy(&tech_pvt->timer_write);
532 		}
533 
534 		if (tech_pvt->read_buffer) {
535 			switch_buffer_destroy(&tech_pvt->read_buffer);
536 		}
537 		if (tech_pvt->write_buffer) {
538 			switch_buffer_destroy(&tech_pvt->write_buffer);
539 		}
540 		//DEBUGA_SKYPE("debugging_hangup 13\n", SKYPOPEN_P_LOG);
541 		switch_mutex_lock(tech_pvt->mutex_thread_audio_cli);
542 		//DEBUGA_SKYPE("debugging_hangup cli lock\n", SKYPOPEN_P_LOG);
543 		if (tech_pvt->tcp_cli_thread) {
544 			//DEBUGA_SKYPE("debugging_hangup 14\n", SKYPOPEN_P_LOG);
545 			switch_thread_join(&status, tech_pvt->tcp_cli_thread);
546 			tech_pvt->tcp_cli_thread = NULL;
547 			//DEBUGA_SKYPE("debugging_hangup 15\n", SKYPOPEN_P_LOG);
548 		}
549 		switch_mutex_unlock(tech_pvt->mutex_thread_audio_cli);
550 		//DEBUGA_SKYPE("debugging_hangup cli unlock\n", SKYPOPEN_P_LOG);
551 		switch_mutex_lock(tech_pvt->mutex_thread_audio_srv);
552 		//DEBUGA_SKYPE("debugging_hangup srv lock\n", SKYPOPEN_P_LOG);
553 		if (tech_pvt->tcp_srv_thread) {
554 			//DEBUGA_SKYPE("debugging_hangup 16\n", SKYPOPEN_P_LOG);
555 			switch_thread_join(&status, tech_pvt->tcp_srv_thread);
556 			tech_pvt->tcp_srv_thread = NULL;
557 			//DEBUGA_SKYPE("debugging_hangup 17\n", SKYPOPEN_P_LOG);
558 		}
559 		switch_mutex_unlock(tech_pvt->mutex_thread_audio_srv);
560 		//DEBUGA_SKYPE("debugging_hangup srv unlock\n", SKYPOPEN_P_LOG);
561 		//DEBUGA_SKYPE("debugging_hangup 18\n", SKYPOPEN_P_LOG);
562 
563 		*tech_pvt->session_uuid_str = '\0';
564 
565 		if (tech_pvt->interface_state != SKYPOPEN_STATE_DEAD) {
566 			tech_pvt->interface_state = SKYPOPEN_STATE_IDLE;
567 			tech_pvt->skype_callflow = CALLFLOW_CALL_IDLE;
568 		} else {
569 			memset(tech_pvt, '\0', sizeof(private_t));
570 		}
571 		switch_core_session_set_private(session, NULL);
572 	} else {
573 		DEBUGA_SKYPE("!!!!!!NO tech_pvt!!!! CHANNEL DESTROY %s\n", SKYPOPEN_P_LOG, switch_core_session_get_uuid(session));
574 	}
575 
576 	DEBUGA_SKYPE("CHANNEL DESTROYED %s\n", SKYPOPEN_P_LOG, switch_core_session_get_uuid(session));
577 	return SWITCH_STATUS_SUCCESS;
578 }
579 
channel_on_hangup(switch_core_session_t * session)580 static switch_status_t channel_on_hangup(switch_core_session_t *session)
581 {
582 	switch_channel_t *channel = NULL;
583 	private_t *tech_pvt = NULL;
584 	char msg_to_skype[256];
585 	//switch_status_t status;
586 
587 
588 	channel = switch_core_session_get_channel(session);
589 	switch_assert(channel != NULL);
590 
591 	tech_pvt = switch_core_session_get_private(session);
592 
593 	//DEBUGA_SKYPE("debugging_hangup 1\n", SKYPOPEN_P_LOG);
594 
595 	if (tech_pvt) {
596 		if (tech_pvt->interface_state == SKYPOPEN_STATE_DEAD) {
597 			return SWITCH_STATUS_SUCCESS;
598 		}
599 		if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
600 			if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
601 				tech_pvt->ob_failed_calls++;
602 			} else {
603 				tech_pvt->ib_failed_calls++;
604 			}
605 		}
606 
607 		tech_pvt->interface_state = SKYPOPEN_STATE_HANGUP_REQUESTED;
608 		switch_mutex_lock(tech_pvt->flag_mutex);
609 		switch_clear_flag(tech_pvt, TFLAG_IO);
610 		switch_clear_flag(tech_pvt, TFLAG_VOICE);
611 		if (switch_test_flag(tech_pvt, TFLAG_PROGRESS)) {
612 			switch_clear_flag(tech_pvt, TFLAG_PROGRESS);
613 		}
614 		switch_mutex_unlock(tech_pvt->flag_mutex);
615 
616 
617 		//DEBUGA_SKYPE("debugging_hangup 2\n", SKYPOPEN_P_LOG);
618 
619 		if (strlen(tech_pvt->skype_call_id)) {
620 			DEBUGA_SKYPE("hanging up skype call: %s\n", SKYPOPEN_P_LOG, tech_pvt->skype_call_id);
621 			if(strlen(tech_pvt->skype_voicemail_id_greeting)){
622 				sprintf(msg_to_skype, "ALTER VOICEMAIL %s STOPPLAYBACK", tech_pvt->skype_voicemail_id_greeting);
623 				skypopen_signaling_write(tech_pvt, msg_to_skype);
624 				switch_sleep(MS_SKYPOPEN * 1000 * 100);//XXX FIXME 2000 millisecs, 2 seconds, so it will record at least 1 second
625 			}
626 
627 			if(strlen(tech_pvt->skype_voicemail_id_greeting)){
628 				sprintf(msg_to_skype, "ALTER VOICEMAIL %s DELETE", tech_pvt->skype_voicemail_id_greeting);
629 				skypopen_signaling_write(tech_pvt, msg_to_skype);
630 				switch_sleep(MS_SKYPOPEN * 1000 * 10);//XXX FIXME 200 millisecs
631 			}
632 			if(strlen(tech_pvt->skype_voicemail_id)){
633 				sprintf(msg_to_skype, "ALTER VOICEMAIL %s STOPRECORDING", tech_pvt->skype_voicemail_id);
634 				skypopen_signaling_write(tech_pvt, msg_to_skype);
635 				switch_sleep(MS_SKYPOPEN * 1000 * 10);//XXX FIXME 200 millisecs
636 			}
637 			sprintf(msg_to_skype, "ALTER CALL %s HANGUP", tech_pvt->skype_call_id);
638 			skypopen_signaling_write(tech_pvt, msg_to_skype);
639 			sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", tech_pvt->skype_call_id);
640 			skypopen_signaling_write(tech_pvt, msg_to_skype);
641 		}
642 		DEBUGA_SKYPE("%s CHANNEL HANGUP\n", SKYPOPEN_P_LOG, tech_pvt->name);
643 		switch_mutex_lock(globals.mutex);
644 		globals.calls--;
645 		if (globals.calls < 0) {
646 			globals.calls = 0;
647 		}
648 		//DEBUGA_SKYPE("debugging_hangup 9\n", SKYPOPEN_P_LOG);
649 		tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
650 		if (tech_pvt->skype_callflow == CALLFLOW_STATUS_FINISHED) {
651 			tech_pvt->skype_callflow = CALLFLOW_CALL_IDLE;
652 		}
653 		//DEBUGA_SKYPE("debugging_hangup 10\n", SKYPOPEN_P_LOG);
654 		switch_mutex_unlock(globals.mutex);
655 	} else {
656 		WARNINGA("FYI %s CHANNEL has no tech_pvt in his private\n", SKYPOPEN_P_LOG, switch_channel_get_name(channel));
657 		//DEBUGA_SKYPE("debugging_hangup 11\n", SKYPOPEN_P_LOG);
658 	}
659 	//DEBUGA_SKYPE("debugging_hangup 12\n", SKYPOPEN_P_LOG);
660 
661 	//switch_channel_set_state(channel, CS_DESTROY);
662 
663 	return SWITCH_STATUS_SUCCESS;
664 }
665 
channel_on_routing(switch_core_session_t * session)666 static switch_status_t channel_on_routing(switch_core_session_t *session)
667 {
668 	//switch_channel_t *channel = NULL;
669 	private_t *tech_pvt = NULL;
670 
671 	//channel = switch_core_session_get_channel(session);
672 	//switch_assert(channel != NULL);
673 
674 	tech_pvt = switch_core_session_get_private(session);
675 	switch_assert(tech_pvt != NULL);
676 
677 	DEBUGA_SKYPE("%s CHANNEL ROUTING\n", SKYPOPEN_P_LOG, tech_pvt->name);
678 
679 	return SWITCH_STATUS_SUCCESS;
680 }
681 
channel_on_execute(switch_core_session_t * session)682 static switch_status_t channel_on_execute(switch_core_session_t *session)
683 {
684 
685 	switch_channel_t *channel = NULL;
686 	private_t *tech_pvt = NULL;
687 
688 	channel = switch_core_session_get_channel(session);
689 	switch_assert(channel != NULL);
690 
691 	tech_pvt = switch_core_session_get_private(session);
692 	switch_assert(tech_pvt != NULL);
693 
694 	DEBUGA_SKYPE("%s CHANNEL EXECUTE\n", SKYPOPEN_P_LOG, tech_pvt->name);
695 
696 	return SWITCH_STATUS_SUCCESS;
697 }
698 
channel_kill_channel(switch_core_session_t * session,int sig)699 static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig)
700 {
701 	switch_channel_t *channel = NULL;
702 	private_t *tech_pvt = NULL;
703 
704 	channel = switch_core_session_get_channel(session);
705 	switch_assert(channel != NULL);
706 
707 	tech_pvt = switch_core_session_get_private(session);
708 
709 	//DEBUGA_SKYPE("%s CHANNEL KILL_CHANNEL\n", SKYPOPEN_P_LOG, tech_pvt->name);
710 	if (tech_pvt) {
711 		switch (sig) {
712 		case SWITCH_SIG_KILL:
713 			DEBUGA_SKYPE("%s CHANNEL got SWITCH_SIG_KILL\n", SKYPOPEN_P_LOG, switch_channel_get_name(channel));
714 			if (tech_pvt->interface_state == SKYPOPEN_STATE_DEAD) {
715 				switch_channel_set_state(channel, CS_HANGUP);
716 				return SWITCH_STATUS_SUCCESS;
717 			}
718 			tech_pvt->interface_state = SKYPOPEN_STATE_HANGUP_REQUESTED;
719 			if (tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD) {
720 				DEBUGA_SKYPE("FYI %s CHANNEL in CALLFLOW_STATUS_REMOTEHOLD got SWITCH_SIG_KILL\n", SKYPOPEN_P_LOG, switch_channel_get_name(channel));
721 			}
722 			if (switch_channel_get_state(channel) == CS_NEW) {
723 				WARNINGA("FYI %s CHANNEL in CS_NEW state got SWITCH_SIG_KILL\n", SKYPOPEN_P_LOG, switch_channel_get_name(channel));
724 			}
725 			if (switch_channel_get_state(channel) != CS_NEW && switch_channel_get_state(channel) < CS_EXECUTE) {
726 				WARNINGA("FYI %s CHANNEL in %d state got SWITCH_SIG_KILL\n", SKYPOPEN_P_LOG, switch_channel_get_name(channel),
727 						 switch_channel_get_state(channel));
728 			}
729 
730 			switch_mutex_lock(tech_pvt->flag_mutex);
731 			switch_clear_flag(tech_pvt, TFLAG_IO);
732 			switch_clear_flag(tech_pvt, TFLAG_VOICE);
733 			switch_set_flag(tech_pvt, TFLAG_HANGUP);
734 			if (switch_test_flag(tech_pvt, TFLAG_PROGRESS)) {
735 				switch_clear_flag(tech_pvt, TFLAG_PROGRESS);
736 			}
737 			switch_mutex_unlock(tech_pvt->flag_mutex);
738 			break;
739 		case SWITCH_SIG_BREAK:
740 			DEBUGA_SKYPE("%s CHANNEL got SWITCH_SIG_BREAK\n", SKYPOPEN_P_LOG, switch_channel_get_name(channel));
741 			switch_mutex_lock(tech_pvt->flag_mutex);
742 			switch_set_flag(tech_pvt, TFLAG_BREAK);
743 			switch_mutex_unlock(tech_pvt->flag_mutex);
744 			break;
745 		default:
746 			break;
747 		}
748 	} else {
749 		WARNINGA("FYI %s CHANNEL has no tech_pvt in his private\n", SKYPOPEN_P_LOG, switch_channel_get_name(channel));
750 	}
751 
752 	return SWITCH_STATUS_SUCCESS;
753 }
754 
channel_on_consume_media(switch_core_session_t * session)755 static switch_status_t channel_on_consume_media(switch_core_session_t *session)
756 {
757 	private_t *tech_pvt = NULL;
758 
759 	tech_pvt = switch_core_session_get_private(session);
760 
761 	DEBUGA_SKYPE("%s CHANNEL CONSUME_MEDIA\n", SKYPOPEN_P_LOG, tech_pvt->name);
762 	return SWITCH_STATUS_SUCCESS;
763 }
764 
765 
channel_on_exchange_media(switch_core_session_t * session)766 static switch_status_t channel_on_exchange_media(switch_core_session_t *session)
767 {
768 	private_t *tech_pvt = NULL;
769 	tech_pvt = switch_core_session_get_private(session);
770 	DEBUGA_SKYPE("%s CHANNEL EXCHANGE_MEDIA\n", SKYPOPEN_P_LOG, tech_pvt->name);
771 	return SWITCH_STATUS_SUCCESS;
772 }
773 
channel_on_soft_execute(switch_core_session_t * session)774 static switch_status_t channel_on_soft_execute(switch_core_session_t *session)
775 {
776 	private_t *tech_pvt = NULL;
777 	tech_pvt = switch_core_session_get_private(session);
778 	DEBUGA_SKYPE("%s CHANNEL SOFT_EXECUTE\n", SKYPOPEN_P_LOG, tech_pvt->name);
779 	return SWITCH_STATUS_SUCCESS;
780 }
781 
782 #if 0
783 static switch_status_t channel_on_reset(switch_core_session_t *session)
784 {
785 	private_t *tech_pvt = NULL;
786 	switch_channel_t *channel = NULL;
787 	tech_pvt = switch_core_session_get_private(session);
788 	DEBUGA_SKYPE("%s CHANNEL RESET\n", SKYPOPEN_P_LOG, tech_pvt->name);
789 
790 
791 	if (session) {
792 		channel = switch_core_session_get_channel(session);
793 	} else {
794 		ERRORA("No session???\n", SKYPOPEN_P_LOG);
795 	}
796 	if (channel) {
797 		switch_channel_set_state(channel, CS_HANGUP);
798 	} else {
799 		ERRORA("No channel???\n", SKYPOPEN_P_LOG);
800 	}
801 
802 
803 	return SWITCH_STATUS_SUCCESS;
804 }
805 #endif //0
806 
807 
channel_send_dtmf(switch_core_session_t * session,const switch_dtmf_t * dtmf)808 static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
809 {
810 	private_t *tech_pvt = switch_core_session_get_private(session);
811 	switch_assert(tech_pvt != NULL);
812 
813 	DEBUGA_SKYPE("%s CHANNEL SEND_DTMF\n", SKYPOPEN_P_LOG, tech_pvt->name);
814 	DEBUGA_SKYPE("DTMF: %c\n", SKYPOPEN_P_LOG, dtmf->digit);
815 
816 	skypopen_senddigit(tech_pvt, dtmf->digit);
817 
818 	return SWITCH_STATUS_SUCCESS;
819 }
820 
channel_read_frame(switch_core_session_t * session,switch_frame_t ** frame,switch_io_flag_t flags,int stream_id)821 static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
822 {
823 	switch_channel_t *channel = NULL;
824 	private_t *tech_pvt = NULL;
825 	switch_byte_t *data;
826 	char digit_str[256];
827 	short *frame_16_khz;
828 	short frame_8_khz[160];
829 	unsigned int i;
830 	unsigned int a;
831 	size_t bytes_read = 0;
832 	int try = 0;
833 
834 
835 	*frame = NULL;
836 
837 	channel = switch_core_session_get_channel(session);
838 	switch_assert(channel != NULL);
839 
840 	tech_pvt = switch_core_session_get_private(session);
841 	switch_assert(tech_pvt != NULL);
842 
843 	tech_pvt->read_frame.flags = SFF_NONE;
844 
845 	if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
846 		switch_sleep(MS_SKYPOPEN * 1000);
847 		return SWITCH_STATUS_FALSE;
848 	}
849 	if (!switch_channel_ready(channel)) {
850 		ERRORA("channel not ready \n", SKYPOPEN_P_LOG);
851 		switch_sleep(MS_SKYPOPEN * 1000);
852 		return SWITCH_STATUS_FALSE;
853 	}
854 
855 	if (switch_test_flag(tech_pvt, TFLAG_PROGRESS)) {
856 		//DEBUGA_SKYPE("CHANNEL READ FRAME in TFLAG_PROGRESS goto CNG\n", SKYPOPEN_P_LOG);
857 		//switch_sleep(MS_SKYPOPEN * 1000);
858 		goto cng;
859 	}
860 
861 	if (!tech_pvt->read_buffer) {
862 		int32_t max_len = BYTES_PER_FRAME * 10;
863 
864 		switch_buffer_create(skypopen_module_pool, &tech_pvt->read_buffer, max_len);
865 		switch_assert(tech_pvt->read_buffer);
866 		switch_buffer_zero(tech_pvt->read_buffer);
867 		tech_pvt->begin_to_read = 1;
868 	}
869 
870 
871 
872 	if (tech_pvt->timer_read.timer_interface && tech_pvt->timer_read.timer_interface->timer_next) {
873 		switch_core_timer_next(&tech_pvt->timer_read);
874 	}
875 
876 	try = 0;
877   read:
878 
879 
880 	if (tech_pvt && tech_pvt->interface_state != SKYPOPEN_STATE_DOWN
881 		&& (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
882 			|| tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
883 			|| tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPOPEN_STATE_UP)) {
884 		switch_mutex_lock(tech_pvt->mutex_audio_srv);
885 		if (tech_pvt->read_buffer && switch_buffer_inuse(tech_pvt->read_buffer)) {
886 			bytes_read = switch_buffer_read(tech_pvt->read_buffer, tech_pvt->read_frame.data, BYTES_PER_FRAME);
887 			tech_pvt->read_frame.datalen = (uint32_t)bytes_read;
888 		}
889 		switch_mutex_unlock(tech_pvt->mutex_audio_srv);
890 
891 		if (!bytes_read) {
892 			switch_sleep(1000);	//XXX don't like this
893 			try++;
894 			if (try < 5) {
895 				//DEBUGA_SKYPE("skypopen_audio_read going back to read\n", SKYPOPEN_P_LOG);
896 				goto read;
897 			}
898 
899 			if (!strlen(tech_pvt->skype_voicemail_id)) {
900 				DEBUGA_SKYPE("READ BUFFER EMPTY, skypopen_audio_read Silence\n", SKYPOPEN_P_LOG);
901 			}
902 			memset(tech_pvt->read_frame.data, 255, BYTES_PER_FRAME);
903 			tech_pvt->read_frame.datalen = BYTES_PER_FRAME;
904 
905 		}
906 	} else {
907 		memset(tech_pvt->read_frame.data, 255, BYTES_PER_FRAME);
908 		tech_pvt->read_frame.datalen = BYTES_PER_FRAME;
909 	}
910 
911 	switch_mutex_lock(tech_pvt->flag_mutex);
912 	switch_set_flag(tech_pvt, TFLAG_VOICE);
913 	switch_mutex_unlock(tech_pvt->flag_mutex);
914 
915 	while (switch_test_flag(tech_pvt, TFLAG_IO)) {
916 		if (switch_test_flag(tech_pvt, TFLAG_BREAK)) {
917 			switch_mutex_lock(tech_pvt->flag_mutex);
918 			switch_clear_flag(tech_pvt, TFLAG_BREAK);
919 			switch_mutex_unlock(tech_pvt->flag_mutex);
920 			DEBUGA_SKYPE("CHANNEL READ FRAME goto CNG\n", SKYPOPEN_P_LOG);
921 			goto cng;
922 		}
923 
924 		if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
925 			DEBUGA_SKYPE("CHANNEL READ FRAME not IO\n", SKYPOPEN_P_LOG);
926 			return SWITCH_STATUS_FALSE;
927 		}
928 
929 		if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) {
930 			switch_mutex_lock(tech_pvt->flag_mutex);
931 			switch_clear_flag(tech_pvt, TFLAG_VOICE);
932 			switch_mutex_unlock(tech_pvt->flag_mutex);
933 			if (!tech_pvt->read_frame.datalen) {
934 				DEBUGA_SKYPE("CHANNEL READ CONTINUE\n", SKYPOPEN_P_LOG);
935 				continue;
936 			}
937 			*frame = &tech_pvt->read_frame;
938 
939 
940 			if (switch_true(switch_channel_get_variable(channel, "skype_get_inband_dtmf"))) {
941 
942 				frame_16_khz = tech_pvt->read_frame.data;
943 
944 				a = 0;
945 				for (i = 0; i < tech_pvt->read_frame.datalen / sizeof(short); i++) {
946 					frame_8_khz[a] = frame_16_khz[i];
947 					i++;
948 					a++;
949 				}
950 
951 				memset(digit_str, 0, sizeof(digit_str));
952 				dtmf_rx(&tech_pvt->dtmf_state, (int16_t *) frame_8_khz, 160);
953 				dtmf_rx_get(&tech_pvt->dtmf_state, digit_str, sizeof(digit_str));
954 
955 
956 				if (digit_str[0]) {
957 					switch_time_t new_dtmf_timestamp = switch_time_now();
958 					if ((new_dtmf_timestamp - tech_pvt->old_dtmf_timestamp) > 350000) {
959 						char *p = digit_str;
960 						switch_channel_t *channel = switch_core_session_get_channel(session);
961 
962 						if (channel) {
963 
964 							while (p && *p) {
965 								switch_dtmf_t dtmf = { 0 };
966 								dtmf.digit = *p;
967 								dtmf.duration = SWITCH_DEFAULT_DTMF_DURATION;
968 								switch_channel_queue_dtmf(channel, &dtmf);
969 								p++;
970 							}
971 							NOTICA("DTMF DETECTED: [%s] new_dtmf_timestamp: %u, delta_t: %u\n", SKYPOPEN_P_LOG, digit_str,
972 								   (unsigned int) new_dtmf_timestamp, (unsigned int) (new_dtmf_timestamp - tech_pvt->old_dtmf_timestamp));
973 							tech_pvt->old_dtmf_timestamp = new_dtmf_timestamp;
974 						} else {
975 							WARNINGA("NO CHANNEL ?\n", SKYPOPEN_P_LOG);
976 						}
977 					}
978 				}
979 			}
980 #if SWITCH_BYTE_ORDER == __BIG_ENDIAN
981 			if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
982 				switch_swap_linear((*frame)->data, (int) (*frame)->datalen / 2);
983 			}
984 #endif
985 			return SWITCH_STATUS_SUCCESS;
986 		}
987 		DEBUGA_SKYPE("CHANNEL READ no TFLAG_IO\n", SKYPOPEN_P_LOG);
988 		return SWITCH_STATUS_FALSE;
989 	}
990 
991 	DEBUGA_SKYPE("CHANNEL READ FALSE\n", SKYPOPEN_P_LOG);
992 	return SWITCH_STATUS_FALSE;
993 
994   cng:
995 	data = (switch_byte_t *) tech_pvt->read_frame.data;
996 	data[0] = 65;
997 	data[1] = 0;
998 	tech_pvt->read_frame.datalen = 2;
999 	tech_pvt->read_frame.flags = SFF_CNG;
1000 	*frame = &tech_pvt->read_frame;
1001 	return SWITCH_STATUS_SUCCESS;
1002 
1003 }
1004 
channel_write_frame(switch_core_session_t * session,switch_frame_t * frame,switch_io_flag_t flags,int stream_id)1005 static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
1006 {
1007 	switch_channel_t *channel = NULL;
1008 	private_t *tech_pvt = NULL;
1009 	int no_space = 0;
1010 
1011 	channel = switch_core_session_get_channel(session);
1012 	switch_assert(channel != NULL);
1013 
1014 	tech_pvt = switch_core_session_get_private(session);
1015 	switch_assert(tech_pvt != NULL);
1016 
1017 	if (switch_test_flag(tech_pvt, TFLAG_PROGRESS)) {
1018 		//DEBUGA_SKYPE("CHANNEL in TFLAG_PROGRESS\n", SKYPOPEN_P_LOG);
1019 		return SWITCH_STATUS_SUCCESS;
1020 	}
1021 
1022 	if (!switch_channel_ready(channel)) {
1023 		ERRORA("channel not ready \n", SKYPOPEN_P_LOG);
1024 		return SWITCH_STATUS_FALSE;
1025 	}
1026 	if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
1027 		DEBUGA_SKYPE("channel not in TFLAG_IO \n", SKYPOPEN_P_LOG);
1028 		return SWITCH_STATUS_FALSE;
1029 	}
1030 #if SWITCH_BYTE_ORDER == __BIG_ENDIAN
1031 	if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
1032 		switch_swap_linear(frame->data, (int) frame->datalen / 2);
1033 	}
1034 #endif
1035 	if (!tech_pvt->write_buffer) {
1036 		int32_t max_len = BYTES_PER_FRAME * 4;
1037 
1038 		switch_buffer_create(skypopen_module_pool, &tech_pvt->write_buffer, max_len);
1039 		switch_assert(tech_pvt->write_buffer);
1040 	}
1041 
1042 	switch_mutex_lock(tech_pvt->mutex_audio_cli);
1043 	if (switch_buffer_freespace(tech_pvt->write_buffer) < frame->datalen) {
1044 		switch_buffer_zero(tech_pvt->write_buffer);
1045 		no_space = 1;
1046 	}
1047 	switch_buffer_write(tech_pvt->write_buffer, frame->data, frame->datalen);
1048 	switch_mutex_unlock(tech_pvt->mutex_audio_cli);
1049 	if (no_space && !strlen(tech_pvt->skype_voicemail_id)) {
1050 		//switch_sleep(MS_SKYPOPEN * 1000);
1051 		DEBUGA_SKYPE("NO SPACE in WRITE BUFFER: there was no space for %d\n", SKYPOPEN_P_LOG, frame->datalen);
1052 	}
1053 	tech_pvt->begin_to_write = 1;
1054 
1055 	return SWITCH_STATUS_SUCCESS;
1056 }
1057 
channel_answer_channel(switch_core_session_t * session)1058 static switch_status_t channel_answer_channel(switch_core_session_t *session)
1059 {
1060 	private_t *tech_pvt;
1061 	switch_channel_t *channel = NULL;
1062 	int conta = 0;
1063 
1064 	channel = switch_core_session_get_channel(session);
1065 	switch_assert(channel != NULL);
1066 
1067 	tech_pvt = switch_core_session_get_private(session);
1068 	switch_assert(tech_pvt != NULL);
1069 
1070 	switch_mutex_lock(tech_pvt->flag_mutex);
1071 	switch_clear_flag(tech_pvt, TFLAG_IO);
1072 	switch_mutex_unlock(tech_pvt->flag_mutex);
1073 	skypopen_answer(tech_pvt);
1074 
1075 	while (!switch_test_flag(tech_pvt, TFLAG_IO)) {
1076 		if (switch_channel_get_state(channel) == CS_RESET) {
1077 			return SWITCH_STATUS_FALSE;
1078 		}
1079 		switch_sleep(50000);
1080 		conta++;
1081 		if (conta == 10) {		//0.5 seconds
1082 			return SWITCH_STATUS_FALSE;
1083 		}
1084 	}
1085 	switch_mutex_lock(globals.mutex);
1086 	globals.calls++;
1087 
1088 	switch_mutex_unlock(globals.mutex);
1089 	DEBUGA_SKYPE("%s CHANNEL ANSWER %s\n", SKYPOPEN_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session));
1090 
1091 
1092 
1093 
1094 	DEBUGA_SKYPE("ANSWERED! \n", SKYPOPEN_P_LOG);
1095 
1096 	return SWITCH_STATUS_SUCCESS;
1097 }
1098 
channel_receive_message(switch_core_session_t * session,switch_core_session_message_t * msg)1099 static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
1100 {
1101 	switch_channel_t *channel;
1102 	private_t *tech_pvt;
1103 	char msg_to_skype[256];
1104 
1105 	channel = switch_core_session_get_channel(session);
1106 	switch_assert(channel != NULL);
1107 
1108 	tech_pvt = (private_t *) switch_core_session_get_private(session);
1109 	switch_assert(tech_pvt != NULL);
1110 
1111 	switch (msg->message_id) {
1112 	case SWITCH_MESSAGE_INDICATE_PROGRESS:
1113 		{
1114 			DEBUGA_SKYPE("%s CHANNEL got SWITCH_MESSAGE_INDICATE_PROGRESS\n", SKYPOPEN_P_LOG, switch_channel_get_name(channel));
1115 			switch_mutex_lock(tech_pvt->flag_mutex);
1116 			switch_set_flag(tech_pvt, TFLAG_PROGRESS);
1117 			switch_mutex_unlock(tech_pvt->flag_mutex);
1118 		}
1119 		break;
1120 	case SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS:
1121 		{
1122 			DEBUGA_SKYPE("%s CHANNEL got SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS\n", SKYPOPEN_P_LOG, switch_channel_get_name(channel));
1123 			if (switch_test_flag(tech_pvt, TFLAG_PROGRESS)) {
1124 				sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", tech_pvt->ring_id);
1125 				skypopen_signaling_write(tech_pvt, msg_to_skype);
1126 				sprintf(msg_to_skype, "ALTER CALL %s HANGUP", tech_pvt->ring_id);
1127 				skypopen_signaling_write(tech_pvt, msg_to_skype);
1128 				sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", tech_pvt->skype_call_id);
1129 				skypopen_signaling_write(tech_pvt, msg_to_skype);
1130 				sprintf(msg_to_skype, "ALTER CALL %s HANGUP", tech_pvt->skype_call_id);
1131 				skypopen_signaling_write(tech_pvt, msg_to_skype);
1132 				switch_mutex_lock(tech_pvt->flag_mutex);
1133 				switch_clear_flag(tech_pvt, TFLAG_PROGRESS);
1134 				switch_mutex_unlock(tech_pvt->flag_mutex);
1135 			}
1136 		}
1137 		break;
1138 
1139 	case SWITCH_MESSAGE_INDICATE_ANSWER:
1140 		{
1141 			DEBUGA_SKYPE("%s CHANNEL got SWITCH_MESSAGE_INDICATE_ANSWER\n", SKYPOPEN_P_LOG, switch_channel_get_name(channel));
1142 
1143 			channel_answer_channel(session);
1144 			switch_mutex_lock(tech_pvt->flag_mutex);
1145 			switch_clear_flag(tech_pvt, TFLAG_PROGRESS);
1146 			switch_mutex_unlock(tech_pvt->flag_mutex);
1147 
1148 			if (tech_pvt->read_buffer) {
1149 				switch_mutex_lock(tech_pvt->mutex_audio_srv);
1150 				switch_buffer_zero(tech_pvt->read_buffer);
1151 				if (tech_pvt->timer_read.timer_interface && tech_pvt->timer_read.timer_interface->timer_next) {
1152 					switch_core_timer_sync(&tech_pvt->timer_read);
1153 				}
1154 				if (tech_pvt->timer_read_srv.timer_interface && tech_pvt->timer_read_srv.timer_interface->timer_next) {
1155 					switch_core_timer_sync(&tech_pvt->timer_read_srv);
1156 				}
1157 				switch_mutex_unlock(tech_pvt->mutex_audio_srv);
1158 			}
1159 
1160 			if (tech_pvt->write_buffer) {
1161 				switch_mutex_lock(tech_pvt->mutex_audio_cli);
1162 				switch_buffer_zero(tech_pvt->write_buffer);
1163 				if (tech_pvt->timer_write.timer_interface && tech_pvt->timer_write.timer_interface->timer_next) {
1164 					switch_core_timer_sync(&tech_pvt->timer_write);
1165 				}
1166 				switch_mutex_unlock(tech_pvt->mutex_audio_cli);
1167 			}
1168 			DEBUGA_SKYPE("Synching audio\n", SKYPOPEN_P_LOG);
1169 
1170 		}
1171 		break;
1172 	case SWITCH_MESSAGE_INDICATE_AUDIO_SYNC:
1173 
1174 		DEBUGA_SKYPE("%s CHANNEL got SWITCH_MESSAGE_INDICATE_AUDIO_SYNC\n", SKYPOPEN_P_LOG, switch_channel_get_name(channel));
1175 
1176 		if (tech_pvt->read_buffer) {
1177 			switch_mutex_lock(tech_pvt->mutex_audio_srv);
1178 			switch_buffer_zero(tech_pvt->read_buffer);
1179 			if (tech_pvt->timer_read.timer_interface && tech_pvt->timer_read.timer_interface->timer_next) {
1180 				switch_core_timer_sync(&tech_pvt->timer_read);
1181 			}
1182 			if (tech_pvt->timer_read_srv.timer_interface && tech_pvt->timer_read_srv.timer_interface->timer_next) {
1183 				switch_core_timer_sync(&tech_pvt->timer_read_srv);
1184 			}
1185 			switch_mutex_unlock(tech_pvt->mutex_audio_srv);
1186 		}
1187 
1188 		if (tech_pvt->write_buffer) {
1189 			switch_mutex_lock(tech_pvt->mutex_audio_cli);
1190 			switch_buffer_zero(tech_pvt->write_buffer);
1191 			if (tech_pvt->timer_write.timer_interface && tech_pvt->timer_write.timer_interface->timer_next) {
1192 				switch_core_timer_sync(&tech_pvt->timer_write);
1193 			}
1194 			switch_mutex_unlock(tech_pvt->mutex_audio_cli);
1195 		}
1196 		DEBUGA_SKYPE("Synching audio\n", SKYPOPEN_P_LOG);
1197 		break;
1198 	case SWITCH_MESSAGE_INDICATE_BRIDGE:
1199 		DEBUGA_SKYPE("%s CHANNEL got SWITCH_MESSAGE_INDICATE_BRIDGE\n", SKYPOPEN_P_LOG, switch_channel_get_name(channel));
1200 
1201 		if (tech_pvt->read_buffer) {
1202 			switch_mutex_lock(tech_pvt->mutex_audio_srv);
1203 			switch_buffer_zero(tech_pvt->read_buffer);
1204 			if (tech_pvt->timer_read.timer_interface && tech_pvt->timer_read.timer_interface->timer_next) {
1205 				switch_core_timer_sync(&tech_pvt->timer_read);
1206 			}
1207 			if (tech_pvt->timer_read_srv.timer_interface && tech_pvt->timer_read_srv.timer_interface->timer_next) {
1208 				switch_core_timer_sync(&tech_pvt->timer_read_srv);
1209 			}
1210 			switch_mutex_unlock(tech_pvt->mutex_audio_srv);
1211 		}
1212 
1213 		if (tech_pvt->write_buffer) {
1214 			switch_mutex_lock(tech_pvt->mutex_audio_cli);
1215 			switch_buffer_zero(tech_pvt->write_buffer);
1216 			if (tech_pvt->timer_write.timer_interface && tech_pvt->timer_write.timer_interface->timer_next) {
1217 				switch_core_timer_sync(&tech_pvt->timer_write);
1218 			}
1219 			switch_mutex_unlock(tech_pvt->mutex_audio_cli);
1220 		}
1221 		DEBUGA_SKYPE("Synching audio\n", SKYPOPEN_P_LOG);
1222 		break;
1223 
1224 	default:
1225 		{
1226 
1227 			DEBUGA_SKYPE("MSG_ID=%d\n", SKYPOPEN_P_LOG, msg->message_id);
1228 		}
1229 		break;
1230 	}
1231 
1232 	return SWITCH_STATUS_SUCCESS;
1233 }
1234 
channel_receive_event(switch_core_session_t * session,switch_event_t * event)1235 static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event)
1236 {
1237 	struct private_object *tech_pvt = switch_core_session_get_private(session);
1238 	char *body = switch_event_get_body(event);
1239 	switch_assert(tech_pvt != NULL);
1240 
1241 	if (!body) {
1242 		body = "";
1243 	}
1244 
1245 	WARNINGA("event: |||%s|||\n", SKYPOPEN_P_LOG, body);
1246 
1247 	return SWITCH_STATUS_SUCCESS;
1248 }
1249 
1250 switch_state_handler_table_t skypopen_state_handlers = {
1251 	/*.on_init */ channel_on_init,
1252 	/*.on_routing */ channel_on_routing,
1253 	/*.on_execute */ channel_on_execute,
1254 	/*.on_hangup */ channel_on_hangup,
1255 	/*.on_exchange_media */ channel_on_exchange_media,
1256 	/*.on_soft_execute */ channel_on_soft_execute,
1257 	/*.on_consume_media */ channel_on_consume_media,
1258 	/*.on_hibernate */ NULL,
1259 	/*.on_reset */ NULL,
1260 	/*.on_park */ NULL,
1261 	/*.on_reporting */ NULL,
1262 	/*.on_destroy */ channel_on_destroy
1263 };
1264 
1265 switch_io_routines_t skypopen_io_routines = {
1266 	/*.outgoing_channel */ channel_outgoing_channel,
1267 	/*.read_frame */ channel_read_frame,
1268 	/*.write_frame */ channel_write_frame,
1269 	/*.kill_channel */ channel_kill_channel,
1270 	/*.send_dtmf */ channel_send_dtmf,
1271 	/*.receive_message */ channel_receive_message,
1272 	/*.receive_event */ channel_receive_event
1273 };
1274 
channel_outgoing_channel(switch_core_session_t * session,switch_event_t * var_event,switch_caller_profile_t * outbound_profile,switch_core_session_t ** new_session,switch_memory_pool_t ** pool,switch_originate_flag_t flags,switch_call_cause_t * cancel_cause)1275 static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session,
1276 													switch_event_t *var_event,
1277 													switch_caller_profile_t *outbound_profile,
1278 													switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
1279 													switch_call_cause_t *cancel_cause)
1280 {
1281 	private_t *tech_pvt = NULL;
1282 	if ((*new_session = switch_core_session_request_uuid(skypopen_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool, switch_event_get_header(var_event, "origination_uuid"))) != 0) {
1283 		switch_channel_t *channel = NULL;
1284 		switch_caller_profile_t *caller_profile;
1285 		char *rdest;
1286 		int found = 0;
1287 		char interface_name[256];
1288 
1289 		DEBUGA_SKYPE("1 SESSION_REQUEST %s\n", SKYPOPEN_P_LOG, switch_core_session_get_uuid(*new_session));
1290 		switch_core_session_add_stream(*new_session, NULL);
1291 
1292 
1293 		if (!zstr(outbound_profile->destination_number)) {
1294 			int i;
1295 			char *slash;
1296 
1297 			switch_copy_string(interface_name, outbound_profile->destination_number, 255);
1298 			slash = strrchr(interface_name, '/');
1299 			if(slash != NULL){
1300 				*slash = '\0';
1301 			}
1302 
1303 			switch_mutex_lock(globals.mutex);
1304 			if (strncmp("ANY", interface_name, strlen(interface_name)) == 0 || strncmp("RR", interface_name, strlen(interface_name)) == 0) {
1305 				/* Find the first idle interface using Round Robin */
1306 				DEBUGA_SKYPE("Finding one available skype interface RR\n", SKYPOPEN_P_LOG);
1307 				tech_pvt = find_available_skypopen_interface_rr(NULL);
1308 				if (tech_pvt)
1309 					found = 1;
1310 			}
1311 
1312 			for (i = 0; !found && i < SKYPOPEN_MAX_INTERFACES; i++) {
1313 				/* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */
1314 				if (strlen(globals.SKYPOPEN_INTERFACES[i].name)
1315 					&& (strncmp(globals.SKYPOPEN_INTERFACES[i].name, interface_name, strlen(interface_name)) == 0)) {
1316 					if (strlen(globals.SKYPOPEN_INTERFACES[i].session_uuid_str)) {
1317 						DEBUGA_SKYPE
1318 							("globals.SKYPOPEN_INTERFACES[%d].name=|||%s||| session_uuid_str=|||%s||| is BUSY\n",
1319 							 SKYPOPEN_P_LOG, i, globals.SKYPOPEN_INTERFACES[i].name, globals.SKYPOPEN_INTERFACES[i].session_uuid_str);
1320 						DEBUGA_SKYPE("1 SESSION_DESTROY %s\n", SKYPOPEN_P_LOG, switch_core_session_get_uuid(*new_session));
1321 						switch_core_session_destroy(new_session);
1322 						switch_mutex_unlock(globals.mutex);
1323 						return SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
1324 					}
1325 
1326 					DEBUGA_SKYPE("globals.SKYPOPEN_INTERFACES[%d].name=|||%s|||?\n", SKYPOPEN_P_LOG, i, globals.SKYPOPEN_INTERFACES[i].name);
1327 					tech_pvt = &globals.SKYPOPEN_INTERFACES[i];
1328 					found = 1;
1329 					break;
1330 				}
1331 
1332 			}
1333 
1334 		} else {
1335 			ERRORA("Doh! no destination number?\n", SKYPOPEN_P_LOG);
1336 			switch_core_session_destroy(new_session);
1337 			return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1338 		}
1339 
1340 		if (!found) {
1341 			DEBUGA_SKYPE("Doh! no available interface for |||%s|||?\n", SKYPOPEN_P_LOG, interface_name);
1342 			DEBUGA_SKYPE("2 SESSION_DESTROY %s\n", SKYPOPEN_P_LOG, switch_core_session_get_uuid(*new_session));
1343 			switch_core_session_destroy(new_session);
1344 			switch_mutex_unlock(globals.mutex);
1345 			return SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
1346 		}
1347 
1348 		channel = switch_core_session_get_channel(*new_session);
1349 		if (!channel) {
1350 			ERRORA("Doh! no channel?\n", SKYPOPEN_P_LOG);
1351 			switch_core_session_destroy(new_session);
1352 			switch_mutex_unlock(globals.mutex);
1353 			return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1354 		}
1355 		switch_channel_set_variable(channel, "waste", "false");
1356 		if (skypopen_tech_init(tech_pvt, *new_session) != SWITCH_STATUS_SUCCESS) {
1357 			ERRORA("Doh! no tech_init?\n", SKYPOPEN_P_LOG);
1358 			switch_core_session_destroy(new_session);
1359 			switch_mutex_unlock(globals.mutex);
1360 			return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1361 		}
1362 
1363 
1364 		if (outbound_profile) {
1365 			char name[128];
1366 
1367 			if (strncmp("ANY", outbound_profile->destination_number, 3) == 0) {
1368 				snprintf(name, sizeof(name), "skypopen/%s%s", tech_pvt->name, outbound_profile->destination_number + 3);
1369 			} else if (strncmp("RR", outbound_profile->destination_number, 2) == 0) {
1370 				snprintf(name, sizeof(name), "skypopen/%s%s", tech_pvt->name, outbound_profile->destination_number + 2);
1371 			} else {
1372 				snprintf(name, sizeof(name), "skypopen/%s", outbound_profile->destination_number);
1373 			}
1374 
1375 			switch_channel_set_name(channel, name);
1376 			caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
1377 			switch_channel_set_caller_profile(channel, caller_profile);
1378 			tech_pvt->caller_profile = caller_profile;
1379 		} else {
1380 			ERRORA("Doh! no caller profile\n", SKYPOPEN_P_LOG);
1381 			switch_core_session_destroy(new_session);
1382 			switch_mutex_unlock(globals.mutex);
1383 			return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1384 		}
1385 
1386 
1387 		rdest = strchr(caller_profile->destination_number, '/');
1388 		*rdest++ = '\0';
1389 
1390 		switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(*new_session), sizeof(tech_pvt->session_uuid_str));
1391 		caller_profile = tech_pvt->caller_profile;
1392 		caller_profile->destination_number = rdest;
1393 
1394 		switch_mutex_lock(tech_pvt->flag_mutex);
1395 		tech_pvt->ob_calls++;
1396 		switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
1397 		switch_mutex_unlock(tech_pvt->flag_mutex);
1398 		switch_channel_set_state(channel, CS_INIT);
1399 		skypopen_call(tech_pvt, rdest, 30);
1400 		switch_mutex_unlock(globals.mutex);
1401 		return SWITCH_CAUSE_SUCCESS;
1402 	}
1403 
1404 	ERRORA("Doh! no new_session\n", SKYPOPEN_P_LOG);
1405 	return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1406 }
1407 
1408 /*!
1409  * \brief This thread runs during a call, and monitor the interface for signaling, like hangup, caller id, etc most of signaling is handled inside the skypopen_signaling_read function
1410  *
1411  */
skypopen_signaling_thread_func(switch_thread_t * thread,void * obj)1412 static void *SWITCH_THREAD_FUNC skypopen_signaling_thread_func(switch_thread_t *thread, void *obj)
1413 {
1414 	private_t *tech_pvt = obj;
1415 	int res;
1416 	int forever = 1;
1417 	switch_event_t *event;
1418 
1419 	if (!tech_pvt)
1420 		return NULL;
1421 
1422 	DEBUGA_SKYPE("In skypopen_signaling_thread_func: started, p=%p\n", SKYPOPEN_P_LOG, (void *) tech_pvt);
1423 
1424 	while (forever) {
1425 		if (!(running && tech_pvt->running))
1426 			break;
1427 		res = skypopen_signaling_read(tech_pvt);
1428 
1429 		if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_INCOMING_RAW) == SWITCH_STATUS_SUCCESS) {
1430 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "X-Skype-Response-Code", "%d", res);
1431 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "X-Skype-Interface", "%s", tech_pvt->interface_id);
1432 			switch_event_add_body(event, "%s", tech_pvt->message);
1433 			switch_event_fire(&event);
1434 		}
1435 
1436 		if (res == CALLFLOW_INCOMING_HANGUP || tech_pvt->skype_callflow == CALLFLOW_INCOMING_HANGUP) {
1437 			switch_core_session_t *session = NULL;
1438 			switch_channel_t *channel = NULL;
1439 			int conta;
1440 
1441 			DEBUGA_SKYPE("skype call ended\n", SKYPOPEN_P_LOG);
1442 
1443 			if (tech_pvt) {
1444 				if (tech_pvt->interface_state == SKYPOPEN_STATE_DEAD) {
1445 					break;
1446 				}
1447 				session = switch_core_session_locate(tech_pvt->session_uuid_str);
1448 				if (session) {
1449 					channel = switch_core_session_get_channel(session);
1450 					if (channel) {
1451 						switch_channel_state_t state = switch_channel_get_state(channel);
1452 						if (state < CS_EXECUTE) {
1453 							switch_sleep(20000);	//20 msec, let the state evolve from CS_NEW
1454 						}
1455 						switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
1456 					} else {
1457 						ERRORA("no channel?\n", SKYPOPEN_P_LOG);
1458 					}
1459 					switch_core_session_rwunlock(session);
1460 				} else {
1461 					DEBUGA_SKYPE("no session\n", SKYPOPEN_P_LOG);
1462 
1463 					tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
1464 					DEBUGA_SKYPE("audio tcp threads to DIE\n", SKYPOPEN_P_LOG);
1465 					conta = 0;
1466 					while (tech_pvt->tcp_srv_thread) {
1467 						switch_sleep(50000);
1468 						conta++;
1469 						if (conta == 20) {
1470 							ERRORA("tcp_srv_thread is NOT dead, this can LEAK MEMORY\n", SKYPOPEN_P_LOG);
1471 							break;
1472 						}
1473 					}
1474 					DEBUGA_SKYPE("audio tcp srv thread DEAD %d\n", SKYPOPEN_P_LOG, conta);
1475 					conta = 0;
1476 					while (tech_pvt->tcp_cli_thread) {
1477 						switch_sleep(50000);
1478 						conta++;
1479 						if (conta == 20) {
1480 							ERRORA("tcp_cli_thread is NOT dead, this can LEAK MEMORY\n", SKYPOPEN_P_LOG);
1481 							break;
1482 						}
1483 					}
1484 					DEBUGA_SKYPE("audio tcp cli thread DEAD %d\n", SKYPOPEN_P_LOG, conta);
1485 				}
1486 				switch_mutex_lock(globals.mutex);
1487 				tech_pvt->ringing_state = SKYPOPEN_RINGING_INIT;
1488 				*tech_pvt->session_uuid_str = '\0';
1489 				*tech_pvt->initial_skype_user = '\0';
1490 				*tech_pvt->answer_id = '\0';
1491 				*tech_pvt->answer_value = '\0';
1492 				*tech_pvt->ring_id = '\0';
1493 				*tech_pvt->ring_value = '\0';
1494 				*tech_pvt->callid_number = '\0';
1495 				*tech_pvt->callid_name = '\0';
1496 
1497 				tech_pvt->skype_callflow = CALLFLOW_CALL_IDLE;
1498 				tech_pvt->interface_state = SKYPOPEN_STATE_IDLE;
1499 				switch_mutex_unlock(globals.mutex);
1500 			} else {
1501 				ERRORA("no tech_pvt?\n", SKYPOPEN_P_LOG);
1502 			}
1503 		}
1504 	}
1505 	tech_pvt->skypopen_signaling_thread = NULL;
1506 	DEBUGA_SKYPE("EXITING\n", SKYPOPEN_P_LOG);
1507 	return NULL;
1508 }
1509 
load_config(int reload_type)1510 static switch_status_t load_config(int reload_type)
1511 {
1512 	char *cf = "skypopen.conf";
1513 	switch_xml_t cfg, xml, global_settings, param, interfaces, myinterface;
1514 	private_t *tech_pvt = NULL;
1515 
1516 	// CLOUDTREE (Thomas Hazel) - always try to load configuration
1517 	running = 1;
1518 
1519 	switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, skypopen_module_pool);
1520 	if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
1521 		ERRORA("open of %s failed\n", SKYPOPEN_P_LOG, cf);
1522 		running = 0;
1523 		switch_xml_free(xml);
1524 		return SWITCH_STATUS_TERM;
1525 	}
1526 
1527 	switch_mutex_lock(globals.mutex);
1528 	if ((global_settings = switch_xml_child(cfg, "global_settings"))) {
1529 		for (param = switch_xml_child(global_settings, "param"); param; param = param->next) {
1530 			char *var = (char *) switch_xml_attr_soft(param, "name");
1531 			char *val = (char *) switch_xml_attr_soft(param, "value");
1532 
1533 			if (!strcasecmp(var, "debug")) {
1534 				globals.debug = atoi(val);
1535 				DEBUGA_SKYPE("globals.debug=%d\n", SKYPOPEN_P_LOG, globals.debug);
1536 
1537 			} else if (!strcmp(var, "context")) {
1538 				set_global_context(val);
1539 				DEBUGA_SKYPE("globals.context=%s\n", SKYPOPEN_P_LOG, globals.context);
1540 			} else if (!strcmp(var, "dialplan")) {
1541 				set_global_dialplan(val);
1542 				DEBUGA_SKYPE("globals.dialplan=%s\n", SKYPOPEN_P_LOG, globals.dialplan);
1543 			} else if (!strcmp(var, "destination")) {
1544 				set_global_destination(val);
1545 				DEBUGA_SKYPE("globals.destination=%s\n", SKYPOPEN_P_LOG, globals.destination);
1546 			} else if (!strcmp(var, "skype_user")) {
1547 				set_global_skype_user(val);
1548 				DEBUGA_SKYPE("globals.skype_user=%s\n", SKYPOPEN_P_LOG, globals.skype_user);
1549 			} else if (!strcmp(var, "report_incoming_chatmessages")) {
1550 				set_global_report_incoming_chatmessages(val);
1551 				DEBUGA_SKYPE("globals.report_incoming_chatmessages=%s\n", SKYPOPEN_P_LOG, globals.report_incoming_chatmessages);
1552 			} else if (!strcmp(var, "silent_mode")) {
1553 				set_global_silent_mode(val);
1554 				DEBUGA_SKYPE("globals.silent_mode=%s\n", SKYPOPEN_P_LOG, globals.silent_mode);
1555 			} else if (!strcmp(var, "write_silence_when_idle")) {
1556 				set_global_write_silence_when_idle(val);
1557 				DEBUGA_SKYPE("globals.write_silence_when_idle=%s\n", SKYPOPEN_P_LOG, globals.write_silence_when_idle);
1558 			} else if (!strcmp(var, "setsockopt")) {
1559 				set_global_setsockopt(val);
1560 				DEBUGA_SKYPE("globals.setsockopt=%s\n", SKYPOPEN_P_LOG, globals.setsockopt);
1561 			}
1562 
1563 		}
1564 	}
1565 
1566 	globals.start_port = 32769;
1567 	if ((interfaces = switch_xml_child(cfg, "per_interface_settings"))) {
1568 		int i = 0;
1569 
1570 		for (myinterface = switch_xml_child(interfaces, "interface"); myinterface; myinterface = myinterface->next) {
1571 			char *id = (char *) switch_xml_attr(myinterface, "id");
1572 			char *name = (char *) switch_xml_attr(myinterface, "name");
1573 			char *context = "default";
1574 			char *dialplan = "XML";
1575 			char *destination = "5000";
1576 			char *X11_display = NULL;
1577 			char *skype_user = NULL;
1578 			char *report_incoming_chatmessages = "true";
1579 			char *silent_mode = "false";
1580 			char *write_silence_when_idle = "true";
1581 			char *setsockopt = "false";
1582 			uint32_t interface_id = 0;
1583 
1584 			if (globals.context)
1585 				context = globals.context;
1586 			if (globals.dialplan)
1587 				dialplan = globals.dialplan;
1588 			if (globals.destination)
1589 				destination = globals.destination;
1590 			if (globals.skype_user)
1591 				skype_user = globals.skype_user;
1592 			if (globals.report_incoming_chatmessages)
1593 				report_incoming_chatmessages = globals.report_incoming_chatmessages;
1594 			if (globals.silent_mode)
1595 				silent_mode = globals.silent_mode;
1596 			if (globals.write_silence_when_idle)
1597 				write_silence_when_idle = globals.write_silence_when_idle;
1598 			if (globals.setsockopt)
1599 				setsockopt = globals.setsockopt;
1600 
1601 			tech_pvt = NULL;
1602 
1603 			for (param = switch_xml_child(myinterface, "param"); param; param = param->next) {
1604 				char *var = (char *) switch_xml_attr_soft(param, "name");
1605 				char *val = (char *) switch_xml_attr_soft(param, "value");
1606 
1607 				if (!strcasecmp(var, "context")) {
1608 					context = val;
1609 				} else if (!strcasecmp(var, "dialplan")) {
1610 					dialplan = val;
1611 				} else if (!strcasecmp(var, "destination")) {
1612 					destination = val;
1613 				} else if (!strcasecmp(var, "skype_user")) {
1614 					skype_user = val;
1615 				} else if (!strcasecmp(var, "report_incoming_chatmessages")) {
1616 					report_incoming_chatmessages = val;
1617 				} else if (!strcasecmp(var, "silent_mode")) {
1618 					silent_mode = val;
1619 				} else if (!strcasecmp(var, "write_silence_when_idle")) {
1620 					write_silence_when_idle = val;
1621 				} else if (!strcasecmp(var, "setsockopt")) {
1622 					setsockopt = val;
1623 				} else if (!strcasecmp(var, "X11-display") || !strcasecmp(var, "X11_display")) {
1624 					X11_display = val;
1625 				}
1626 
1627 			}
1628 			if (!skype_user) {
1629 				ERRORA("interface missing REQUIRED param 'skype_user'\n", SKYPOPEN_P_LOG);
1630 				continue;
1631 			}
1632 
1633 			if (reload_type == SOFT_RELOAD) {
1634 				char the_interface[256];
1635 				sprintf(the_interface, "#%s", name);
1636 
1637 				if (interface_exists(the_interface) == SWITCH_STATUS_SUCCESS) {
1638 					continue;
1639 				}
1640 			}
1641 #ifndef WIN32
1642 			if (!X11_display) {
1643 				ERRORA("interface missing REQUIRED param 'X11_display'\n", SKYPOPEN_P_LOG);
1644 				continue;
1645 			}
1646 #endif
1647 			if (!id) {
1648 				ERRORA("interface missing REQUIRED param 'id'\n", SKYPOPEN_P_LOG);
1649 				continue;
1650 			}
1651 			if (switch_is_number(id)) {
1652 				interface_id = atoi(id);
1653 				DEBUGA_SKYPE("interface_id=%d\n", SKYPOPEN_P_LOG, interface_id);
1654 			} else {
1655 				ERRORA("interface param 'id' MUST be a number, now id='%s'\n", SKYPOPEN_P_LOG, id);
1656 				continue;
1657 			}
1658 
1659 			if (!name) {
1660 				WARNINGA("interface missing param 'name', not nice, but works\n", SKYPOPEN_P_LOG);
1661 			}
1662 
1663 			if (name) {
1664 				DEBUGA_SKYPE("name=%s\n", SKYPOPEN_P_LOG, name);
1665 			}
1666 #ifndef WIN32
1667 			if (!XInitThreads()) {
1668 				ERRORA("Not initialized XInitThreads!\n", SKYPOPEN_P_LOG);
1669 			} else {
1670 				DEBUGA_SKYPE("Initialized XInitThreads!\n", SKYPOPEN_P_LOG);
1671 			}
1672 			switch_sleep(20000);
1673 #endif /* WIN32 */
1674 
1675 			if (interface_id && interface_id < SKYPOPEN_MAX_INTERFACES) {
1676 				private_t newconf;
1677 				switch_threadattr_t *skypopen_api_thread_attr = NULL;
1678 				switch_threadattr_t *skypopen_signaling_thread_attr = NULL;
1679 
1680 				memset(&newconf, '\0', sizeof(newconf));
1681 				globals.SKYPOPEN_INTERFACES[interface_id] = newconf;
1682 				globals.SKYPOPEN_INTERFACES[interface_id].running = 1;
1683 
1684 
1685 				tech_pvt = &globals.SKYPOPEN_INTERFACES[interface_id];
1686 
1687 				switch_set_string(globals.SKYPOPEN_INTERFACES[interface_id].interface_id, id);
1688 				if (name) {
1689 					switch_set_string(globals.SKYPOPEN_INTERFACES[interface_id].name, name);
1690 				} else {
1691 					switch_set_string(globals.SKYPOPEN_INTERFACES[interface_id].name, "N/A");
1692 				}
1693 				DEBUGA_SKYPE("CONFIGURING interface_id=%d\n", SKYPOPEN_P_LOG, interface_id);
1694 
1695 				switch_set_string(globals.SKYPOPEN_INTERFACES[interface_id].context, context);
1696 				switch_set_string(globals.SKYPOPEN_INTERFACES[interface_id].dialplan, dialplan);
1697 				switch_set_string(globals.SKYPOPEN_INTERFACES[interface_id].destination, destination);
1698 				switch_set_string(globals.SKYPOPEN_INTERFACES[interface_id].X11_display, X11_display);
1699 				switch_set_string(globals.SKYPOPEN_INTERFACES[interface_id].skype_user, skype_user);
1700 
1701 				if (!strcmp(report_incoming_chatmessages, "true") || !strcmp(report_incoming_chatmessages, "1")) {
1702 					globals.SKYPOPEN_INTERFACES[interface_id].report_incoming_chatmessages = 1;
1703 				} else {
1704 					globals.SKYPOPEN_INTERFACES[interface_id].report_incoming_chatmessages = 0;	//redundant, just in case
1705 
1706 				}
1707 
1708 				if (!strcmp(silent_mode, "true") || !strcmp(silent_mode, "1")) {
1709 					globals.SKYPOPEN_INTERFACES[interface_id].silent_mode = 1;
1710 				} else {
1711 					globals.SKYPOPEN_INTERFACES[interface_id].silent_mode = 0;	//redundant, just in case
1712 
1713 				}
1714 
1715 				if (!strcmp(write_silence_when_idle, "true") || !strcmp(write_silence_when_idle, "1")) {
1716 					globals.SKYPOPEN_INTERFACES[interface_id].write_silence_when_idle = 1;
1717 				} else {
1718 					globals.SKYPOPEN_INTERFACES[interface_id].write_silence_when_idle = 0;	//redundant, just in case
1719 
1720 				}
1721 
1722 				if (!strcmp(setsockopt, "true") || !strcmp(setsockopt, "1")) {
1723 					globals.SKYPOPEN_INTERFACES[interface_id].setsockopt = 1;
1724 				} else {
1725 					globals.SKYPOPEN_INTERFACES[interface_id].setsockopt = 0;	//redundant, just in case
1726 
1727 				}
1728 
1729 				DEBUGA_SKYPE("interface_id=%d globals.SKYPOPEN_INTERFACES[interface_id].name=%s\n",
1730 							 SKYPOPEN_P_LOG, interface_id, globals.SKYPOPEN_INTERFACES[interface_id].name);
1731 				DEBUGA_SKYPE
1732 					("interface_id=%d globals.SKYPOPEN_INTERFACES[interface_id].context=%s\n",
1733 					 SKYPOPEN_P_LOG, interface_id, globals.SKYPOPEN_INTERFACES[interface_id].context);
1734 				DEBUGA_SKYPE
1735 					("interface_id=%d globals.SKYPOPEN_INTERFACES[interface_id].dialplan=%s\n",
1736 					 SKYPOPEN_P_LOG, interface_id, globals.SKYPOPEN_INTERFACES[interface_id].dialplan);
1737 				DEBUGA_SKYPE
1738 					("interface_id=%d globals.SKYPOPEN_INTERFACES[interface_id].destination=%s\n",
1739 					 SKYPOPEN_P_LOG, interface_id, globals.SKYPOPEN_INTERFACES[interface_id].destination);
1740 				DEBUGA_SKYPE
1741 					("interface_id=%d globals.SKYPOPEN_INTERFACES[interface_id].X11_display=%s\n",
1742 					 SKYPOPEN_P_LOG, interface_id, globals.SKYPOPEN_INTERFACES[interface_id].X11_display);
1743 				DEBUGA_SKYPE
1744 					("interface_id=%d globals.SKYPOPEN_INTERFACES[interface_id].skype_user=%s\n",
1745 					 SKYPOPEN_P_LOG, interface_id, globals.SKYPOPEN_INTERFACES[interface_id].skype_user);
1746 				DEBUGA_SKYPE
1747 					("interface_id=%d globals.SKYPOPEN_INTERFACES[interface_id].report_incoming_chatmessages=%d\n",
1748 					 SKYPOPEN_P_LOG, interface_id, globals.SKYPOPEN_INTERFACES[interface_id].report_incoming_chatmessages);
1749 				DEBUGA_SKYPE
1750 					("interface_id=%d globals.SKYPOPEN_INTERFACES[interface_id].silent_mode=%d\n",
1751 					 SKYPOPEN_P_LOG, interface_id, globals.SKYPOPEN_INTERFACES[interface_id].silent_mode);
1752 				DEBUGA_SKYPE
1753 					("interface_id=%d globals.SKYPOPEN_INTERFACES[interface_id].write_silence_when_idle=%d\n",
1754 					 SKYPOPEN_P_LOG, interface_id, globals.SKYPOPEN_INTERFACES[interface_id].write_silence_when_idle);
1755 				DEBUGA_SKYPE
1756 					("interface_id=%d globals.SKYPOPEN_INTERFACES[interface_id].setsockopt=%d\n",
1757 					 SKYPOPEN_P_LOG, interface_id, globals.SKYPOPEN_INTERFACES[interface_id].setsockopt);
1758 
1759 				WARNINGA("STARTING interface_id=%d\n", SKYPOPEN_P_LOG, interface_id);
1760 
1761 				switch_threadattr_create(&skypopen_api_thread_attr, skypopen_module_pool);
1762 				switch_threadattr_detach_set(skypopen_api_thread_attr, 0);
1763 				switch_threadattr_stacksize_set(skypopen_api_thread_attr, SWITCH_THREAD_STACKSIZE);
1764 
1765 				switch_thread_create(&globals.SKYPOPEN_INTERFACES[interface_id].skypopen_api_thread,
1766 									 skypopen_api_thread_attr, skypopen_do_skypeapi_thread, &globals.SKYPOPEN_INTERFACES[interface_id],
1767 									 skypopen_module_pool);
1768 
1769 				switch_sleep(100000);
1770 
1771 				switch_threadattr_create(&skypopen_signaling_thread_attr, skypopen_module_pool);
1772 				switch_threadattr_detach_set(skypopen_signaling_thread_attr, 0);
1773 				switch_threadattr_stacksize_set(skypopen_signaling_thread_attr, SWITCH_THREAD_STACKSIZE);
1774 
1775 				switch_thread_create(&globals.SKYPOPEN_INTERFACES[interface_id].skypopen_signaling_thread, skypopen_signaling_thread_attr,
1776 									 skypopen_signaling_thread_func, &globals.SKYPOPEN_INTERFACES[interface_id], skypopen_module_pool);
1777 
1778 				switch_sleep(100000);
1779 
1780 				skypopen_audio_init(&globals.SKYPOPEN_INTERFACES[interface_id]);
1781 				switch_mutex_init(&globals.SKYPOPEN_INTERFACES[interface_id].mutex_audio_srv, SWITCH_MUTEX_NESTED, skypopen_module_pool);
1782 				switch_mutex_init(&globals.SKYPOPEN_INTERFACES[interface_id].mutex_audio_cli, SWITCH_MUTEX_NESTED, skypopen_module_pool);
1783 				switch_mutex_init(&globals.SKYPOPEN_INTERFACES[interface_id].mutex_thread_audio_srv, SWITCH_MUTEX_NESTED, skypopen_module_pool);
1784 				switch_mutex_init(&globals.SKYPOPEN_INTERFACES[interface_id].mutex_thread_audio_cli, SWITCH_MUTEX_NESTED, skypopen_module_pool);
1785 
1786 				NOTICA
1787 					("WAITING roughly 10 seconds to find a running Skype client and connect to its SKYPE API for interface_id=%d\n",
1788 					 SKYPOPEN_P_LOG, interface_id);
1789 				i = 0;
1790 				while (globals.SKYPOPEN_INTERFACES[interface_id].SkypopenHandles.api_connected == 0 && running && i < 200) {	// 10 seconds! thanks Jeff Lenk
1791 					switch_sleep(50000);
1792 					i++;
1793 				}
1794 				if (globals.SKYPOPEN_INTERFACES[interface_id].SkypopenHandles.api_connected) {
1795 					NOTICA
1796 						("Found a running Skype client, connected to its SKYPE API for interface_id=%d, waiting 60 seconds for CURRENTUSERHANDLE==%s\n",
1797 						 SKYPOPEN_P_LOG, interface_id, globals.SKYPOPEN_INTERFACES[interface_id].skype_user);
1798 				} else {
1799 					ERRORA
1800 						("Failed to connect to a SKYPE API for interface_id=%d, no SKYPE client running, please (re)start Skype client. Skypopen exiting\n",
1801 						 SKYPOPEN_P_LOG, interface_id);
1802 					running = 0;
1803 					switch_mutex_unlock(globals.mutex);
1804 					switch_xml_free(xml);
1805 					return SWITCH_STATUS_FALSE;
1806 				}
1807 
1808 				i = 0;
1809 				while (globals.SKYPOPEN_INTERFACES[interface_id].SkypopenHandles.currentuserhandle == 0 && running && i < 1200) {	// 60 seconds! thanks Jeff Lenk
1810 					switch_sleep(50000);
1811 					i++;
1812 				}
1813 				if (globals.SKYPOPEN_INTERFACES[interface_id].SkypopenHandles.currentuserhandle) {
1814 					WARNINGA
1815 						("Interface_id=%d is now STARTED, the Skype client to which we are connected gave us the correct CURRENTUSERHANDLE (%s)\n",
1816 						 SKYPOPEN_P_LOG, interface_id, globals.SKYPOPEN_INTERFACES[interface_id].skype_user);
1817 
1818 					skypopen_signaling_write(&globals.SKYPOPEN_INTERFACES[interface_id], "PROTOCOL 999");
1819 					switch_sleep(20000);
1820 					skypopen_signaling_write(&globals.SKYPOPEN_INTERFACES[interface_id], "SET AUTOAWAY OFF");
1821 					switch_sleep(20000);
1822 					skypopen_signaling_write(&globals.SKYPOPEN_INTERFACES[interface_id], "SET WINDOWSTATE HIDDEN");
1823 					switch_sleep(20000);
1824 					skypopen_signaling_write(&globals.SKYPOPEN_INTERFACES[interface_id], "SET USERSTATUS ONLINE");
1825 					switch_sleep(20000);
1826 					if (globals.SKYPOPEN_INTERFACES[interface_id].silent_mode) {
1827 						skypopen_signaling_write(&globals.SKYPOPEN_INTERFACES[interface_id], "SET SILENT_MODE ON");
1828 						switch_sleep(20000);
1829 						skypopen_signaling_write(&globals.SKYPOPEN_INTERFACES[interface_id], "SET SILENT_MODE OFF");
1830 						switch_sleep(20000);
1831 						skypopen_signaling_write(&globals.SKYPOPEN_INTERFACES[interface_id], "SET SILENT_MODE ON");
1832 						switch_sleep(20000);
1833 					}
1834 				} else {
1835 					ERRORA
1836 						("The Skype client to which we are connected FAILED to gave us CURRENTUSERHANDLE=%s, interface_id=%d FAILED to start. No Skype client logged in as '%s' has been found. Please (re)launch a Skype client logged in as '%s'. Skypopen exiting now\n",
1837 						 SKYPOPEN_P_LOG, globals.SKYPOPEN_INTERFACES[interface_id].skype_user,
1838 						 interface_id, globals.SKYPOPEN_INTERFACES[interface_id].skype_user, globals.SKYPOPEN_INTERFACES[interface_id].skype_user);
1839 					running = 0;
1840 					switch_mutex_unlock(globals.mutex);
1841 					switch_xml_free(xml);
1842 					return SWITCH_STATUS_FALSE;
1843 				}
1844 
1845 			} else {
1846 				ERRORA("interface id %d is higher than SKYPOPEN_MAX_INTERFACES (%d)\n", SKYPOPEN_P_LOG, interface_id, SKYPOPEN_MAX_INTERFACES);
1847 				continue;
1848 			}
1849 
1850 		}
1851 
1852 		for (i = 0; i < SKYPOPEN_MAX_INTERFACES; i++) {
1853 			if (strlen(globals.SKYPOPEN_INTERFACES[i].name)) {
1854 				/* How many real intterfaces */
1855 				globals.real_interfaces = i + 1;
1856 
1857 				tech_pvt = &globals.SKYPOPEN_INTERFACES[i];
1858 
1859 				DEBUGA_SKYPE("i=%d globals.SKYPOPEN_INTERFACES[%d].interface_id=%s\n", SKYPOPEN_P_LOG, i, i, globals.SKYPOPEN_INTERFACES[i].interface_id);
1860 				DEBUGA_SKYPE("i=%d globals.SKYPOPEN_INTERFACES[%d].name=%s\n", SKYPOPEN_P_LOG, i, i, globals.SKYPOPEN_INTERFACES[i].name);
1861 				DEBUGA_SKYPE("i=%d globals.SKYPOPEN_INTERFACES[%d].context=%s\n", SKYPOPEN_P_LOG, i, i, globals.SKYPOPEN_INTERFACES[i].context);
1862 				DEBUGA_SKYPE("i=%d globals.SKYPOPEN_INTERFACES[%d].dialplan=%s\n", SKYPOPEN_P_LOG, i, i, globals.SKYPOPEN_INTERFACES[i].dialplan);
1863 				DEBUGA_SKYPE("i=%d globals.SKYPOPEN_INTERFACES[%d].destination=%s\n", SKYPOPEN_P_LOG, i, i, globals.SKYPOPEN_INTERFACES[i].destination);
1864 				DEBUGA_SKYPE("i=%d globals.SKYPOPEN_INTERFACES[%d].X11_display=%s\n", SKYPOPEN_P_LOG, i, i, globals.SKYPOPEN_INTERFACES[i].X11_display);
1865 				DEBUGA_SKYPE("i=%d globals.SKYPOPEN_INTERFACES[%d].skype_user=%s\n", SKYPOPEN_P_LOG, i, i, globals.SKYPOPEN_INTERFACES[i].skype_user);
1866 				DEBUGA_SKYPE("i=%d globals.SKYPOPEN_INTERFACES[%d].report_incoming_chatmessages=%d\n", SKYPOPEN_P_LOG, i, i,
1867 							 globals.SKYPOPEN_INTERFACES[i].report_incoming_chatmessages);
1868 				DEBUGA_SKYPE("i=%d globals.SKYPOPEN_INTERFACES[%d].silent_mode=%d\n", SKYPOPEN_P_LOG, i, i, globals.SKYPOPEN_INTERFACES[i].silent_mode);
1869 				DEBUGA_SKYPE("i=%d globals.SKYPOPEN_INTERFACES[%d].write_silence_when_idle=%d\n", SKYPOPEN_P_LOG, i, i,
1870 							 globals.SKYPOPEN_INTERFACES[i].write_silence_when_idle);
1871 				DEBUGA_SKYPE("i=%d globals.SKYPOPEN_INTERFACES[%d].setsockopt=%d\n", SKYPOPEN_P_LOG, i, i, globals.SKYPOPEN_INTERFACES[i].setsockopt);
1872 			}
1873 		}
1874 	}
1875 
1876 	switch_mutex_unlock(globals.mutex);
1877 	switch_xml_free(xml);
1878 
1879 	return SWITCH_STATUS_SUCCESS;
1880 }
1881 
chat_send(switch_event_t * message_event)1882 static switch_status_t chat_send(switch_event_t *message_event)
1883 {
1884 	char *user = NULL, *host, *f_user = NULL, *f_host = NULL, *f_resource = NULL;
1885 	private_t *tech_pvt = NULL;
1886 	int i = 0, found = 0, tried = 0;
1887 	char skype_msg[1024];
1888 
1889 	const char *proto;
1890 	const char *from;
1891 	const char *to;
1892 	const char *subject;
1893 	const char *body;
1894 	//const char *type;
1895 	const char *hint;
1896 
1897 	proto = switch_event_get_header(message_event, "proto");
1898 	from = switch_event_get_header(message_event, "from");
1899 	to = switch_event_get_header(message_event, "to");
1900 	subject = switch_event_get_header(message_event, "subject");
1901 	body = switch_event_get_body(message_event);
1902 	//type = switch_event_get_header(message_event, "type");
1903 	hint = switch_event_get_header(message_event, "hint");
1904 
1905 	switch_assert(proto != NULL);
1906 
1907 	//DEBUGA_SKYPE("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=%s, hint=%s)\n", SKYPOPEN_P_LOG, proto, from, to, subject, body, type,
1908 	//           hint ? hint : "NULL");
1909 	DEBUGA_SKYPE("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, hint=%s)\n", SKYPOPEN_P_LOG, proto, from, to, subject, body,
1910 				 hint ? hint : "NULL");
1911 
1912 	if (!to || !strlen(to)) {
1913 		ERRORA("Missing To: header.\n", SKYPOPEN_P_LOG);
1914 		return SWITCH_STATUS_SUCCESS;
1915 	}
1916 
1917 	if ((!from && !hint) || (!strlen(from) && !strlen(hint))) {
1918 		ERRORA("Missing From: AND Hint: headers.\n", SKYPOPEN_P_LOG);
1919 		return SWITCH_STATUS_SUCCESS;
1920 	}
1921 
1922 	if (from && (f_user = strdup(from))) {
1923 		if ((f_host = strchr(f_user, '@'))) {
1924 			*f_host++ = '\0';
1925 			if ((f_resource = strchr(f_host, '/'))) {
1926 				*f_resource++ = '\0';
1927 			}
1928 		}
1929 	}
1930 
1931 	if (to && (user = strdup(to))) {
1932 		if ((host = strchr(user, '@'))) {
1933 			*host++ = '\0';
1934 		}
1935 		//DEBUGA_SKYPE("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=%s, hint=%s)\n", SKYPOPEN_P_LOG, proto, from, to, subject, body, type,
1936 		//           hint ? hint : "NULL");
1937 		DEBUGA_SKYPE("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, hint=%s)\n", SKYPOPEN_P_LOG, proto, from, to, subject, body,
1938 					 hint ? hint : "NULL");
1939 		if (hint && strlen(hint)) {
1940 			//in hint we receive the interface name to use
1941 			for (i = 0; !found && i < SKYPOPEN_MAX_INTERFACES; i++) {
1942 				if (strlen(globals.SKYPOPEN_INTERFACES[i].name)
1943 					&& (strncmp(globals.SKYPOPEN_INTERFACES[i].name, hint, strlen(hint)) == 0)) {
1944 					tech_pvt = &globals.SKYPOPEN_INTERFACES[i];
1945 					DEBUGA_SKYPE("Using interface: globals.SKYPOPEN_INTERFACES[%d].name=|||%s|||\n", SKYPOPEN_P_LOG, i,
1946 								 globals.SKYPOPEN_INTERFACES[i].name);
1947 					found = 1;
1948 					break;
1949 				}
1950 			}
1951 		} else {
1952 			//we have no a predefined interface name to use (hint is NULL), so let's choose an interface from the username (from)
1953 			for (i = 0; !found && i < SKYPOPEN_MAX_INTERFACES; i++) {
1954 				if (strlen(globals.SKYPOPEN_INTERFACES[i].name)
1955 					&& (strncmp(globals.SKYPOPEN_INTERFACES[i].skype_user, from, strlen(from)) == 0)) {
1956 					tech_pvt = &globals.SKYPOPEN_INTERFACES[i];
1957 					DEBUGA_SKYPE("Using interface: globals.SKYPOPEN_INTERFACES[%d].name=|||%s|||\n", SKYPOPEN_P_LOG, i,
1958 								 globals.SKYPOPEN_INTERFACES[i].name);
1959 					found = 1;
1960 					break;
1961 				}
1962 			}
1963 		}
1964 		if (!found) {
1965 			ERRORA("ERROR: A Skypopen interface with name='%s' or one with skypeuser='%s' was not found\n", SKYPOPEN_P_LOG, hint ? hint : "NULL",
1966 				   from ? from : "NULL");
1967 			goto end;
1968 		} else {
1969 
1970 			snprintf(skype_msg, sizeof(skype_msg), "CHAT CREATE %s", to);
1971 			skypopen_signaling_write(tech_pvt, skype_msg);
1972 			switch_sleep(20000);
1973 		}
1974 
1975 		found = 0;
1976 
1977 		while (!found) {
1978 			for (i = 0; i < MAX_CHATS; i++) {
1979 				//DEBUGA_SKYPE("tech_pvt->chats[i].dialog_partner='%s' to='%s'\n", SKYPOPEN_P_LOG, tech_pvt->chats[i].dialog_partner, to);
1980 				if (!strcmp(tech_pvt->chats[i].dialog_partner, to)) {
1981 					snprintf(skype_msg, sizeof(skype_msg), "CHATMESSAGE %s %s", tech_pvt->chats[i].chatname, body);
1982 					skypopen_signaling_write(tech_pvt, skype_msg);
1983 					found = 1;
1984 					break;
1985 				}
1986 			}
1987 			if (found) {
1988 				break;
1989 			}
1990 			tried++;
1991 			if (tried > 20) {
1992 				ERRORA
1993 					("No chat with dialog_partner='%s' was found. (If you're using mod_sms this is a bug of mod_skypopen when using mod_sms, from next incoming message it will probably work...)\n",
1994 					 SKYPOPEN_P_LOG, to);
1995 				break;
1996 			}
1997 			switch_sleep(50000);
1998 		}
1999 
2000 	}
2001   end:
2002 	switch_safe_free(user);
2003 	switch_safe_free(f_user);
2004 	return SWITCH_STATUS_SUCCESS;
2005 }
2006 
2007 
SWITCH_MODULE_LOAD_FUNCTION(mod_skypopen_load)2008 SWITCH_MODULE_LOAD_FUNCTION(mod_skypopen_load)
2009 {
2010 	switch_api_interface_t *commands_api_interface;
2011 	switch_chat_interface_t *chat_interface;
2012 
2013 	skypopen_module_pool = pool;
2014 	memset(&globals, '\0', sizeof(globals));
2015 
2016 	// CLOUDTREE (Thomas Hazel)
2017 #ifndef WIN32
2018 	// XXX: these assumes no one will override
2019 	//XSetErrorHandler(X11_errors_handler);
2020 	//XXX giovanni: seems that if Xserver is up, but skype client is crashed, the error is non fatal. Let's use Thomas handler in this case too
2021 	XSetErrorHandler(xio_error_handler2);
2022 	XSetIOErrorHandler(xio_error_handler);
2023 
2024 	memset(&global_handles_list, 0, sizeof(global_handles_list));
2025 	switch_mutex_init(&globals.list_mutex, SWITCH_MUTEX_NESTED, skypopen_module_pool);
2026 #endif
2027 
2028 	running = 1;
2029 
2030 	if (load_config(FULL_RELOAD) == SWITCH_STATUS_SUCCESS) {
2031 
2032 		*module_interface = switch_loadable_module_create_module_interface(pool, modname);
2033 		skypopen_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
2034 		skypopen_endpoint_interface->interface_name = "skypopen";
2035 		skypopen_endpoint_interface->io_routines = &skypopen_io_routines;
2036 		skypopen_endpoint_interface->state_handler = &skypopen_state_handlers;
2037 
2038 		if (running) {
2039 
2040 			SWITCH_ADD_API(commands_api_interface, "sk", "Skypopen console commands", sk_function, SK_SYNTAX);
2041 			SWITCH_ADD_API(commands_api_interface, "skypopen", "Skypopen interface commands", skypopen_function, SKYPOPEN_SYNTAX);
2042 			SWITCH_ADD_API(commands_api_interface, "skypopen_chat", "Skypopen_chat interface remote_skypename TEXT", skypopen_chat_function,
2043 					SKYPOPEN_CHAT_SYNTAX);
2044 			SWITCH_ADD_CHAT(chat_interface, SKYPE_CHAT_PROTO, chat_send);
2045 
2046 			if (switch_event_reserve_subclass(MY_EVENT_INCOMING_CHATMESSAGE) != SWITCH_STATUS_SUCCESS) {
2047 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n");
2048 				return SWITCH_STATUS_FALSE;
2049 			}
2050 
2051 			if (switch_event_reserve_subclass(MY_EVENT_INCOMING_RAW) != SWITCH_STATUS_SUCCESS) {
2052 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n");
2053 				return SWITCH_STATUS_FALSE;
2054 			}
2055 
2056 			/* indicate that the module should continue to be loaded */
2057 			return SWITCH_STATUS_SUCCESS;
2058 		}
2059 	} else {
2060 		running = 0;
2061 		switch_sleep(1000000); //1 full second
2062 		return SWITCH_STATUS_FALSE;
2063 	}
2064 	return SWITCH_STATUS_FALSE;
2065 }
2066 
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypopen_shutdown)2067 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypopen_shutdown)
2068 {
2069 	int x;
2070 	private_t *tech_pvt = NULL;
2071 	switch_status_t status = SWITCH_STATUS_SUCCESS;
2072 	switch_size_t howmany = 8;
2073 	int interface_id;
2074 
2075 	running = 0;
2076 
2077 	for (interface_id = 0; interface_id < SKYPOPEN_MAX_INTERFACES; interface_id++) {
2078 		tech_pvt = &globals.SKYPOPEN_INTERFACES[interface_id];
2079 
2080 
2081 		if (strlen(globals.SKYPOPEN_INTERFACES[interface_id].name)) {
2082 			if (globals.SKYPOPEN_INTERFACES[interface_id].skypopen_signaling_thread) {
2083 #ifdef WIN32
2084 				skypopen_signaling_write(tech_pvt, "DIE");
2085 				switch_sleep(20000);
2086 				switch_file_write(tech_pvt->SkypopenHandles.fdesc[1], "sciutati", &howmany);	// let's the controldev_thread die
2087 
2088 #else /* WIN32 */
2089 				skypopen_signaling_write(tech_pvt, "DIE");
2090 				switch_sleep(20000);
2091 				howmany = write(tech_pvt->SkypopenHandles.fdesc[1], "sciutati", howmany);
2092 #endif /* WIN32 */
2093 			}
2094 
2095 			if (globals.SKYPOPEN_INTERFACES[interface_id].skypopen_api_thread) {
2096 #ifdef WIN32
2097 				if (SendMessage(tech_pvt->SkypopenHandles.win32_hInit_MainWindowHandle, WM_DESTROY, 0, 0) == FALSE) {	// let's the skypopen_api_thread_func die
2098 					DEBUGA_SKYPE("got FALSE here, thread probably was already dead. GetLastError returned: %d\n", SKYPOPEN_P_LOG, GetLastError());
2099 					tech_pvt->skypopen_api_thread = NULL;
2100 				}
2101 #else
2102 				if (tech_pvt->SkypopenHandles.disp) {
2103 					XEvent e;
2104 					Atom atom1 = XInternAtom(tech_pvt->SkypopenHandles.disp, "SKYPECONTROLAPI_MESSAGE_BEGIN",
2105 											 False);
2106 					switch_sleep(20000);
2107 					XFlush(tech_pvt->SkypopenHandles.disp);
2108 					memset(&e, 0, sizeof(e));
2109 					e.xclient.type = ClientMessage;
2110 					e.xclient.message_type = atom1;	/*  leading message */
2111 					e.xclient.display = tech_pvt->SkypopenHandles.disp;
2112 					e.xclient.window = tech_pvt->SkypopenHandles.skype_win;
2113 					e.xclient.format = 8;
2114 
2115 					XSendEvent(tech_pvt->SkypopenHandles.disp, tech_pvt->SkypopenHandles.win, False, 0, &e);
2116 					XFlush(tech_pvt->SkypopenHandles.disp);
2117 				}
2118 #endif
2119 			}
2120 			x = 10;
2121 			while (x) {
2122 				x--;
2123 				switch_yield(50000);
2124 			}
2125 #ifndef WIN32
2126 			if (tech_pvt->SkypopenHandles.disp) {
2127 				DEBUGA_SKYPE("CLOSIN X\n", SKYPOPEN_P_LOG);
2128 				XCloseDisplay(tech_pvt->SkypopenHandles.disp);
2129 				DEBUGA_SKYPE("CLOSIN X END\n", SKYPOPEN_P_LOG);
2130 			}
2131 #endif
2132 			if (globals.SKYPOPEN_INTERFACES[interface_id].skypopen_signaling_thread) {
2133 				switch_thread_join(&status, globals.SKYPOPEN_INTERFACES[interface_id].skypopen_signaling_thread);
2134 			}
2135 			if (status != SWITCH_STATUS_SUCCESS)
2136 				DEBUGA_SKYPE("got FALSE here, thread was not joined\n", SKYPOPEN_P_LOG);
2137 			if (globals.SKYPOPEN_INTERFACES[interface_id].skypopen_api_thread) {
2138 				switch_thread_join(&status, globals.SKYPOPEN_INTERFACES[interface_id].skypopen_api_thread);
2139 			}
2140 			if (status != SWITCH_STATUS_SUCCESS)
2141 				DEBUGA_SKYPE("got FALSE here, thread was not joined\n", SKYPOPEN_P_LOG);
2142 #ifndef WIN32
2143 			WARNINGA("SHUTDOWN interface_id=%d\n", SKYPOPEN_P_LOG, interface_id);
2144 			shutdown(tech_pvt->audiopipe_cli[0], 2);
2145 			close(tech_pvt->audiopipe_cli[0]);
2146 			shutdown(tech_pvt->audiopipe_cli[1], 2);
2147 			close(tech_pvt->audiopipe_cli[1]);
2148 			shutdown(tech_pvt->audiopipe_srv[0], 2);
2149 			close(tech_pvt->audiopipe_srv[0]);
2150 			shutdown(tech_pvt->audiopipe_srv[1], 2);
2151 			close(tech_pvt->audiopipe_srv[1]);
2152 			shutdown(tech_pvt->SkypopenHandles.fdesc[0], 2);
2153 			close(tech_pvt->SkypopenHandles.fdesc[0]);
2154 			shutdown(tech_pvt->SkypopenHandles.fdesc[1], 2);
2155 			close(tech_pvt->SkypopenHandles.fdesc[1]);
2156 #endif /* WIN32 */
2157 		}
2158 
2159 	}
2160 	switch_event_free_subclass(MY_EVENT_INCOMING_CHATMESSAGE);
2161 	switch_event_free_subclass(MY_EVENT_INCOMING_RAW);
2162 
2163 	switch_safe_free(globals.context);
2164 	switch_safe_free(globals.dialplan);
2165 	switch_safe_free(globals.destination);
2166 	switch_safe_free(globals.skype_user);
2167 	switch_safe_free(globals.report_incoming_chatmessages);
2168 	switch_safe_free(globals.silent_mode);
2169 	switch_safe_free(globals.write_silence_when_idle);
2170 	switch_safe_free(globals.setsockopt);
2171 
2172 	return SWITCH_STATUS_SUCCESS;
2173 }
2174 
skypopen_do_tcp_srv_thread(switch_thread_t * thread,void * obj)2175 void *SWITCH_THREAD_FUNC skypopen_do_tcp_srv_thread(switch_thread_t *thread, void *obj)
2176 {
2177 	return skypopen_do_tcp_srv_thread_func(obj);
2178 }
2179 
skypopen_do_tcp_cli_thread(switch_thread_t * thread,void * obj)2180 void *SWITCH_THREAD_FUNC skypopen_do_tcp_cli_thread(switch_thread_t *thread, void *obj)
2181 {
2182 	return skypopen_do_tcp_cli_thread_func(obj);
2183 }
2184 
skypopen_do_skypeapi_thread(switch_thread_t * thread,void * obj)2185 void *SWITCH_THREAD_FUNC skypopen_do_skypeapi_thread(switch_thread_t *thread, void *obj)
2186 {
2187 	return skypopen_do_skypeapi_thread_func(obj);
2188 }
2189 
dtmf_received(private_t * tech_pvt,char * value)2190 int dtmf_received(private_t *tech_pvt, char *value)
2191 {
2192 	switch_core_session_t *session = NULL;
2193 	switch_channel_t *channel = NULL;
2194 
2195 	session = switch_core_session_locate(tech_pvt->session_uuid_str);
2196 	if (session) {
2197 		channel = switch_core_session_get_channel(session);
2198 
2199 		if (channel) {
2200 
2201 			if (switch_channel_test_flag(channel, CF_BRIDGED)
2202 				&& !switch_true(switch_channel_get_variable(channel, "skype_add_outband_dtmf_also_when_bridged"))) {
2203 
2204 
2205 				NOTICA
2206 					("received DTMF '%c' on channel %s, but we're BRIDGED, so we DO NOT relay it out of band. If you DO want to relay it out of band when bridged too, on top of audio DTMF, set the channel variable 'skype_add_outband_dtmf_also_when_bridged=true' \n",
2207 					 SKYPOPEN_P_LOG, value[0], switch_channel_get_name(channel));
2208 
2209 			} else {
2210 
2211 
2212 
2213 				switch_dtmf_t dtmf = { (char) value[0], switch_core_default_dtmf_duration(0) };
2214 				DEBUGA_SKYPE("received DTMF %c on channel %s\n", SKYPOPEN_P_LOG, dtmf.digit, switch_channel_get_name(channel));
2215 				switch_mutex_lock(tech_pvt->flag_mutex);
2216 				switch_channel_queue_dtmf(channel, &dtmf);
2217 				switch_set_flag(tech_pvt, TFLAG_DTMF);
2218 				switch_mutex_unlock(tech_pvt->flag_mutex);
2219 			}
2220 		} else {
2221 			WARNINGA("received %c DTMF, but no channel?\n", SKYPOPEN_P_LOG, value[0]);
2222 		}
2223 		switch_core_session_rwunlock(session);
2224 	} else {
2225 		WARNINGA("received %c DTMF, but no session?\n", SKYPOPEN_P_LOG, value[0]);
2226 	}
2227 
2228 	return 0;
2229 }
2230 
skypopen_do_mod_sms_thread(switch_thread_t * thread,void * obj)2231 void *SWITCH_THREAD_FUNC skypopen_do_mod_sms_thread(switch_thread_t *thread, void *obj)
2232 {
2233 	switch_event_t *event;
2234 
2235 
2236 	event = obj;
2237 	switch_core_chat_send("GLOBAL", event);	/* mod_sms */
2238 
2239 	return event;
2240 
2241 }
2242 
2243 
2244 
start_mod_sms_thread(private_t * tech_pvt,switch_event_t * event)2245 int start_mod_sms_thread(private_t *tech_pvt, switch_event_t *event)
2246 {
2247 	switch_threadattr_t *mod_sms_thread_thd_attr = NULL;
2248 	switch_thread_t *mod_sms_thread;
2249 
2250 
2251 	switch_threadattr_create(&mod_sms_thread_thd_attr, skypopen_module_pool);
2252 	switch_threadattr_detach_set(mod_sms_thread_thd_attr, 0);
2253 	switch_threadattr_stacksize_set(mod_sms_thread_thd_attr, SWITCH_THREAD_STACKSIZE);
2254 	if (switch_thread_create(&mod_sms_thread, mod_sms_thread_thd_attr, skypopen_do_mod_sms_thread, event, skypopen_module_pool) == SWITCH_STATUS_SUCCESS) {
2255 		DEBUGA_SKYPE("started mod_sms_thread thread.\n", SKYPOPEN_P_LOG);
2256 	} else {
2257 		ERRORA("failed to start mod_sms_thread thread.\n", SKYPOPEN_P_LOG);
2258 		return -1;
2259 	}
2260 	if (mod_sms_thread == NULL) {
2261 		WARNINGA("mod_sms_thread exited\n", SKYPOPEN_P_LOG);
2262 		return -1;
2263 	}
2264 
2265 	return 0;
2266 }
2267 
2268 
start_audio_threads(private_t * tech_pvt)2269 int start_audio_threads(private_t *tech_pvt)
2270 {
2271 	switch_threadattr_t *tcp_srv_thread_thd_attr = NULL;
2272 	switch_threadattr_t *tcp_cli_thread_thd_attr = NULL;
2273 
2274 	tech_pvt->begin_to_write = 0;
2275 	tech_pvt->begin_to_read = 0;
2276 
2277 	if (switch_core_timer_init(&tech_pvt->timer_read, "soft", MS_SKYPOPEN, SAMPLES_PER_FRAME, skypopen_module_pool) != SWITCH_STATUS_SUCCESS) {
2278 		ERRORA("setup timer failed\n", SKYPOPEN_P_LOG);
2279 		return SWITCH_STATUS_FALSE;
2280 	}
2281 
2282 	switch_core_timer_sync(&tech_pvt->timer_read);
2283 
2284 	if (switch_core_timer_init(&tech_pvt->timer_read_srv, "soft", MS_SKYPOPEN, SAMPLES_PER_FRAME, skypopen_module_pool) != SWITCH_STATUS_SUCCESS) {
2285 		ERRORA("setup timer failed\n", SKYPOPEN_P_LOG);
2286 		return SWITCH_STATUS_FALSE;
2287 	}
2288 
2289 	switch_core_timer_sync(&tech_pvt->timer_read_srv);
2290 
2291 	if (switch_core_timer_init(&tech_pvt->timer_write, "soft", MS_SKYPOPEN, SAMPLES_PER_FRAME, skypopen_module_pool) != SWITCH_STATUS_SUCCESS) {
2292 		ERRORA("setup timer failed\n", SKYPOPEN_P_LOG);
2293 		return SWITCH_STATUS_FALSE;
2294 	}
2295 
2296 	switch_core_timer_sync(&tech_pvt->timer_write);
2297 
2298 	switch_threadattr_create(&tcp_srv_thread_thd_attr, skypopen_module_pool);
2299 	switch_threadattr_detach_set(tcp_srv_thread_thd_attr, 0);
2300 	switch_threadattr_stacksize_set(tcp_srv_thread_thd_attr, SWITCH_THREAD_STACKSIZE);
2301 	switch_threadattr_priority_set(tcp_srv_thread_thd_attr, SWITCH_PRI_REALTIME);
2302 	switch_mutex_lock(tech_pvt->mutex_thread_audio_srv);
2303 	//DEBUGA_SKYPE("debugging_hangup srv lock\n", SKYPOPEN_P_LOG);
2304 	if (switch_thread_create(&tech_pvt->tcp_srv_thread, tcp_srv_thread_thd_attr, skypopen_do_tcp_srv_thread, tech_pvt, skypopen_module_pool) ==
2305 		SWITCH_STATUS_SUCCESS) {
2306 		DEBUGA_SKYPE("started tcp_srv_thread thread.\n", SKYPOPEN_P_LOG);
2307 	} else {
2308 		ERRORA("failed to start tcp_srv_thread thread.\n", SKYPOPEN_P_LOG);
2309 		switch_mutex_unlock(tech_pvt->mutex_thread_audio_srv);
2310 		//DEBUGA_SKYPE("debugging_hangup srv unlock\n", SKYPOPEN_P_LOG);
2311 		return -1;
2312 	}
2313 	switch_mutex_unlock(tech_pvt->mutex_thread_audio_srv);
2314 	//DEBUGA_SKYPE("debugging_hangup srv unlock\n", SKYPOPEN_P_LOG);
2315 
2316 	switch_threadattr_create(&tcp_cli_thread_thd_attr, skypopen_module_pool);
2317 	switch_threadattr_detach_set(tcp_cli_thread_thd_attr, 0);
2318 	switch_threadattr_stacksize_set(tcp_cli_thread_thd_attr, SWITCH_THREAD_STACKSIZE);
2319 	switch_threadattr_priority_set(tcp_cli_thread_thd_attr, SWITCH_PRI_REALTIME);
2320 	switch_mutex_lock(tech_pvt->mutex_thread_audio_cli);
2321 	//DEBUGA_SKYPE("debugging_hangup cli lock\n", SKYPOPEN_P_LOG);
2322 	if (switch_thread_create(&tech_pvt->tcp_cli_thread, tcp_cli_thread_thd_attr, skypopen_do_tcp_cli_thread, tech_pvt, skypopen_module_pool) ==
2323 		SWITCH_STATUS_SUCCESS) {
2324 		DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPOPEN_P_LOG);
2325 	} else {
2326 		ERRORA("failed to start tcp_cli_thread thread.\n", SKYPOPEN_P_LOG);
2327 		switch_mutex_unlock(tech_pvt->mutex_thread_audio_cli);
2328 		//DEBUGA_SKYPE("debugging_hangup cli unlock\n", SKYPOPEN_P_LOG);
2329 		return -1;
2330 	}
2331 	switch_mutex_unlock(tech_pvt->mutex_thread_audio_cli);
2332 	//DEBUGA_SKYPE("debugging_hangup cli unlock\n", SKYPOPEN_P_LOG);
2333 	switch_sleep(100000);
2334 
2335 	if (tech_pvt->tcp_cli_thread == NULL || tech_pvt->tcp_srv_thread == NULL) {
2336 		WARNINGA("tcp_cli_thread or tcp_srv_thread exited\n", SKYPOPEN_P_LOG);
2337 		return -1;
2338 	}
2339 
2340 	return 0;
2341 }
2342 
new_inbound_channel(private_t * tech_pvt)2343 int new_inbound_channel(private_t *tech_pvt)
2344 {
2345 	switch_core_session_t *session = NULL;
2346 	switch_channel_t *channel = NULL;
2347 
2348 	if ((session = switch_core_session_request(skypopen_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL)) != 0) {
2349 		DEBUGA_SKYPE("2 SESSION_REQUEST %s\n", SKYPOPEN_P_LOG, switch_core_session_get_uuid(session));
2350 		switch_core_session_add_stream(session, NULL);
2351 		channel = switch_core_session_get_channel(session);
2352 		if (!channel) {
2353 			ERRORA("Doh! no channel?\n", SKYPOPEN_P_LOG);
2354 			switch_core_session_destroy(&session);
2355 			return 0;
2356 		}
2357 		switch_channel_set_variable(channel, "waste", "false");
2358 		if (skypopen_tech_init(tech_pvt, session) != SWITCH_STATUS_SUCCESS) {
2359 			ERRORA("Doh! no tech_init?\n", SKYPOPEN_P_LOG);
2360 			switch_core_session_destroy(&session);
2361 			return 0;
2362 		}
2363 
2364 		if ((tech_pvt->caller_profile =
2365 			 switch_caller_profile_new(switch_core_session_get_pool(session), "skypopen",
2366 									   tech_pvt->dialplan, tech_pvt->callid_name,
2367 									   tech_pvt->callid_number, NULL, NULL, NULL, NULL, "mod_skypopen", tech_pvt->context, tech_pvt->destination)) != 0) {
2368 			char name[128];
2369 			switch_snprintf(name, sizeof(name), "skypopen/%s", tech_pvt->name);
2370 			switch_channel_set_name(channel, name);
2371 			switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
2372 		}
2373 		switch_channel_set_state(channel, CS_INIT);
2374 		if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
2375 			ERRORA("Error spawning thread\n", SKYPOPEN_P_LOG);
2376 			switch_core_session_destroy(&session);
2377 			return 0;
2378 		}
2379 	}
2380 	if (channel) {
2381 		switch_channel_set_variable(channel, "skype_user", tech_pvt->skype_user);
2382 		switch_channel_set_variable(channel, "initial_skype_user", tech_pvt->initial_skype_user);
2383 	}
2384 
2385 	DEBUGA_SKYPE("new_inbound_channel\n", SKYPOPEN_P_LOG);
2386 
2387 	return 0;
2388 }
2389 
remote_party_is_ringing(private_t * tech_pvt)2390 int remote_party_is_ringing(private_t *tech_pvt)
2391 {
2392 	switch_core_session_t *session = NULL;
2393 	switch_channel_t *channel = NULL;
2394 
2395 	if (!zstr(tech_pvt->session_uuid_str)) {
2396 		session = switch_core_session_locate(tech_pvt->session_uuid_str);
2397 	} else {
2398 		ERRORA("No session_uuid_str???\n", SKYPOPEN_P_LOG);
2399 		return SWITCH_STATUS_FALSE;
2400 	}
2401 	if (session) {
2402 		channel = switch_core_session_get_channel(session);
2403 	} else {
2404 		ERRORA("No session???\n", SKYPOPEN_P_LOG);
2405 		return SWITCH_STATUS_FALSE;
2406 	}
2407 	if (channel) {
2408 		switch_channel_mark_ring_ready(channel);
2409 		DEBUGA_SKYPE("skype_call: REMOTE PARTY RINGING\n", SKYPOPEN_P_LOG);
2410 	} else {
2411 		ERRORA("No channel???\n", SKYPOPEN_P_LOG);
2412 	}
2413 
2414 	switch_core_session_rwunlock(session);
2415 
2416 	return SWITCH_STATUS_SUCCESS;
2417 }
2418 
remote_party_is_early_media(private_t * tech_pvt)2419 int remote_party_is_early_media(private_t *tech_pvt)
2420 {
2421 	switch_core_session_t *session = NULL;
2422 	switch_channel_t *channel = NULL;
2423 
2424 	if (!zstr(tech_pvt->session_uuid_str)) {
2425 		session = switch_core_session_locate(tech_pvt->session_uuid_str);
2426 	} else {
2427 		ERRORA("No session_uuid_str???\n\n\n", SKYPOPEN_P_LOG);
2428 		goto done;
2429 	}
2430 	if (session) {
2431 		channel = switch_core_session_get_channel(session);
2432 		switch_core_session_add_stream(session, NULL);
2433 	} else {
2434 		ERRORA("No session???\n", SKYPOPEN_P_LOG);
2435 		goto done;
2436 	}
2437 	if (channel) {
2438 		switch_channel_mark_pre_answered(channel);
2439 		DEBUGA_SKYPE("skype_call: REMOTE PARTY EARLY MEDIA\n", SKYPOPEN_P_LOG);
2440 	} else {
2441 		ERRORA("No channel???\n", SKYPOPEN_P_LOG);
2442 	}
2443 
2444 	switch_core_session_rwunlock(session);
2445 
2446   done:
2447 	return 0;
2448 }
2449 
outbound_channel_answered(private_t * tech_pvt)2450 int outbound_channel_answered(private_t *tech_pvt)
2451 {
2452 	switch_core_session_t *session = NULL;
2453 	switch_channel_t *channel = NULL;
2454 
2455 	if (!zstr(tech_pvt->session_uuid_str)) {
2456 		session = switch_core_session_locate(tech_pvt->session_uuid_str);
2457 	} else {
2458 		ERRORA("No session???\n", SKYPOPEN_P_LOG);
2459 		goto done;
2460 	}
2461 	if (session) {
2462 		channel = switch_core_session_get_channel(session);
2463 	} else {
2464 		ERRORA("No channel???\n", SKYPOPEN_P_LOG);
2465 		goto done;
2466 	}
2467 	if (channel) {
2468 		switch_channel_mark_answered(channel);
2469 	} else {
2470 		ERRORA("No channel???\n", SKYPOPEN_P_LOG);
2471 	}
2472 
2473 	switch_core_session_rwunlock(session);
2474 
2475   done:
2476 	DEBUGA_SKYPE("outbound_channel_answered!\n", SKYPOPEN_P_LOG);
2477 
2478 	return 0;
2479 }
2480 
find_available_skypopen_interface_rr(private_t * tech_pvt_calling)2481 private_t *find_available_skypopen_interface_rr(private_t *tech_pvt_calling)
2482 {
2483 	private_t *tech_pvt = NULL;
2484 	int i;
2485 
2486 	switch_mutex_lock(globals.mutex);
2487 
2488 	/* Fact is the real interface start from 1 */
2489 	//XXX no, is just a convention, but you can have it start from 0. I do not, for aestetic reasons :-)
2490 
2491 	for (i = 0; i < SKYPOPEN_MAX_INTERFACES; i++) {
2492 		int interface_id;
2493 
2494 		interface_id = globals.next_interface;
2495 		globals.next_interface = interface_id + 1 < SKYPOPEN_MAX_INTERFACES ? interface_id + 1 : 0;
2496 
2497 		if (strlen(globals.SKYPOPEN_INTERFACES[interface_id].name)) {
2498 			int skype_state = 0;
2499 
2500 			tech_pvt = &globals.SKYPOPEN_INTERFACES[interface_id];
2501 			skype_state = tech_pvt->interface_state;
2502 			if ((tech_pvt_calling ? strcmp(tech_pvt->skype_user, tech_pvt_calling->skype_user) : 1)
2503 				&& (SKYPOPEN_STATE_IDLE == skype_state)) {
2504 				DEBUGA_SKYPE("returning as available skype interface name: %s, state: %d callflow: %d\n", SKYPOPEN_P_LOG, tech_pvt->name, skype_state,
2505 							 tech_pvt->skype_callflow);
2506 				if (tech_pvt_calling == NULL) {
2507 					tech_pvt->interface_state = SKYPOPEN_STATE_SELECTED;
2508 				}
2509 
2510 				switch_mutex_unlock(globals.mutex);
2511 				return tech_pvt;
2512 			}
2513 		}
2514 	}
2515 
2516 	switch_mutex_unlock(globals.mutex);
2517 	return NULL;
2518 }
2519 
SWITCH_STANDARD_API(sk_function)2520 SWITCH_STANDARD_API(sk_function)
2521 {
2522 	char *mycmd = NULL, *argv[10] = { 0 };
2523 	int argc = 0;
2524 	int tmp_i = 0;
2525 	char tmp_message[4096];
2526 
2527 	if (globals.sk_console)
2528 		stream->write_function(stream, "sk console is: |||%s|||\n", globals.sk_console->name);
2529 	else
2530 		stream->write_function(stream, "sk console is NOT yet assigned\n");
2531 
2532 	if (!zstr(cmd) && (mycmd = strdup(cmd))) {
2533 		argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
2534 	}
2535 
2536 	if (!argc || !argv[0]) {
2537 		stream->write_function(stream, "%s", SK_SYNTAX);
2538 		goto end;
2539 	}
2540 
2541 
2542 	if (!strcasecmp(argv[0], "balances")) {
2543 		stream->write_function(stream, "  Name  \tBalance\tCurrency\n");
2544 		stream->write_function(stream, "  ====  \t=======\t========\n");
2545 
2546 		for (tmp_i = 0; tmp_i < SKYPOPEN_MAX_INTERFACES; tmp_i++) {
2547 			if (strlen(globals.SKYPOPEN_INTERFACES[tmp_i].name)) {
2548 				skypopen_signaling_write(&globals.SKYPOPEN_INTERFACES[tmp_i], "GET PROFILE PSTN_BALANCE");
2549 				switch_sleep(20000);
2550 
2551 				strncpy(tmp_message, globals.SKYPOPEN_INTERFACES[tmp_i].message, sizeof(globals.SKYPOPEN_INTERFACES[tmp_i].message));
2552 
2553 				skypopen_signaling_write(&globals.SKYPOPEN_INTERFACES[tmp_i], "GET PROFILE PSTN_BALANCE_CURRENCY");
2554 				switch_sleep(20000);
2555 				if (strlen(tmp_message) > 21 && strlen(globals.SKYPOPEN_INTERFACES[tmp_i].message) > 30)
2556 					stream->write_function(stream, "  %s \t%s\t%s\n", globals.SKYPOPEN_INTERFACES[tmp_i].name, tmp_message + 21,
2557 										   globals.SKYPOPEN_INTERFACES[tmp_i].message + 30);
2558 			}
2559 		}
2560 	} else if (!strcasecmp(argv[0], "list")) {
2561 		int i;
2562 		unsigned int ib = 0;
2563 		unsigned int ib_failed = 0;
2564 		unsigned int ob = 0;
2565 		unsigned int ob_failed = 0;
2566 		char next_flag_char = ' ';
2567 
2568 		stream->write_function(stream, "F ID\t    Name    \tIB (F/T)    OB (F/T)\tState\tCallFlw\t\tUUID\n");
2569 		stream->write_function(stream, "= ====\t  ========  \t=======     =======\t======\t============\t======\n");
2570 
2571 		for (i = 0; i < SKYPOPEN_MAX_INTERFACES; i++) {
2572 			if (strlen(globals.SKYPOPEN_INTERFACES[i].name)) {
2573 				next_flag_char = i == globals.next_interface ? '*' : ' ';
2574 				ib += globals.SKYPOPEN_INTERFACES[i].ib_calls;
2575 				ib_failed += globals.SKYPOPEN_INTERFACES[i].ib_failed_calls;
2576 				ob += globals.SKYPOPEN_INTERFACES[i].ob_calls;
2577 				ob_failed += globals.SKYPOPEN_INTERFACES[i].ob_failed_calls;
2578 
2579 				stream->write_function(stream,
2580 									   "%c %d\t[%6s]\t%3u/%u\t%6u/%u\t%s\t%s\t%s\n",
2581 									   next_flag_char,
2582 									   i, globals.SKYPOPEN_INTERFACES[i].name,
2583 									   globals.SKYPOPEN_INTERFACES[i].ib_failed_calls,
2584 									   globals.SKYPOPEN_INTERFACES[i].ib_calls,
2585 									   globals.SKYPOPEN_INTERFACES[i].ob_failed_calls,
2586 									   globals.SKYPOPEN_INTERFACES[i].ob_calls,
2587 									   interface_status[globals.SKYPOPEN_INTERFACES[i].interface_state],
2588 									   skype_callflow[globals.SKYPOPEN_INTERFACES[i].skype_callflow], globals.SKYPOPEN_INTERFACES[i].session_uuid_str);
2589 			} else if (argc > 1 && !strcasecmp(argv[1], "full")) {
2590 				stream->write_function(stream, "%c %d\n", next_flag_char, i);
2591 			}
2592 
2593 		}
2594 		stream->write_function(stream, "\nTotal Interfaces: %d  IB Calls(Failed/Total): %u/%u  OB Calls(Failed/Total): %u/%u\n",
2595 							   globals.real_interfaces > 0 ? globals.real_interfaces - 1 : 0, ib_failed, ib, ob_failed, ob);
2596 
2597 	} else if (!strcasecmp(argv[0], "console")) {
2598 		int i;
2599 		int found = 0;
2600 
2601 		if (argc == 2) {
2602 			for (i = 0; !found && i < SKYPOPEN_MAX_INTERFACES; i++) {
2603 				/* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */
2604 				if (strlen(globals.SKYPOPEN_INTERFACES[i].name)
2605 					&& (strncmp(globals.SKYPOPEN_INTERFACES[i].name, argv[1], strlen(argv[1])) == 0)) {
2606 					globals.sk_console = &globals.SKYPOPEN_INTERFACES[i];
2607 					stream->write_function(stream,
2608 										   "sk console is now: globals.SKYPOPEN_INTERFACES[%d].name=|||%s|||\n", i, globals.SKYPOPEN_INTERFACES[i].name);
2609 					stream->write_function(stream, "sk console is: |||%s|||\n", globals.sk_console->name);
2610 					found = 1;
2611 					break;
2612 				}
2613 
2614 			}
2615 			if (!found)
2616 				stream->write_function(stream, "ERROR: A Skypopen interface with name='%s' was not found\n", argv[1]);
2617 		} else {
2618 
2619 			stream->write_function(stream, "-ERR Usage: sk console interface_name\n");
2620 			goto end;
2621 		}
2622 
2623 	} else if (!strcasecmp(argv[0], "reload")) {
2624 		if (load_config(SOFT_RELOAD) != SWITCH_STATUS_SUCCESS) {
2625 			stream->write_function(stream, "sk reload failed\n");
2626 		} else {
2627 			stream->write_function(stream, "sk reload success\n");
2628 		}
2629 	} else if (!strcasecmp(argv[0], "remove")) {
2630 		if (argc == 2) {
2631 			if (remove_interface(argv[1], FALSE) == SWITCH_STATUS_SUCCESS) {
2632 				if (interface_exists(argv[1]) == SWITCH_STATUS_SUCCESS) {
2633 					stream->write_function(stream, "sk remove '%s' failed\n", argv[1]);
2634 				} else {
2635 					stream->write_function(stream, "sk remove '%s' success\n", argv[1]);
2636 				}
2637 			}
2638 		} else {
2639 			stream->write_function(stream, "-ERR Usage: sk remove interface_name\n");
2640 			goto end;
2641 		}
2642 
2643 	} else {
2644 		if (globals.sk_console)
2645 			skypopen_signaling_write(globals.sk_console, (char *) cmd);
2646 		else
2647 			stream->write_function(stream, "sk console is NOT yet assigned\n");
2648 	}
2649   end:
2650 	switch_safe_free(mycmd);
2651 
2652 	return SWITCH_STATUS_SUCCESS;
2653 }
2654 
SWITCH_STANDARD_API(skypopen_function)2655 SWITCH_STANDARD_API(skypopen_function)
2656 {
2657 	char *mycmd = NULL, *argv[10] = { 0 };
2658 	int argc = 0;
2659 	private_t *tech_pvt = NULL;
2660 
2661 	if (!zstr(cmd) && (mycmd = strdup(cmd))) {
2662 		argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
2663 	}
2664 
2665 	if (!argc) {
2666 		stream->write_function(stream, "ERROR, usage: %s", SKYPOPEN_SYNTAX);
2667 		goto end;
2668 	}
2669 
2670 	if (argc < 2) {
2671 		stream->write_function(stream, "ERROR, usage: %s", SKYPOPEN_SYNTAX);
2672 		goto end;
2673 	}
2674 
2675 	if (argv[0]) {
2676 		int i;
2677 		int found = 0;
2678 
2679 		for (i = 0; !found && i < SKYPOPEN_MAX_INTERFACES; i++) {
2680 			/* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */
2681 			if (strlen(globals.SKYPOPEN_INTERFACES[i].name)
2682 				&& (strncmp(globals.SKYPOPEN_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) {
2683 				tech_pvt = &globals.SKYPOPEN_INTERFACES[i];
2684 				stream->write_function(stream, "Using interface: globals.SKYPOPEN_INTERFACES[%d].name=|||%s|||\n", i, globals.SKYPOPEN_INTERFACES[i].name);
2685 				found = 1;
2686 				break;
2687 			}
2688 
2689 		}
2690 		if (!found) {
2691 			stream->write_function(stream, "ERROR: A Skypopen interface with name='%s' was not found\n", argv[0]);
2692 			switch_safe_free(mycmd);
2693 
2694 			return SWITCH_STATUS_SUCCESS;
2695 		} else {
2696 			skypopen_signaling_write(tech_pvt, (char *) &cmd[strlen(argv[0]) + 1]);
2697 		}
2698 	} else {
2699 		stream->write_function(stream, "ERROR, usage: %s", SKYPOPEN_SYNTAX);
2700 	}
2701   end:
2702 	switch_safe_free(mycmd);
2703 
2704 	return SWITCH_STATUS_SUCCESS;
2705 }
2706 
2707 
skypopen_partner_handle_ring(private_t * tech_pvt)2708 int skypopen_partner_handle_ring(private_t *tech_pvt)
2709 {
2710 	char msg_to_skype[1024];
2711 	int i;
2712 	int found = 0;
2713 	private_t *giovatech;
2714 	struct timeval timenow;
2715 	char *id = tech_pvt->ring_id;
2716 	char *value = tech_pvt->ring_value;
2717 	switch_core_session_t *session = NULL;
2718 
2719 	switch_mutex_lock(globals.mutex);
2720 
2721 	gettimeofday(&timenow, NULL);
2722 	for (i = 0; !found && i < SKYPOPEN_MAX_INTERFACES; i++) {
2723 		if (strlen(globals.SKYPOPEN_INTERFACES[i].name)) {
2724 
2725 			giovatech = &globals.SKYPOPEN_INTERFACES[i];
2726 			if ((giovatech->interface_state != SKYPOPEN_STATE_DEAD) && (giovatech->interface_state != SKYPOPEN_STATE_DOWN) && (giovatech->interface_state != SKYPOPEN_STATE_IDLE) && (strcmp(giovatech->name, tech_pvt->name)) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->ring_value, value)) && ((((timenow.tv_sec - giovatech->ring_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->ring_time.tv_usec)) < 1000000)) {	//XXX 1.0sec - can have a max of 1 call coming from the same skypename to the same skypename each 1.0 seconds
2727 				found = 1;
2728 				DEBUGA_SKYPE
2729 					("FOUND  (name=%s, giovatech->interface_state=%d != SKYPOPEN_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->callid_number=%s == value=%s)\n",
2730 					 SKYPOPEN_P_LOG, giovatech->name, giovatech->interface_state, giovatech->skype_user, tech_pvt->skype_user, giovatech->callid_number,
2731 					 value);
2732 				if (tech_pvt->interface_state == SKYPOPEN_STATE_PRERING) {
2733 					tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
2734 				} else if (tech_pvt->interface_state != 0 && tech_pvt->interface_state != SKYPOPEN_STATE_DOWN) {
2735 					WARNINGA("Why an interface_state %d HERE?\n", SKYPOPEN_P_LOG, tech_pvt->interface_state);
2736 					tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
2737 				}
2738 
2739 				*tech_pvt->answer_id = '\0';
2740 				*tech_pvt->answer_value = '\0';
2741 				*tech_pvt->ring_id = '\0';
2742 				*tech_pvt->ring_value = '\0';
2743 				break;
2744 			}
2745 		}
2746 	}
2747 
2748 	if (found) {
2749 		switch_mutex_unlock(globals.mutex);
2750 		return 0;
2751 	}
2752 	DEBUGA_SKYPE("NOT FOUND\n", SKYPOPEN_P_LOG);
2753 
2754 	// CLOUDTREE (Thomas Hazel)
2755 	if (tech_pvt && tech_pvt->ringing_state == SKYPOPEN_RINGING_INIT) {
2756 		/* we are not inside an active call */
2757 
2758 		switch_channel_t *channel = NULL;
2759 
2760 		tech_pvt->interface_state = SKYPOPEN_STATE_PRERING;
2761 		gettimeofday(&tech_pvt->ring_time, NULL);
2762 		switch_copy_string(tech_pvt->callid_number, value, sizeof(tech_pvt->callid_number) - 1);
2763 
2764 		session = switch_core_session_locate(tech_pvt->session_uuid_str);
2765 		if (session) {
2766 			switch_core_session_rwunlock(session);
2767 			return 0;
2768 		}
2769 
2770 		new_inbound_channel(tech_pvt);
2771 
2772 		switch_sleep(10000);
2773 
2774 		session = switch_core_session_locate(tech_pvt->session_uuid_str);
2775 		if (session) {
2776 			channel = switch_core_session_get_channel(session);
2777 			switch_core_session_queue_indication(session, SWITCH_MESSAGE_INDICATE_RINGING);
2778 			if (channel) {
2779 				switch_channel_mark_ring_ready(channel);
2780 				DEBUGA_SKYPE("switch_channel_mark_ring_ready(channel);\n", SKYPOPEN_P_LOG);
2781 			} else {
2782 				ERRORA("no channel\n", SKYPOPEN_P_LOG);
2783 			}
2784 			switch_core_session_rwunlock(session);
2785 		} else {
2786 			ERRORA("no session\n", SKYPOPEN_P_LOG);
2787 		}
2788 	} else if (!tech_pvt || !tech_pvt->skype_call_id[0]) {
2789 		ERRORA("No Call ID?\n", SKYPOPEN_P_LOG);
2790 	} else {
2791 		DEBUGA_SKYPE("We're in a call now (%s), let's refuse this one (%s)\n", SKYPOPEN_P_LOG, tech_pvt->skype_call_id, id);
2792 		sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
2793 		skypopen_signaling_write(tech_pvt, msg_to_skype);
2794 		sprintf(msg_to_skype, "ALTER CALL %s HANGUP", id);
2795 		skypopen_signaling_write(tech_pvt, msg_to_skype);
2796 	}
2797 
2798 	switch_mutex_unlock(globals.mutex);
2799 	return 0;
2800 }
2801 
skypopen_answer(private_t * tech_pvt)2802 int skypopen_answer(private_t *tech_pvt)
2803 {
2804 	char msg_to_skype[1024];
2805 	int i;
2806 	int found = 0;
2807 	private_t *giovatech;
2808 	struct timeval timenow;
2809 	char *id = tech_pvt->answer_id;
2810 	char *value = tech_pvt->answer_value;
2811 	switch_core_session_t *session = NULL;
2812 	switch_channel_t *channel = NULL;
2813 
2814 	switch_mutex_lock(globals.mutex);
2815 
2816 	gettimeofday(&timenow, NULL);
2817 	for (i = 0; !found && i < SKYPOPEN_MAX_INTERFACES; i++) {
2818 		if (strlen(globals.SKYPOPEN_INTERFACES[i].name)) {
2819 
2820 			giovatech = &globals.SKYPOPEN_INTERFACES[i];
2821 			if (strlen(giovatech->skype_call_id) && (giovatech->interface_state != SKYPOPEN_STATE_DEAD) && (giovatech->interface_state != SKYPOPEN_STATE_DOWN) && (giovatech->interface_state != SKYPOPEN_STATE_IDLE) && (strcmp(giovatech->name, tech_pvt->name)) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->callid_number, value)) && ((((timenow.tv_sec - giovatech->answer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->answer_time.tv_usec)) < 1000000)) {	//XXX 1.0sec - can have a max of 1 call coming from the same skypename to the same skypename each 1.0 seconds
2822 				found = 1;
2823 				DEBUGA_SKYPE
2824 					("FOUND  (name=%s, giovatech->interface_state=%d != SKYPOPEN_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->callid_number=%s == value=%s)\n",
2825 					 SKYPOPEN_P_LOG, giovatech->name, giovatech->interface_state, giovatech->skype_user, tech_pvt->skype_user, giovatech->callid_number,
2826 					 value);
2827 				if (tech_pvt->interface_state == SKYPOPEN_STATE_PRERING) {
2828 					tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
2829 				} else if (tech_pvt->interface_state != 0 && tech_pvt->interface_state != SKYPOPEN_STATE_DOWN) {
2830 					WARNINGA("Why an interface_state %d HERE?\n", SKYPOPEN_P_LOG, tech_pvt->interface_state);
2831 					tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
2832 				}
2833 
2834 
2835 				if (!zstr(tech_pvt->session_uuid_str)) {
2836 					session = switch_core_session_locate(tech_pvt->session_uuid_str);
2837 				} else {
2838 					ERRORA("No session_uuid_str???\n", SKYPOPEN_P_LOG);
2839 					break;
2840 				}
2841 				if (session) {
2842 					channel = switch_core_session_get_channel(session);
2843 				} else {
2844 					ERRORA("No session???\n", SKYPOPEN_P_LOG);
2845 					switch_core_session_rwunlock(session);
2846 					break;
2847 				}
2848 				if (channel) {
2849 					switch_channel_set_state(channel, CS_RESET);
2850 				} else {
2851 					ERRORA("No channel???\n", SKYPOPEN_P_LOG);
2852 					switch_core_session_rwunlock(session);
2853 					break;
2854 				}
2855 
2856 				switch_core_session_rwunlock(session);
2857 
2858 				break;
2859 			}
2860 		}
2861 	}
2862 
2863 	if (found) {
2864 		switch_mutex_unlock(globals.mutex);
2865 		return 0;
2866 	}
2867 	DEBUGA_SKYPE("NOT FOUND\n", SKYPOPEN_P_LOG);
2868 
2869 	// CLOUDTREE (Thomas Hazel)
2870 	if (tech_pvt && tech_pvt->ringing_state == SKYPOPEN_RINGING_INIT) {
2871 		/* we are not inside an active call */
2872 
2873 		tech_pvt->ib_calls++;
2874 
2875 		tech_pvt->interface_state = SKYPOPEN_STATE_PREANSWER;
2876 		sprintf(msg_to_skype, "ALTER CALL %s ANSWER", id);
2877 		skypopen_signaling_write(tech_pvt, msg_to_skype);
2878 		DEBUGA_SKYPE("We answered a Skype RING on skype_call %s\n", SKYPOPEN_P_LOG, id);
2879 		gettimeofday(&tech_pvt->answer_time, NULL);
2880 		switch_copy_string(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
2881 
2882 		switch_copy_string(tech_pvt->callid_number, value, sizeof(tech_pvt->callid_number) - 1);
2883 
2884 		DEBUGA_SKYPE
2885 			("NEW!  name: %s, state: %d, value=%s, tech_pvt->callid_number=%s, tech_pvt->skype_user=%s\n",
2886 			 SKYPOPEN_P_LOG, tech_pvt->name, tech_pvt->interface_state, value, tech_pvt->callid_number, tech_pvt->skype_user);
2887 	} else if (!tech_pvt || !tech_pvt->skype_call_id[0]) {
2888 		ERRORA("No Call ID?\n", SKYPOPEN_P_LOG);
2889 	} else {
2890 		DEBUGA_SKYPE("We're in a call now (%s), let's refuse this one (%s)\n", SKYPOPEN_P_LOG, tech_pvt->skype_call_id, id);
2891 		sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
2892 		skypopen_signaling_write(tech_pvt, msg_to_skype);
2893 		sprintf(msg_to_skype, "ALTER CALL %s HANGUP", id);
2894 		skypopen_signaling_write(tech_pvt, msg_to_skype);
2895 	}
2896 
2897 	switch_mutex_unlock(globals.mutex);
2898 	return 0;
2899 }
2900 
skypopen_transfer(private_t * tech_pvt)2901 int skypopen_transfer(private_t *tech_pvt)
2902 {
2903 	char msg_to_skype[1024];
2904 	int i;
2905 	int found = 0;
2906 	private_t *giovatech;
2907 	struct timeval timenow;
2908 	char *id = tech_pvt->ring_id;
2909 	char *value = tech_pvt->ring_value;
2910 
2911 	switch_mutex_lock(globals.mutex);
2912 
2913 	gettimeofday(&timenow, NULL);
2914 	for (i = 0; !found && i < SKYPOPEN_MAX_INTERFACES; i++) {
2915 		if (strlen(globals.SKYPOPEN_INTERFACES[i].name)) {
2916 
2917 			giovatech = &globals.SKYPOPEN_INTERFACES[i];
2918 			/* let's look for a RINGING one */
2919 			if ((giovatech->interface_state != SKYPOPEN_STATE_DEAD) && (giovatech->interface_state != SKYPOPEN_STATE_DOWN) && (giovatech->interface_state != SKYPOPEN_STATE_IDLE) && (strcmp(giovatech->name, tech_pvt->name)) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->ring_value, value)) && ((((timenow.tv_sec - giovatech->ring_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->ring_time.tv_usec)) < 1000000)) {	//XXX 1.0sec - can have a max of 1 call coming from the same skypename to the same skypename each 1.0 seconds
2920 				found = 1;
2921 				DEBUGA_SKYPE
2922 					("FOUND  (name=%s, giovatech->interface_state=%d != SKYPOPEN_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->callid_number=%s == value=%s)\n",
2923 					 SKYPOPEN_P_LOG, giovatech->name, giovatech->interface_state, giovatech->skype_user, tech_pvt->skype_user, giovatech->callid_number,
2924 					 value);
2925 				if (tech_pvt->interface_state == SKYPOPEN_STATE_PRERING) {
2926 					tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
2927 				}
2928 				break;
2929 			}
2930 		}
2931 	}
2932 
2933 	for (i = 0; !found && i < SKYPOPEN_MAX_INTERFACES; i++) {
2934 		if (strlen(globals.SKYPOPEN_INTERFACES[i].name)) {
2935 
2936 			giovatech = &globals.SKYPOPEN_INTERFACES[i];
2937 			/* let's look for a IDLE one */
2938 			if ((giovatech->interface_state == SKYPOPEN_STATE_IDLE) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user))) {
2939 				found = 1;
2940 				DEBUGA_SKYPE
2941 					("FOUND  (name=%s, giovatech->interface_state=%d == SKYPOPEN_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->callid_number=%s == value=%s)\n",
2942 					 SKYPOPEN_P_LOG, giovatech->name, giovatech->interface_state, giovatech->skype_user, tech_pvt->skype_user, giovatech->callid_number,
2943 					 value);
2944 				if (tech_pvt->interface_state == SKYPOPEN_STATE_PRERING) {
2945 					tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
2946 				}
2947 				break;
2948 			}
2949 		}
2950 	}
2951 
2952 
2953 	if (found) {
2954 		switch_mutex_unlock(globals.mutex);
2955 		return 0;
2956 	}
2957 	DEBUGA_SKYPE("NOT FOUND\n", SKYPOPEN_P_LOG);
2958 
2959 	if (!tech_pvt || !tech_pvt->skype_call_id[0]) {
2960 		/* we are not inside an active call */
2961 		DEBUGA_SKYPE("We're NO MORE in a call now %s\n", SKYPOPEN_P_LOG, tech_pvt ? tech_pvt->skype_call_id : "");
2962 		switch_mutex_unlock(globals.mutex);
2963 
2964 	} else {
2965 
2966 		/*  we're in a call, let's try to transfer */
2967 		/************************** TODO
2968 		  Checking here if it is possible to transfer this call to Test2
2969 		  -> GET CALL 288 CAN_TRANSFER Test2
2970 		  <- CALL 288 CAN_TRANSFER test2 TRUE
2971 		 **********************************/
2972 
2973 		private_t *available_skypopen_interface = NULL;
2974 
2975 		gettimeofday(&timenow, NULL);
2976 		for (i = 0; !found && i < SKYPOPEN_MAX_INTERFACES; i++) {
2977 			if (strlen(globals.SKYPOPEN_INTERFACES[i].name)) {
2978 
2979 				giovatech = &globals.SKYPOPEN_INTERFACES[i];
2980 				if (strlen(giovatech->skype_transfer_call_id) && (giovatech->interface_state != SKYPOPEN_STATE_DOWN) && (giovatech->interface_state != SKYPOPEN_STATE_DEAD) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->transfer_callid_number, value)) && ((((timenow.tv_sec - giovatech->transfer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->transfer_time.tv_usec)) < 1000000)) {	//1.0 sec
2981 					found = 1;
2982 					DEBUGA_SKYPE
2983 						("FOUND  (name=%s, giovatech->interface_state=%d != SKYPOPEN_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->transfer_callid_number=%s == value=%s)\n",
2984 						 SKYPOPEN_P_LOG, giovatech->name, giovatech->interface_state,
2985 						 giovatech->skype_user, tech_pvt->skype_user, giovatech->transfer_callid_number, value)
2986 						break;
2987 				}
2988 			}
2989 		}
2990 
2991 		if (found) {
2992 			switch_mutex_unlock(globals.mutex);
2993 			return 0;
2994 		}
2995 		DEBUGA_SKYPE("NOT FOUND\n", SKYPOPEN_P_LOG);
2996 
2997 		available_skypopen_interface = find_available_skypopen_interface_rr(tech_pvt);
2998 		if (available_skypopen_interface) {
2999 			/* there is a skypopen interface idle, let's transfer the call to it */
3000 
3001 			switch_copy_string(available_skypopen_interface->initial_skype_user, tech_pvt->skype_user, sizeof(tech_pvt->skype_user) - 1);
3002 
3003 			gettimeofday(&tech_pvt->transfer_time, NULL);
3004 			switch_copy_string(tech_pvt->skype_transfer_call_id, id, sizeof(tech_pvt->skype_transfer_call_id) - 1);
3005 
3006 			switch_copy_string(tech_pvt->transfer_callid_number, value, sizeof(tech_pvt->transfer_callid_number) - 1);
3007 
3008 			DEBUGA_SKYPE
3009 				("Let's transfer the skype_call %s to %s interface (with skype_user: %s), because we are already in a skypopen call(%s)\n",
3010 				 SKYPOPEN_P_LOG, tech_pvt->skype_call_id, available_skypopen_interface->name, available_skypopen_interface->skype_user, id);
3011 
3012 
3013 			sprintf(msg_to_skype, "ALTER CALL %s TRANSFER %s", id, available_skypopen_interface->skype_user);
3014 			skypopen_signaling_write(tech_pvt, msg_to_skype);
3015 		} else {
3016 			/* no skypopen interfaces idle, do hangup */
3017 			DEBUGA_SKYPE
3018 				("Not answering the skype_call %s, because we are already in a skypopen call(%s) and not transferring, because no other skypopen interfaces are available\n",
3019 				 SKYPOPEN_P_LOG, id, tech_pvt->skype_call_id);
3020 			sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
3021 			skypopen_signaling_write(tech_pvt, msg_to_skype);
3022 			sprintf(msg_to_skype, "ALTER CALL %s HANGUP", id);
3023 			skypopen_signaling_write(tech_pvt, msg_to_skype);
3024 		}
3025 		switch_sleep(20000);
3026 		DEBUGA_SKYPE
3027 			("We have NOT answered a Skype RING from skype_call %s, because we are already in a skypopen call (%s)\n",
3028 			 SKYPOPEN_P_LOG, id, tech_pvt->skype_call_id);
3029 
3030 		switch_mutex_unlock(globals.mutex);
3031 	}
3032 	return 0;
3033 }
3034 
incoming_chatmessage(private_t * tech_pvt,int which)3035 int incoming_chatmessage(private_t *tech_pvt, int which)
3036 {
3037 	switch_event_t *event;
3038 	switch_core_session_t *session = NULL;
3039 	int event_sent_to_esl = 0;
3040 
3041 	DEBUGA_SKYPE("received CHATMESSAGE on interface %s\n", SKYPOPEN_P_LOG, tech_pvt->name);
3042 
3043 	if (!tech_pvt->report_incoming_chatmessages) {
3044 		DEBUGA_SKYPE("I will not generate an Event, report_incoming_chatmessages is %d\n", SKYPOPEN_P_LOG, tech_pvt->report_incoming_chatmessages);
3045 		return 0;
3046 	}
3047 
3048 	if (!zstr(tech_pvt->session_uuid_str)) {
3049 		session = switch_core_session_locate(tech_pvt->session_uuid_str);
3050 	}
3051 	if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
3052 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SKYPE_CHAT_PROTO);
3053 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", tech_pvt->name);
3054 		//switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", tech_pvt->chatmessages[which].from_dispname);
3055 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", tech_pvt->chatmessages[which].from_handle);
3056 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "SIMPLE MESSAGE");
3057 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "chatname", tech_pvt->chatmessages[which].chatname);
3058 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "id", tech_pvt->chatmessages[which].id);
3059 /* mod_sms begin */
3060 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to", tech_pvt->skype_user);
3061 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", tech_pvt->name);
3062 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_proto", SKYPE_CHAT_PROTO);
3063 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_user", tech_pvt->chatmessages[which].from_handle);
3064 		//switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_host", "from_host");
3065 		//switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_full", "from_full");
3066 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_user", tech_pvt->name);
3067 		//switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_host", "to_host");
3068 /* mod_sms end */
3069 
3070 		switch_event_add_body(event, "%s", tech_pvt->chatmessages[which].body);
3071 
3072 		if (session) {
3073 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "true");
3074 			if (switch_core_session_queue_event(session, &event) != SWITCH_STATUS_SUCCESS) {
3075 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "delivery-failure", "true");
3076 				switch_event_fire(&event);
3077 			}
3078 		} else {				//no session
3079 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "false");
3080 			switch_event_fire(&event);
3081 			event_sent_to_esl = 1;
3082 		}
3083 
3084 	} else {
3085 		ERRORA("cannot create event on interface %s. WHY?????\n", SKYPOPEN_P_LOG, tech_pvt->name);
3086 	}
3087 
3088 	if (!event_sent_to_esl) {
3089 
3090 		if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
3091 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SKYPE_CHAT_PROTO);
3092 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", tech_pvt->name);
3093 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", tech_pvt->chatmessages[which].from_dispname);
3094 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", tech_pvt->chatmessages[which].from_handle);
3095 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "SIMPLE MESSAGE");
3096 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "chatname", tech_pvt->chatmessages[which].chatname);
3097 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "id", tech_pvt->chatmessages[which].id);
3098 			switch_event_add_body(event, "%s", tech_pvt->chatmessages[which].body);
3099 			if (session) {
3100 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "true");
3101 			} else {			//no session
3102 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "false");
3103 			}
3104 			switch_event_fire(&event);
3105 		} else {
3106 			ERRORA("cannot create event on interface %s. WHY?????\n", SKYPOPEN_P_LOG, tech_pvt->name);
3107 		}
3108 	}
3109 
3110 	if (session) {
3111 		switch_core_session_rwunlock(session);
3112 	}
3113 
3114 
3115 	if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
3116 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SKYPE_CHAT_PROTO);
3117 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", tech_pvt->name);
3118 		//switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", tech_pvt->chatmessages[which].from_dispname);
3119 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", tech_pvt->chatmessages[which].from_handle);
3120 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "SIMPLE MESSAGE");
3121 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "chatname", tech_pvt->chatmessages[which].chatname);
3122 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "id", tech_pvt->chatmessages[which].id);
3123 /* mod_sms begin */
3124 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to", tech_pvt->skype_user);
3125 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", tech_pvt->name);
3126 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_proto", SKYPE_CHAT_PROTO);
3127 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_user", tech_pvt->chatmessages[which].from_handle);
3128 		//switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_host", "from_host");
3129 		//switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_full", "from_full");
3130 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_user", tech_pvt->name);
3131 		//switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_host", "to_host");
3132 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "context", tech_pvt->context);
3133 /* mod_sms end */
3134 
3135 		switch_event_add_body(event, "%s", tech_pvt->chatmessages[which].body);
3136 		//switch_core_chat_send("GLOBAL", event); /* mod_sms */
3137 		start_mod_sms_thread(tech_pvt, event);
3138 		//usleep(20000);
3139 
3140 	} else {
3141 		ERRORA("cannot create event on interface %s. WHY?????\n", SKYPOPEN_P_LOG, tech_pvt->name);
3142 	}
3143 
3144 	return 0;
3145 }
3146 
compat_chat_send(const char * proto,const char * from,const char * to,const char * subject,const char * body,const char * type,const char * hint)3147 static switch_status_t compat_chat_send(const char *proto, const char *from, const char *to,
3148 										const char *subject, const char *body, const char *type, const char *hint)
3149 {
3150 	switch_event_t *message_event;
3151 	switch_status_t status;
3152 
3153 	if (switch_event_create(&message_event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
3154 		switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "proto", proto);
3155 		switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "from", from);
3156 		switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "to", to);
3157 		switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "subject", subject);
3158 		switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "type", type);
3159 		switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "hint", hint);
3160 
3161 		if (body) {
3162 			switch_event_add_body(message_event, "%s", body);
3163 		}
3164 	} else {
3165 		abort();
3166 	}
3167 
3168 	status = chat_send(message_event);
3169 	switch_event_destroy(&message_event);
3170 
3171 	return status;
3172 
3173 }
3174 
SWITCH_STANDARD_API(skypopen_chat_function)3175 SWITCH_STANDARD_API(skypopen_chat_function)
3176 {
3177 	char *mycmd = NULL, *argv[10] = { 0 };
3178 	int argc = 0;
3179 	private_t *tech_pvt = NULL;
3180 	int i;
3181 	int found = 0;
3182 
3183 	if (!zstr(cmd) && (mycmd = strdup(cmd))) {
3184 		argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
3185 	}
3186 
3187 	if (!argc) {
3188 		stream->write_function(stream, "ERROR, usage: %s", SKYPOPEN_CHAT_SYNTAX);
3189 		goto end;
3190 	}
3191 
3192 	if (argc < 3) {
3193 		stream->write_function(stream, "ERROR, usage: %s", SKYPOPEN_CHAT_SYNTAX);
3194 		goto end;
3195 	}
3196 
3197 	if (argv[0]) {
3198 		for (i = 0; !found && i < SKYPOPEN_MAX_INTERFACES; i++) {
3199 			/* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */
3200 			if (strlen(globals.SKYPOPEN_INTERFACES[i].name)
3201 				&& (strncmp(globals.SKYPOPEN_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) {
3202 				tech_pvt = &globals.SKYPOPEN_INTERFACES[i];
3203 				stream->write_function(stream, "Using interface: globals.SKYPOPEN_INTERFACES[%d].name=|||%s|||\n", i, globals.SKYPOPEN_INTERFACES[i].name);
3204 				found = 1;
3205 				break;
3206 			}
3207 
3208 		}
3209 		if (!found) {
3210 			stream->write_function(stream, "ERROR: A Skypopen interface with name='%s' was not found\n", argv[0]);
3211 			goto end;
3212 		} else {
3213 
3214 			NOTICA("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=NULL, hint=%s)\n", SKYPOPEN_P_LOG, SKYPE_CHAT_PROTO,
3215 				   tech_pvt->skype_user, argv[1], "SIMPLE MESSAGE", switch_str_nil((char *) &cmd[strlen(argv[0]) + 1 + strlen(argv[1]) + 1]),
3216 				   tech_pvt->name);
3217 
3218 			compat_chat_send(SKYPE_CHAT_PROTO, tech_pvt->skype_user, argv[1], "SIMPLE MESSAGE",
3219 							 switch_str_nil((char *) &cmd[strlen(argv[0]) + 1 + strlen(argv[1]) + 1]), NULL, tech_pvt->name);
3220 
3221 		}
3222 	} else {
3223 		stream->write_function(stream, "ERROR, usage: %s", SKYPOPEN_CHAT_SYNTAX);
3224 		goto end;
3225 	}
3226 
3227   end:
3228 	switch_safe_free(mycmd);
3229 
3230 	return SWITCH_STATUS_SUCCESS;
3231 }
3232 
next_port(void)3233 int next_port(void)
3234 {
3235 	switch_mutex_lock(globals.mutex);
3236 	globals.start_port++;
3237 	if (globals.start_port == 65000)
3238 		globals.start_port = 32769;
3239 	switch_mutex_unlock(globals.mutex);
3240 	return (globals.start_port - 1);
3241 }
3242 
3243 #ifndef WIN32
3244 // CLOUDTREE (THomas Hazel) - is there a capable freeswitch list?
skypopen_list_add(struct SkypopenList * list,struct SkypopenHandles * handle)3245 struct SkypopenHandles *skypopen_list_add(struct SkypopenList *list, struct SkypopenHandles *handle)
3246 {
3247 	switch_mutex_lock(globals.list_mutex);
3248 
3249 	if (handle->managed == SWITCH_TRUE) {
3250 		// already added
3251 		switch_mutex_unlock(globals.list_mutex);
3252 		return 0;
3253 	}
3254 
3255 	if (list->head == 0) {
3256 		list->head = handle;
3257 		handle->prev = 0;
3258 
3259 	} else {
3260 		((struct SkypopenHandles *) list->tail)->next = handle;
3261 		((struct SkypopenHandles *) handle)->prev = list->tail;
3262 	}
3263 
3264 	list->tail = handle;
3265 	handle->next = 0;
3266 
3267 	handle->managed = SWITCH_TRUE;
3268 
3269 	list->entries++;
3270 
3271 	switch_mutex_unlock(globals.list_mutex);
3272 
3273 	return handle;
3274 }
3275 
3276 // CLOUDTREE (THomas Hazel) - is there a capable freeswitch list?
skypopen_list_remove_by_value(struct SkypopenList * list,Display * display)3277 struct SkypopenHandles *skypopen_list_remove_by_value(struct SkypopenList *list, Display * display)
3278 {
3279 	struct SkypopenHandles *iter;
3280 	struct SkypopenHandles *handle = 0;
3281 
3282 	switch_mutex_lock(globals.list_mutex);
3283 
3284 	iter = (struct SkypopenHandles *) list->head;
3285 	while (iter != 0) {
3286 		if (iter->disp == display) {
3287 			handle = iter;
3288 			break;
3289 		}
3290 
3291 		iter = (struct SkypopenHandles *) iter->next;
3292 	}
3293 
3294 	if ((handle != 0) && (handle->managed == SWITCH_TRUE)) {
3295 		if (handle->prev == 0) {
3296 			list->head = ((struct SkypopenHandles *) handle)->next;
3297 
3298 		} else {
3299 			((struct SkypopenHandles *) handle->prev)->next = ((struct SkypopenHandles *) handle)->next;
3300 		}
3301 
3302 		if (handle->next == 0) {
3303 			list->tail = ((struct SkypopenHandles *) handle)->prev;
3304 
3305 		} else {
3306 			((struct SkypopenHandles *) handle->next)->prev = ((struct SkypopenHandles *) handle)->prev;
3307 		}
3308 
3309 		handle->managed = SWITCH_FALSE;
3310 		handle->next = 0;
3311 		handle->prev = 0;
3312 
3313 		list->entries--;
3314 	}
3315 
3316 	switch_mutex_unlock(globals.list_mutex);
3317 
3318 	return handle;
3319 }
3320 
3321 // CLOUDTREE (THomas Hazel) - is there a capable freeswitch list?
skypopen_list_remove_by_reference(struct SkypopenList * list,struct SkypopenHandles * handle)3322 struct SkypopenHandles *skypopen_list_remove_by_reference(struct SkypopenList *list, struct SkypopenHandles *handle)
3323 {
3324 	private_t *tech_pvt = NULL;
3325 
3326 	switch_mutex_lock(globals.list_mutex);
3327 
3328 	DEBUGA_SKYPE("BEGIN REMOVE\n", SKYPOPEN_P_LOG);
3329 	if (handle->managed == SWITCH_FALSE) {
3330 		// already removed
3331 		switch_mutex_unlock(globals.list_mutex);
3332 		DEBUGA_SKYPE("EXIT REMOVE\n", SKYPOPEN_P_LOG);
3333 		return 0;
3334 	}
3335 
3336 	if (handle->prev == 0) {
3337 		list->head = ((struct SkypopenHandles *) handle)->next;
3338 
3339 	} else {
3340 		((struct SkypopenHandles *) handle->prev)->next = ((struct SkypopenHandles *) handle)->next;
3341 	}
3342 
3343 	if (handle->next == 0) {
3344 		list->tail = ((struct SkypopenHandles *) handle)->prev;
3345 
3346 	} else {
3347 		((struct SkypopenHandles *) handle->next)->prev = ((struct SkypopenHandles *) handle)->prev;
3348 	}
3349 
3350 	handle->managed = SWITCH_FALSE;
3351 	handle->next = 0;
3352 	handle->prev = 0;
3353 
3354 	list->entries--;
3355 
3356 	switch_mutex_unlock(globals.list_mutex);
3357 	DEBUGA_SKYPE("EXIT REMOVE\n", SKYPOPEN_P_LOG);
3358 
3359 	return handle;
3360 }
3361 
3362 // CLOUDTREE (THomas Hazel) - is there a capable freeswitch list?
3363 #ifdef XIO_ERROR_BY_UCONTEXT
skypopen_list_find(struct SkypopenList * list,struct SkypopenHandles * find)3364 struct SkypopenHandles *skypopen_list_find(struct SkypopenList *list, struct SkypopenHandles *find)
3365 {
3366 	struct SkypopenHandles *iter;
3367 	struct SkypopenHandles *handle = NULL;
3368 
3369 	switch_mutex_lock(globals.list_mutex);
3370 
3371 	iter = (struct SkypopenHandles *) list->head;
3372 	while (iter != NULL) {
3373 		if (iter == find) {
3374 			handle = iter;
3375 			break;
3376 		}
3377 
3378 		iter = (struct SkypopenHandles *) iter->next;
3379 	}
3380 
3381 	switch_mutex_unlock(globals.list_mutex);
3382 
3383 	return handle;
3384 }
3385 #endif
3386 
3387 // CLOUDTREE (THomas Hazel) - is there a capable freeswitch list?
skypopen_list_size(struct SkypopenList * list)3388 int skypopen_list_size(struct SkypopenList *list)
3389 {
3390 	return list->entries;
3391 }
3392 #endif /* NOT WIN32 */
3393 
3394 /* For Emacs:
3395  * Local Variables:
3396  * mode:c
3397  * indent-tabs-mode:t
3398  * tab-width:4
3399  * c-basic-offset:4
3400  * End:
3401  * For VIM:
3402  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
3403  */
3404