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