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 * skypopen_protocol.c -- Low Level Interface for mod_skypopen
31 *
32 */
33
34
35 #include "skypopen.h"
36
37 #ifdef ASTERISK
38 #define skypopen_sleep usleep
39 #define skypopen_strncpy strncpy
40 #define tech_pvt p
41 extern int skypopen_debug;
42 extern char *skypopen_console_active;
43 #else /* FREESWITCH */
44 #define skypopen_sleep switch_sleep
45 #define skypopen_strncpy switch_copy_string
46 extern switch_memory_pool_t *skypopen_module_pool;
47 extern switch_endpoint_interface_t *skypopen_endpoint_interface;
48 #endif /* ASTERISK */
49 int samplerate_skypopen = SAMPLERATE_SKYPOPEN;
50
51 extern int running;
52 extern char *interface_status[];
53 extern char *skype_callflow[];
54
55 /*************************************/
56 /* suspicious globals FIXME */
57 #ifdef WIN32
58 DWORD win32_dwThreadId;
59 #else
60
61 // CLOUDTREE (Thomas Hazel)
62 static int global_x_error = Success;
63 extern struct SkypopenList global_handles_list;
64 extern switch_status_t remove_interface(char *the_interface, switch_bool_t force);
65
66 #endif /* WIN32 */
67 /*************************************/
68 #ifndef WIN32
skypopen_socket_create_and_bind(private_t * tech_pvt,int * which_port)69 int skypopen_socket_create_and_bind(private_t *tech_pvt, int *which_port)
70 #else
71 int skypopen_socket_create_and_bind(private_t *tech_pvt, unsigned short *which_port)
72 #endif //WIN32
73 {
74 int s = -1;
75 struct sockaddr_in my_addr;
76 #ifndef WIN32
77 int start_port = 6001;
78 unsigned int size = sizeof(int);
79 #else
80 unsigned short start_port = 6001;
81 int size = sizeof(int);
82 #endif //WIN32
83 int sockbufsize = 0;
84 int flag = 0;
85
86
87 memset(&my_addr, 0, sizeof(my_addr));
88 my_addr.sin_family = AF_INET;
89 my_addr.sin_addr.s_addr = htonl(0x7f000001); /* use the localhost */
90
91 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
92 ERRORA("socket Error\n", SKYPOPEN_P_LOG);
93 return -1;
94 }
95
96 if (*which_port != 0)
97 start_port = *which_port;
98 #ifdef WIN32
99 start_port = (unsigned short) next_port();
100 #else
101 start_port = (unsigned short) next_port();
102 #endif
103 my_addr.sin_port = htons(start_port);
104 *which_port = start_port;
105 while (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) {
106 DEBUGA_SKYPE("*which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPOPEN_P_LOG, *which_port, tech_pvt->tcp_cli_port,
107 tech_pvt->tcp_srv_port);
108 DEBUGA_SKYPE("bind errno=%d, error: %s\n", SKYPOPEN_P_LOG, errno, strerror(errno));
109 start_port++;
110 my_addr.sin_port = htons(start_port);
111 *which_port = start_port;
112 DEBUGA_SKYPE("*which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPOPEN_P_LOG, *which_port, tech_pvt->tcp_cli_port,
113 tech_pvt->tcp_srv_port);
114
115 if (start_port > 65000) {
116 ERRORA("NO MORE PORTS! *which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPOPEN_P_LOG, *which_port,
117 tech_pvt->tcp_cli_port, tech_pvt->tcp_srv_port);
118 return -1;
119 }
120 }
121
122 DEBUGA_SKYPE("Binded! *which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPOPEN_P_LOG, *which_port, tech_pvt->tcp_cli_port,
123 tech_pvt->tcp_srv_port);
124
125 sockbufsize = 0;
126 size = sizeof(int);
127 getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &sockbufsize, &size);
128 DEBUGA_SKYPE("1 SO_RCVBUF is %d, size is %d\n", SKYPOPEN_P_LOG, sockbufsize, size);
129 sockbufsize = 0;
130 size = sizeof(int);
131 getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *) &sockbufsize, &size);
132 DEBUGA_SKYPE("1 SO_SNDBUF is %d, size is %d\n", SKYPOPEN_P_LOG, sockbufsize, size);
133
134
135
136 #ifdef WIN32
137 sockbufsize = SAMPLES_PER_FRAME * 8;
138 #else
139 sockbufsize = SAMPLES_PER_FRAME * 8;
140 #endif //WIN32
141 size = sizeof(int);
142 if (tech_pvt->setsockopt) {
143 setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &sockbufsize, size);
144 }
145
146 sockbufsize = 0;
147 size = sizeof(int);
148 getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &sockbufsize, &size);
149 DEBUGA_SKYPE("2 SO_RCVBUF is %d, size is %d\n", SKYPOPEN_P_LOG, sockbufsize, size);
150
151 #ifdef WIN32
152 sockbufsize = SAMPLES_PER_FRAME * 8;
153 #else
154 sockbufsize = SAMPLES_PER_FRAME * 8;
155 #endif //WIN32
156 size = sizeof(int);
157 if (tech_pvt->setsockopt) {
158 setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *) &sockbufsize, size);
159 }
160
161 sockbufsize = 0;
162 size = sizeof(int);
163 getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *) &sockbufsize, &size);
164 DEBUGA_SKYPE("2 SO_SNDBUF is %d, size is %d\n", SKYPOPEN_P_LOG, sockbufsize, size);
165
166 flag = 0;
167 getsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, &size);
168 DEBUGA_SKYPE("TCP_NODELAY is %d\n", SKYPOPEN_P_LOG, flag);
169 flag = 1;
170 if (tech_pvt->setsockopt) {
171 setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, size);
172 }
173 flag = 0;
174 getsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, &size);
175 DEBUGA_SKYPE("TCP_NODELAY is %d\n", SKYPOPEN_P_LOG, flag);
176
177
178
179
180 return s;
181 }
182
skypopen_signaling_read(private_t * tech_pvt)183 int skypopen_signaling_read(private_t *tech_pvt)
184 {
185 char read_from_pipe[4096];
186 char message[4096];
187 char message_2[4096];
188 char *buf, obj[512] = "", id[512] = "", prop[512] = "", value[512] = "", *where;
189 char **stringp = NULL;
190 int a;
191 unsigned int howmany;
192 unsigned int i;
193
194 memset(read_from_pipe, 0, 4096);
195 memset(message, 0, 4096);
196 memset(message_2, 0, 4096);
197
198 howmany = skypopen_pipe_read(tech_pvt->SkypopenHandles.fdesc[0], (short *) read_from_pipe, sizeof(read_from_pipe));
199
200 a = 0;
201 for (i = 0; i < howmany; i++) {
202 message[a] = read_from_pipe[i];
203 a++;
204
205 if (read_from_pipe[i] == '\0') {
206 //if (!strstr(message, "DURATION")) {
207 DEBUGA_SKYPE("READING: |||%s||| \n", SKYPOPEN_P_LOG, message);
208 strncpy(tech_pvt->message, message, sizeof(tech_pvt->message));
209 //}
210 if (!strcasecmp(message, "SILENT_MODE OFF")) {
211 if (tech_pvt->silent_mode) {
212 DEBUGA_SKYPE("Resetting SILENT_MODE on skype_call: %s.\n", SKYPOPEN_P_LOG, id);
213 skypopen_signaling_write(tech_pvt, "SET SILENT_MODE ON");
214 //switch_sleep(1000);
215 }
216 }
217 if (!strcasecmp(message, "ERROR 68")) {
218 DEBUGA_SKYPE
219 ("If I don't connect immediately, please give the Skype client authorization to be connected by Skypopen (and to not ask you again)\n",
220 SKYPOPEN_P_LOG);
221 skypopen_sleep(1000000);
222 skypopen_signaling_write(tech_pvt, "PROTOCOL 999");
223 skypopen_sleep(20000);
224 return 0;
225 }
226 if (!strncasecmp(message, "ERROR 92 CALL", 12)) {
227 ERRORA("Skype got ERROR: |||%s|||, the (skypeout) number we called was not recognized as valid\n", SKYPOPEN_P_LOG, message);
228 tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED;
229 DEBUGA_SKYPE("skype_call now is DOWN\n", SKYPOPEN_P_LOG);
230 tech_pvt->skype_call_id[0] = '\0';
231
232 if (tech_pvt->interface_state != SKYPOPEN_STATE_HANGUP_REQUESTED) {
233 tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
234 return CALLFLOW_INCOMING_HANGUP;
235 } else {
236 tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
237 }
238 }
239
240 if (!strncasecmp(message, "ERROR", 4)) {
241 if (!strncasecmp(message, "ERROR 96 CALL", 12)) {
242 DEBUGA_SKYPE
243 ("Skype got ERROR: |||%s|||, we are trying to use this interface to make or receive a call, but another call is half-active on this interface. Let's the previous one to continue.\n",
244 SKYPOPEN_P_LOG, message);
245 } else if (!strncasecmp(message, "ERROR 99 CALL", 12)) {
246 DEBUGA_SKYPE("Skype got ERROR: |||%s|||, another call is active on this interface\n\n\n", SKYPOPEN_P_LOG, message);
247 tech_pvt->interface_state = SKYPOPEN_STATE_ERROR_DOUBLE_CALL;
248 } else if (!strncasecmp(message, "ERROR 531 VOICEMAIL", 18)) {
249 NOTICA("Skype got ERROR about VOICEMAIL, no problem: |||%s|||\n", SKYPOPEN_P_LOG, message);
250 } else if (!strncasecmp(message, "ERROR 529 VOICEMAIL", 18)) {
251 NOTICA("Skype got ERROR about VOICEMAIL, no problem: |||%s|||\n", SKYPOPEN_P_LOG, message);
252 } else if (!strncasecmp(message, "ERROR 592 ALTER CALL", 19)) {
253 NOTICA("Skype got ERROR about TRANSFERRING, no problem: |||%s|||\n", SKYPOPEN_P_LOG, message);
254 } else if (!strncasecmp(message, "ERROR 559 CALL", 13) | !strncasecmp(message, "ERROR 556 CALL", 13)) {
255 if (tech_pvt->interface_state == SKYPOPEN_STATE_PREANSWER) {
256 DEBUGA_SKYPE("Skype got ERROR about a failed action (probably TRYING to ANSWER A CALL), let's go down: |||%s|||\n", SKYPOPEN_P_LOG,
257 message);
258 tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED;
259 DEBUGA_SKYPE("skype_call now is DOWN\n", SKYPOPEN_P_LOG);
260 tech_pvt->skype_call_id[0] = '\0';
261 tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
262 return CALLFLOW_INCOMING_HANGUP;
263
264 } else {
265 DEBUGA_SKYPE("Skype got ERROR about a failed action (probably TRYING to HANGUP A CALL), no problem: |||%s|||\n", SKYPOPEN_P_LOG,
266 message);
267 }
268 } else if (!strncasecmp(message, "ERROR 36 Not online", 18)) {
269 char msg_to_skype[256];
270 ERRORA("Skype client is not online, eg: not connected to Skype network, probably got a temporary net outage: |||%s|||\n",
271 SKYPOPEN_P_LOG, message);
272 if (strlen(tech_pvt->skype_call_id)) {
273 sprintf(msg_to_skype, "ALTER CALL %s HANGUP", tech_pvt->skype_call_id);
274 skypopen_signaling_write(tech_pvt, msg_to_skype);
275 }
276 if (strlen(tech_pvt->ring_id)) {
277 sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", tech_pvt->ring_id);
278 skypopen_signaling_write(tech_pvt, msg_to_skype);
279 }
280 tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
281 return CALLFLOW_INCOMING_HANGUP;
282 } else if (!strncasecmp(message, "ERROR 589 ALTER CALL", 19)) {
283 char msg_to_skype[256];
284 DEBUGA_SKYPE("Skype client was not able to correctly manage tcp audio sockets, probably got a local or remote hangup: |||%s|||\n",
285 SKYPOPEN_P_LOG, message);
286 if (strlen(tech_pvt->skype_call_id)) {
287 sprintf(msg_to_skype, "ALTER CALL %s HANGUP", tech_pvt->skype_call_id);
288 skypopen_signaling_write(tech_pvt, msg_to_skype);
289 }
290 if (strlen(tech_pvt->ring_id)) {
291 sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", tech_pvt->ring_id);
292 skypopen_signaling_write(tech_pvt, msg_to_skype);
293 }
294 tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
295 return CALLFLOW_INCOMING_HANGUP;
296 } else {
297 ERRORA("Skype got ERROR: |||%s|||\n", SKYPOPEN_P_LOG, message);
298 tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED;
299 ERRORA("skype_call now is DOWN\n", SKYPOPEN_P_LOG);
300 tech_pvt->skype_call_id[0] = '\0';
301
302 if (tech_pvt->interface_state != SKYPOPEN_STATE_HANGUP_REQUESTED) {
303 tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
304 return CALLFLOW_INCOMING_HANGUP;
305 } else {
306 tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
307 }
308 }
309 }
310
311 skypopen_strncpy(message_2, message, sizeof(message) - 1);
312 buf = message;
313 stringp = &buf;
314 where = strsep(stringp, " ");
315 if (!where) {
316 WARNINGA("Skype MSG without spaces: %s\n", SKYPOPEN_P_LOG, message);
317 }
318
319 if (!strcasecmp(message, "CURRENTUSERHANDLE")) {
320 skypopen_strncpy(obj, where, sizeof(obj) - 1);
321 where = strsep(stringp, " ");
322 skypopen_strncpy(id, where, sizeof(id) - 1);
323 if (!strcasecmp(id, tech_pvt->skype_user)) {
324 tech_pvt->SkypopenHandles.currentuserhandle = 1;
325 DEBUGA_SKYPE
326 ("Skype MSG: message: %s, currentuserhandle: %s, cuh: %s, skype_user: %s!\n",
327 SKYPOPEN_P_LOG, message, obj, id, tech_pvt->skype_user);
328 }
329 }
330 if (!strcasecmp(message, "USER")) {
331 skypopen_strncpy(obj, where, sizeof(obj) - 1);
332 where = strsep(stringp, " ");
333 skypopen_strncpy(id, where, sizeof(id) - 1);
334 where = strsep(stringp, " ");
335 skypopen_strncpy(prop, where, sizeof(prop) - 1);
336 if (!strcasecmp(prop, "RECEIVEDAUTHREQUEST")) {
337 char msg_to_skype[256];
338 DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n", SKYPOPEN_P_LOG, message, obj, id, prop);
339 sprintf(msg_to_skype, "SET USER %s ISAUTHORIZED TRUE", id);
340 skypopen_signaling_write(tech_pvt, msg_to_skype);
341 }
342 }
343 if (!strcasecmp(message, "MESSAGE")) {
344 skypopen_strncpy(obj, where, sizeof(obj) - 1);
345 where = strsep(stringp, " ");
346 skypopen_strncpy(id, where, sizeof(id) - 1);
347 where = strsep(stringp, " ");
348 skypopen_strncpy(prop, where, sizeof(prop) - 1);
349 if (!strcasecmp(prop, "STATUS")) {
350 where = strsep(stringp, " ");
351 skypopen_strncpy(value, where, sizeof(value) - 1);
352 if (!strcasecmp(value, "RECEIVED")) {
353 char msg_to_skype[256];
354 DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s value: %s!\n", SKYPOPEN_P_LOG, message, obj, id, prop, value);
355 //TODO: authomatically flag messages as read based on config param
356 sprintf(msg_to_skype, "SET MESSAGE %s SEEN", id);
357 skypopen_signaling_write(tech_pvt, msg_to_skype);
358 }
359 } else if (!strcasecmp(prop, "BODY")) {
360 char msg_to_skype[256];
361 DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n", SKYPOPEN_P_LOG, message, obj, id, prop);
362 //TODO: authomatically flag messages as read based on config param
363 sprintf(msg_to_skype, "SET MESSAGE %s SEEN", id);
364 skypopen_signaling_write(tech_pvt, msg_to_skype);
365 }
366 }
367 if (!strcasecmp(message, "CHAT")) {
368 char msg_to_skype[256];
369 int i;
370 int found;
371
372 skypopen_strncpy(obj, where, sizeof(obj) - 1);
373 where = strsep(stringp, " ");
374 skypopen_strncpy(id, where, sizeof(id) - 1);
375 where = strsep(stringp, " ");
376 skypopen_strncpy(prop, where, sizeof(prop) - 1);
377 skypopen_strncpy(value, *stringp, sizeof(value) - 1);
378
379 if (!strcasecmp(prop, "STATUS") && !strcasecmp(value, "DIALOG")) {
380 DEBUGA_SKYPE("CHAT %s is DIALOG\n", SKYPOPEN_P_LOG, id);
381 sprintf(msg_to_skype, "GET CHAT %s DIALOG_PARTNER", id);
382 skypopen_signaling_write(tech_pvt, msg_to_skype);
383 }
384
385 if (!strcasecmp(prop, "DIALOG_PARTNER")) {
386 DEBUGA_SKYPE("CHAT %s has DIALOG_PARTNER %s\n", SKYPOPEN_P_LOG, id, value);
387 found = 0;
388 for (i = 0; i < MAX_CHATS; i++) {
389 if (strlen(tech_pvt->chats[i].chatname) == 0 || !strcmp(tech_pvt->chats[i].chatname, id)) {
390 strncpy(tech_pvt->chats[i].chatname, id, sizeof(tech_pvt->chats[i].chatname));
391 strncpy(tech_pvt->chats[i].dialog_partner, value, sizeof(tech_pvt->chats[i].dialog_partner));
392 found = 1;
393 break;
394 }
395 }
396 if (!found) {
397 ERRORA("why we do not have a chats slot free? we have more than %d chats in parallel?\n", SKYPOPEN_P_LOG, MAX_CHATS);
398 }
399
400 DEBUGA_SKYPE("CHAT %s is in position %d in the chats array, chatname=%s, dialog_partner=%s\n", SKYPOPEN_P_LOG, id, i,
401 tech_pvt->chats[i].chatname, tech_pvt->chats[i].dialog_partner);
402 }
403
404 }
405
406
407 if (!strcasecmp(message, "CHATMESSAGE")) {
408 char msg_to_skype[256];
409 int i;
410 int found;
411
412 skypopen_strncpy(obj, where, sizeof(obj) - 1);
413 where = strsep(stringp, " ");
414 skypopen_strncpy(id, where, sizeof(id) - 1);
415 where = strsep(stringp, " ");
416 skypopen_strncpy(prop, where, sizeof(prop) - 1);
417 skypopen_strncpy(value, *stringp, sizeof(value) - 1);
418
419 if (!tech_pvt->report_incoming_chatmessages) {
420 if (!strcasecmp(prop, "STATUS") && !strcasecmp(value, "RECEIVED")) {
421 sprintf(msg_to_skype, "SET CHATMESSAGE %s SEEN", id);
422 skypopen_signaling_write(tech_pvt, msg_to_skype);
423 }
424 } else {
425 if (!strcasecmp(prop, "STATUS") && !strcasecmp(value, "RECEIVED")) {
426 DEBUGA_SKYPE("RECEIVED CHATMESSAGE %s, let's see which type it is\n", SKYPOPEN_P_LOG, id);
427 sprintf(msg_to_skype, "GET CHATMESSAGE %s TYPE", id);
428 skypopen_signaling_write(tech_pvt, msg_to_skype);
429 }
430
431 if (!strcasecmp(prop, "TYPE") && !strcasecmp(value, "SAID")) {
432 DEBUGA_SKYPE("CHATMESSAGE %s is of type SAID, let's get the other infos\n", SKYPOPEN_P_LOG, id);
433 found = 0;
434 for (i = 0; i < MAX_CHATMESSAGES; i++) {
435 if (strlen(tech_pvt->chatmessages[i].id) == 0) {
436 strncpy(tech_pvt->chatmessages[i].id, id, sizeof(tech_pvt->chatmessages[i].id));
437 strncpy(tech_pvt->chatmessages[i].type, value, sizeof(tech_pvt->chatmessages[i].type));
438 found = 1;
439 break;
440 }
441 }
442 if (!found) {
443 ERRORA("why we do not have a chatmessages slot free? we have more than %d chatmessages in parallel?\n", SKYPOPEN_P_LOG,
444 MAX_CHATMESSAGES);
445 } else {
446 DEBUGA_SKYPE("CHATMESSAGE %s is in position %d in the chatmessages array, type=%s, id=%s\n", SKYPOPEN_P_LOG, id, i,
447 tech_pvt->chatmessages[i].type, tech_pvt->chatmessages[i].id);
448 sprintf(msg_to_skype, "GET CHATMESSAGE %s CHATNAME", id);
449 skypopen_signaling_write(tech_pvt, msg_to_skype);
450 //skypopen_sleep(1000);
451 sprintf(msg_to_skype, "GET CHATMESSAGE %s FROM_HANDLE", id);
452 skypopen_signaling_write(tech_pvt, msg_to_skype);
453 //skypopen_sleep(1000);
454 sprintf(msg_to_skype, "GET CHATMESSAGE %s FROM_DISPNAME", id);
455 skypopen_signaling_write(tech_pvt, msg_to_skype);
456 //skypopen_sleep(1000);
457 sprintf(msg_to_skype, "GET CHATMESSAGE %s BODY", id);
458 skypopen_signaling_write(tech_pvt, msg_to_skype);
459 }
460 }
461
462 if (!strcasecmp(prop, "CHATNAME")) {
463 DEBUGA_SKYPE("CHATMESSAGE %s belongs to the CHAT %s\n", SKYPOPEN_P_LOG, id, value);
464 found = 0;
465 for (i = 0; i < MAX_CHATMESSAGES; i++) {
466 if (!strcmp(tech_pvt->chatmessages[i].id, id)) {
467 strncpy(tech_pvt->chatmessages[i].chatname, value, sizeof(tech_pvt->chatmessages[i].chatname));
468 found = 1;
469 break;
470 }
471 }
472 if (!found) {
473 DEBUGA_SKYPE("why chatmessage %s was not found in the chatmessages array??\n", SKYPOPEN_P_LOG, id);
474 }
475 }
476 if (!strcasecmp(prop, "FROM_HANDLE")) {
477 DEBUGA_SKYPE("CHATMESSAGE %s was sent by FROM_HANDLE %s\n", SKYPOPEN_P_LOG, id, value);
478 found = 0;
479 for (i = 0; i < MAX_CHATMESSAGES; i++) {
480 if (!strcmp(tech_pvt->chatmessages[i].id, id)) {
481 strncpy(tech_pvt->chatmessages[i].from_handle, value, sizeof(tech_pvt->chatmessages[i].from_handle));
482 found = 1;
483 break;
484 }
485 }
486 if (!found) {
487 DEBUGA_SKYPE("why chatmessage %s was not found in the chatmessages array??\n", SKYPOPEN_P_LOG, id);
488 }
489
490 }
491 if (!strcasecmp(prop, "FROM_DISPNAME")) {
492 DEBUGA_SKYPE("CHATMESSAGE %s was sent by FROM_DISPNAME %s\n", SKYPOPEN_P_LOG, id, value);
493 found = 0;
494 for (i = 0; i < MAX_CHATMESSAGES; i++) {
495 if (!strcmp(tech_pvt->chatmessages[i].id, id)) {
496 strncpy(tech_pvt->chatmessages[i].from_dispname, value, sizeof(tech_pvt->chatmessages[i].from_dispname));
497 found = 1;
498 break;
499 }
500 }
501 if (!found) {
502 DEBUGA_SKYPE("why chatmessage %s was not found in the chatmessages array??\n", SKYPOPEN_P_LOG, id);
503 }
504
505 }
506 if (!strcasecmp(prop, "BODY")) {
507 DEBUGA_SKYPE("CHATMESSAGE %s has BODY %s\n", SKYPOPEN_P_LOG, id, value);
508 found = 0;
509 for (i = 0; i < MAX_CHATMESSAGES; i++) {
510 if (!strcmp(tech_pvt->chatmessages[i].id, id)) {
511 strncpy(tech_pvt->chatmessages[i].body, value, sizeof(tech_pvt->chatmessages[i].body));
512 found = 1;
513 break;
514 }
515 }
516 if (!found) {
517 DEBUGA_SKYPE("why chatmessage %s was not found in the chatmessages array??\n", SKYPOPEN_P_LOG, id);
518 } else {
519 DEBUGA_SKYPE
520 ("CHATMESSAGE %s is in position %d in the chatmessages array, type=%s, id=%s, chatname=%s, from_handle=%s, from_dispname=%s, body=%s\n",
521 SKYPOPEN_P_LOG, id, i, tech_pvt->chatmessages[i].type, tech_pvt->chatmessages[i].id, tech_pvt->chatmessages[i].chatname,
522 tech_pvt->chatmessages[i].from_handle, tech_pvt->chatmessages[i].from_dispname, tech_pvt->chatmessages[i].body);
523 if (strcmp(tech_pvt->chatmessages[i].from_handle, tech_pvt->skype_user)) { //if the message was not sent by myself
524 incoming_chatmessage(tech_pvt, i);
525 memset(&tech_pvt->chatmessages[i], '\0', sizeof(tech_pvt->chatmessages[i]));
526
527 sprintf(msg_to_skype, "SET CHATMESSAGE %s SEEN", id);
528 skypopen_signaling_write(tech_pvt, msg_to_skype);
529 } else {
530 DEBUGA_SKYPE
531 ("CHATMESSAGE %s is in position %d in the chatmessages array, type=%s, id=%s, chatname=%s, from_handle=%s, from_dispname=%s, body=%s NOT DELETED\n",
532 SKYPOPEN_P_LOG, id, i, tech_pvt->chatmessages[i].type, tech_pvt->chatmessages[i].id, tech_pvt->chatmessages[i].chatname,
533 tech_pvt->chatmessages[i].from_handle, tech_pvt->chatmessages[i].from_dispname, tech_pvt->chatmessages[i].body);
534 memset(&tech_pvt->chatmessages[i], '\0', sizeof(tech_pvt->chatmessages[i]));
535 DEBUGA_SKYPE("chatmessage %s HAS BEEN DELETED\n", SKYPOPEN_P_LOG, id);
536 }
537
538 }
539
540 }
541 }
542
543 }
544
545
546 if (!strcasecmp(message, "VOICEMAIL")) {
547 char msg_to_skype[1024];
548
549 skypopen_strncpy(obj, where, sizeof(obj) - 1);
550 where = strsep(stringp, " ");
551 skypopen_strncpy(id, where, sizeof(id) - 1);
552 where = strsep(stringp, " ");
553 skypopen_strncpy(prop, where, sizeof(prop) - 1);
554 where = strsep(stringp, " ");
555 skypopen_strncpy(value, where, sizeof(value) - 1);
556 where = strsep(stringp, " ");
557
558 //DEBUGA_SKYPE
559 //("Skype MSG: message: %s, obj: %s, id: %s, prop: %s, value: %s,where: %s!\n",
560 //SKYPOPEN_P_LOG, message, obj, id, prop, value, where ? where : "NULL");
561
562 if (!strcasecmp(prop, "STATUS") && !strcasecmp(value, "RECORDING") ) {
563 DEBUGA_SKYPE("VOICEMAIL %s INPUT\n", SKYPOPEN_P_LOG, id);
564 sprintf(msg_to_skype, "ALTER VOICEMAIL %s SET_INPUT PORT=\"%d\"", id, tech_pvt->tcp_cli_port);
565 skypopen_signaling_write(tech_pvt, msg_to_skype);
566 } else if (!strcasecmp(prop, "STATUS") && !strcasecmp(value, "PLAYING") ) {
567 DEBUGA_SKYPE("VOICEMAIL %s OUTPUT\n", SKYPOPEN_P_LOG, id);
568 sprintf(msg_to_skype, "ALTER VOICEMAIL %s SET_OUTPUT PORT=\"%d\"", id, tech_pvt->tcp_srv_port);
569 skypopen_signaling_write(tech_pvt, msg_to_skype);
570 sprintf(tech_pvt->skype_voicemail_id_greeting, "%s", id);
571
572 } else if (!strcasecmp(prop, "TYPE") && !strcasecmp(value, "OUTGOING") ) {
573 DEBUGA_SKYPE("VOICEMAIL OUTGOING id is %s\n", SKYPOPEN_P_LOG, id);
574 sprintf(tech_pvt->skype_voicemail_id, "%s", id);
575 } else if (!strcasecmp(prop, "STATUS") && !strcasecmp(value, "PLAYED") ) {
576 //switch_ivr_broadcast( tech_pvt->session_uuid_str, "gentones::%(500,0,800)",SMF_ECHO_ALEG|SMF_ECHO_BLEG);
577 switch_ivr_broadcast( tech_pvt->session_uuid_str, "gentones::%(500,0,800)",SMF_ECHO_BLEG);
578 memset(tech_pvt->skype_voicemail_id_greeting, '\0', sizeof(tech_pvt->skype_voicemail_id_greeting));
579
580 }
581 }
582
583 if (!strcasecmp(message, "CALL")) {
584 skypopen_strncpy(obj, where, sizeof(obj) - 1);
585 where = strsep(stringp, " ");
586 skypopen_strncpy(id, where, sizeof(id) - 1);
587 where = strsep(stringp, " ");
588 skypopen_strncpy(prop, where, sizeof(prop) - 1);
589 where = strsep(stringp, " ");
590 skypopen_strncpy(value, where, sizeof(value) - 1);
591 where = strsep(stringp, " ");
592
593 //DEBUGA_SKYPE
594 //("Skype MSG: message: %s, obj: %s, id: %s, prop: %s, value: %s,where: %s!\n",
595 //SKYPOPEN_P_LOG, message, obj, id, prop, value, where ? where : "NULL");
596
597 if (!strcasecmp(prop, "PARTNER_HANDLE")) {
598 if (tech_pvt->interface_state == SKYPOPEN_STATE_IDLE) {
599 /* we are NOT inside an active call */
600 DEBUGA_SKYPE("Call %s go to skypopen_partner_handle_ring\n", SKYPOPEN_P_LOG, id);
601 skypopen_strncpy(tech_pvt->ring_id, id, sizeof(tech_pvt->ring_id));
602 skypopen_strncpy(tech_pvt->ring_value, value, sizeof(tech_pvt->ring_value));
603 skypopen_strncpy(tech_pvt->answer_id, id, sizeof(tech_pvt->answer_id));
604 skypopen_strncpy(tech_pvt->answer_value, value, sizeof(tech_pvt->answer_value));
605 skypopen_partner_handle_ring(tech_pvt);
606 } else {
607 /* we are inside an active call */
608 if (!strcasecmp(tech_pvt->skype_call_id, id)) {
609 /* this is the call in which we are calling out */
610 DEBUGA_SKYPE("Call %s DO NOTHING\n", SKYPOPEN_P_LOG, id);
611 } else {
612 DEBUGA_SKYPE("Call %s TRY TRANSFER\n", SKYPOPEN_P_LOG, id);
613 skypopen_strncpy(tech_pvt->ring_id, id, sizeof(tech_pvt->ring_id));
614 skypopen_strncpy(tech_pvt->ring_value, value, sizeof(tech_pvt->ring_value));
615 skypopen_strncpy(tech_pvt->answer_id, id, sizeof(tech_pvt->answer_id));
616 skypopen_strncpy(tech_pvt->answer_value, value, sizeof(tech_pvt->answer_value));
617 skypopen_transfer(tech_pvt);
618 }
619 }
620 }
621 if (!strcasecmp(prop, "PARTNER_DISPNAME")) {
622 snprintf(tech_pvt->callid_name, sizeof(tech_pvt->callid_name) - 1, "%s%s%s", value, where ? " " : "", where ? where : "");
623 }
624 if (!strcasecmp(prop, "CONF_ID") && !strcasecmp(value, "0")) {
625 }
626 if (!strcasecmp(prop, "CONF_ID") && strcasecmp(value, "0")) {
627 DEBUGA_SKYPE("the skype_call %s is a conference call\n", SKYPOPEN_P_LOG, id);
628 }
629 if (!strcasecmp(prop, "DTMF")) {
630 DEBUGA_SKYPE("Call %s received a DTMF: %s\n", SKYPOPEN_P_LOG, id, value);
631 dtmf_received(tech_pvt, value);
632 }
633 if (!strcasecmp(prop, "FAILUREREASON")) {
634 DEBUGA_SKYPE("Skype FAILED on skype_call %s. Let's wait for the FAILED message.\n", SKYPOPEN_P_LOG, id);
635 }
636 #if 0
637 #ifndef WIN32
638 if (!strcasecmp(prop, "DURATION")) { /* each 20 seconds, we zero the buffers and sync the timers */
639 if (!((atoi(value) % 20))) {
640 if (tech_pvt->read_buffer) {
641 switch_mutex_lock(tech_pvt->mutex_audio_srv);
642 switch_buffer_zero(tech_pvt->read_buffer);
643 if (tech_pvt->timer_read.timer_interface && tech_pvt->timer_read.timer_interface->timer_next) {
644 switch_core_timer_sync(&tech_pvt->timer_read);
645 }
646 if (tech_pvt->timer_read_srv.timer_interface && tech_pvt->timer_read_srv.timer_interface->timer_next) {
647 switch_core_timer_sync(&tech_pvt->timer_read_srv);
648 }
649 switch_mutex_unlock(tech_pvt->mutex_audio_srv);
650 }
651
652 if (tech_pvt->write_buffer) {
653 switch_mutex_lock(tech_pvt->mutex_audio_cli);
654 switch_buffer_zero(tech_pvt->write_buffer);
655 if (tech_pvt->timer_write.timer_interface && tech_pvt->timer_write.timer_interface->timer_next) {
656 switch_core_timer_sync(&tech_pvt->timer_write);
657 }
658 switch_mutex_unlock(tech_pvt->mutex_audio_cli);
659 }
660 DEBUGA_SKYPE("Synching audio on skype_call: %s.\n", SKYPOPEN_P_LOG, id);
661 }
662 }
663 #endif //WIN32
664 #endif //0
665 if (!strcasecmp(prop, "DURATION") && (!strcasecmp(value, "1"))) {
666 if (strcasecmp(id, tech_pvt->skype_call_id)) {
667 skypopen_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
668 DEBUGA_SKYPE("We called a Skype contact and he answered us on skype_call: %s.\n", SKYPOPEN_P_LOG, id);
669 }
670 }
671
672 if (!strcasecmp(prop, "DURATION") && (tech_pvt->interface_state == SKYPOPEN_STATE_ERROR_DOUBLE_CALL)) {
673 char msg_to_skype[1024];
674 skypopen_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
675 WARNINGA("We are in a double call situation, trying to get out hanging up call id: %s.\n", SKYPOPEN_P_LOG, id);
676 sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
677 skypopen_signaling_write(tech_pvt, msg_to_skype);
678 sprintf(msg_to_skype, "ALTER CALL %s HANGUP", id);
679 skypopen_signaling_write(tech_pvt, msg_to_skype);
680 //skypopen_sleep(10000);
681 }
682
683
684 if (!strcasecmp(prop, "VM_DURATION") && (!strcasecmp(value, "0"))) {
685 char msg_to_skype[1024];
686
687 NOTICA("We called a Skype contact and he started Skype voicemail on our skype_call: %s.\n", SKYPOPEN_P_LOG, id);
688
689 if (!strlen(tech_pvt->session_uuid_str)) {
690 DEBUGA_SKYPE("no tech_pvt->session_uuid_str\n", SKYPOPEN_P_LOG);
691 }
692 if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
693 if (!strlen(tech_pvt->session_uuid_str) || !strlen(tech_pvt->skype_call_id)
694 || !strcasecmp(tech_pvt->skype_call_id, id)) {
695 skypopen_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
696 DEBUGA_SKYPE("skype_call: %s is now active\n", SKYPOPEN_P_LOG, id);
697
698 if (tech_pvt->skype_callflow != CALLFLOW_STATUS_EARLYMEDIA) {
699 tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS;
700 tech_pvt->interface_state = SKYPOPEN_STATE_UP;
701
702 if (tech_pvt->tcp_cli_thread == NULL) {
703 DEBUGA_SKYPE("START start_audio_threads\n", SKYPOPEN_P_LOG);
704 if (start_audio_threads(tech_pvt)) {
705 WARNINGA("start_audio_threads FAILED\n", SKYPOPEN_P_LOG);
706 return CALLFLOW_INCOMING_HANGUP;
707 }
708 }
709 }
710 tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS;
711 if (skypopen_answered(tech_pvt) != SWITCH_STATUS_SUCCESS) {
712 sprintf(msg_to_skype, "ALTER CALL %s HANGUP", id);
713 skypopen_signaling_write(tech_pvt, msg_to_skype);
714 }
715 } else {
716 DEBUGA_SKYPE("I'm on %s, skype_call %s is NOT MY call, ignoring\n", SKYPOPEN_P_LOG, tech_pvt->skype_call_id, id);
717 }
718 } else {
719 tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS;
720 DEBUGA_SKYPE("Back from REMOTEHOLD!\n", SKYPOPEN_P_LOG);
721 }
722 }
723
724 if (!strcasecmp(prop, "STATUS")) {
725
726 if (!strcasecmp(value, "RINGING")) {
727 char msg_to_skype[1024];
728 if (tech_pvt->interface_state == SKYPOPEN_STATE_IDLE) {
729 // CLOUDTREE (Thomas Hazel)
730 skypopen_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
731
732 /* we are NOT inside an active call */
733 DEBUGA_SKYPE("NO ACTIVE calls in this moment, skype_call %s is RINGING, to ask PARTNER_DISPNAME and PARTNER_HANDLE\n",
734 SKYPOPEN_P_LOG, id);
735 sprintf(msg_to_skype, "GET CALL %s PARTNER_DISPNAME", id);
736 skypopen_signaling_write(tech_pvt, msg_to_skype);
737 //skypopen_sleep(100);
738 sprintf(msg_to_skype, "GET CALL %s PARTNER_HANDLE", id);
739 skypopen_signaling_write(tech_pvt, msg_to_skype);
740 //skypopen_sleep(10000);
741 } else {
742 /* we are inside an active call */
743 if (!strcasecmp(tech_pvt->skype_call_id, id)) {
744 // CLOUDTREE (Thomas Hazel)
745 tech_pvt->ringing_state = SKYPOPEN_RINGING_PRE;
746
747 /* this is the call in which we are calling out */
748 tech_pvt->skype_callflow = CALLFLOW_STATUS_RINGING;
749 tech_pvt->interface_state = SKYPOPEN_STATE_RINGING;
750 skypopen_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
751 DEBUGA_SKYPE("Our remote party in skype_call %s is RINGING\n", SKYPOPEN_P_LOG, id);
752 if (remote_party_is_ringing(tech_pvt) != SWITCH_STATUS_SUCCESS) {
753 DEBUGA_SKYPE
754 ("We are getting the RINGING from a call we probably canceled, trying to get out hanging up call id: %s.\n",
755 SKYPOPEN_P_LOG, id);
756 sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
757 skypopen_signaling_write(tech_pvt, msg_to_skype);
758 sprintf(msg_to_skype, "ALTER CALL %s HANGUP", id);
759 skypopen_signaling_write(tech_pvt, msg_to_skype);
760 tech_pvt->skype_call_id[0] = '\0';
761 // CLOUDTREE (Thomas Hazel)
762 tech_pvt->ringing_state = SKYPOPEN_RINGING_INIT;
763 tech_pvt->skype_callflow = CALLFLOW_CALL_IDLE;
764 tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
765 DEBUGA_SKYPE("we're now DOWN\n", SKYPOPEN_P_LOG);
766 return CALLFLOW_INCOMING_HANGUP;
767
768 }
769 } else {
770 DEBUGA_SKYPE
771 ("We are in another call, but skype_call %s is RINGING on us, let's ask PARTNER_HANDLE, so maybe we'll TRANSFER\n",
772 SKYPOPEN_P_LOG, id);
773 sprintf(msg_to_skype, "GET CALL %s PARTNER_HANDLE", id);
774 skypopen_signaling_write(tech_pvt, msg_to_skype);
775 //skypopen_sleep(10000);
776 }
777 }
778 } else if (!strcasecmp(value, "EARLYMEDIA")) {
779 char msg_to_skype[1024];
780 tech_pvt->skype_callflow = CALLFLOW_STATUS_EARLYMEDIA;
781 tech_pvt->interface_state = SKYPOPEN_STATE_DIALING;
782 DEBUGA_SKYPE("Our remote party in skype_call %s is EARLYMEDIA\n", SKYPOPEN_P_LOG, id);
783 if (tech_pvt->tcp_cli_thread == NULL) {
784 DEBUGA_SKYPE("START start_audio_threads\n", SKYPOPEN_P_LOG);
785 if (start_audio_threads(tech_pvt)) {
786 ERRORA("start_audio_threads FAILED\n", SKYPOPEN_P_LOG);
787 return CALLFLOW_INCOMING_HANGUP;
788 }
789 }
790 //skypopen_sleep(1000);
791 sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"%d\"", id, tech_pvt->tcp_cli_port);
792 skypopen_signaling_write(tech_pvt, msg_to_skype);
793 //skypopen_sleep(1000);
794 sprintf(msg_to_skype, "#output ALTER CALL %s SET_OUTPUT PORT=\"%d\"", id, tech_pvt->tcp_srv_port);
795 skypopen_signaling_write(tech_pvt, msg_to_skype);
796
797 remote_party_is_early_media(tech_pvt);
798 } else if (!strcasecmp(value, "MISSED") || !strcasecmp(value, "FINISHED")) {
799 if (!strcasecmp(tech_pvt->skype_call_id, id)) {
800 DEBUGA_SKYPE("skype_call %s is MY call, now I'm going DOWN\n", SKYPOPEN_P_LOG, id);
801 if (tech_pvt->interface_state != SKYPOPEN_STATE_HANGUP_REQUESTED) {
802 return CALLFLOW_INCOMING_HANGUP;
803 } else {
804 tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
805 }
806 } else {
807 DEBUGA_SKYPE("skype_call %s is NOT MY call, ignoring\n", SKYPOPEN_P_LOG, id);
808 }
809
810 } else if (!strcasecmp(value, "CANCELLED")) {
811 tech_pvt->skype_callflow = CALLFLOW_STATUS_CANCELLED;
812 DEBUGA_SKYPE("we tried to call Skype on skype_call %s and Skype has now CANCELLED\n", SKYPOPEN_P_LOG, id);
813 tech_pvt->skype_call_id[0] = '\0';
814 if (tech_pvt->interface_state != SKYPOPEN_STATE_HANGUP_REQUESTED) {
815 tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
816 return CALLFLOW_INCOMING_HANGUP;
817 } else {
818 tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
819 }
820 } else if (!strcasecmp(value, "FAILED")) {
821 tech_pvt->skype_callflow = CALLFLOW_STATUS_FAILED;
822 DEBUGA_SKYPE("we tried to call Skype on skype_call %s and Skype has now FAILED\n", SKYPOPEN_P_LOG, id);
823 tech_pvt->skype_call_id[0] = '\0';
824 skypopen_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
825 tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
826 return CALLFLOW_INCOMING_HANGUP;
827 } else if (!strcasecmp(value, "REFUSED")) {
828 if (!strcasecmp(id, tech_pvt->skype_call_id)) {
829 /* this is the id of the call we are in, probably we generated it */
830 tech_pvt->skype_callflow = CALLFLOW_STATUS_REFUSED;
831 DEBUGA_SKYPE("we tried to call Skype on skype_call %s and Skype has now REFUSED\n", SKYPOPEN_P_LOG, id);
832 skypopen_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
833 tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
834 tech_pvt->skype_call_id[0] = '\0';
835 return CALLFLOW_INCOMING_HANGUP;
836 } else {
837 /* we're here because were us that refused an incoming call */
838 DEBUGA_SKYPE("we REFUSED skype_call %s\n", SKYPOPEN_P_LOG, id);
839 }
840 } else if (!strcasecmp(value, "TRANSFERRING")) {
841 DEBUGA_SKYPE("skype_call %s is transferring\n", SKYPOPEN_P_LOG, id);
842 } else if (!strcasecmp(value, "TRANSFERRED")) {
843 DEBUGA_SKYPE("skype_call %s has been transferred\n", SKYPOPEN_P_LOG, id);
844 } else if (!strcasecmp(value, "ROUTING")) {
845 tech_pvt->skype_callflow = CALLFLOW_STATUS_ROUTING;
846 tech_pvt->interface_state = SKYPOPEN_STATE_DIALING;
847 skypopen_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
848 DEBUGA_SKYPE("skype_call: %s is now ROUTING\n", SKYPOPEN_P_LOG, id);
849 } else if (!strcasecmp(value, "UNPLACED")) {
850 tech_pvt->skype_callflow = CALLFLOW_STATUS_UNPLACED;
851 tech_pvt->interface_state = SKYPOPEN_STATE_DIALING;
852 skypopen_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
853 DEBUGA_SKYPE("skype_call: %s is now UNPLACED\n", SKYPOPEN_P_LOG, id);
854 } else if (!strcasecmp(value, "INPROGRESS")) {
855 char msg_to_skype[1024];
856
857 if (!strlen(tech_pvt->session_uuid_str)) {
858 DEBUGA_SKYPE("no tech_pvt->session_uuid_str\n", SKYPOPEN_P_LOG);
859 }
860 if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
861 if (!strlen(tech_pvt->session_uuid_str) || !strlen(tech_pvt->skype_call_id)
862 || !strcasecmp(tech_pvt->skype_call_id, id)) {
863 skypopen_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
864 DEBUGA_SKYPE("skype_call: %s is now active\n", SKYPOPEN_P_LOG, id);
865
866 if (tech_pvt->skype_callflow != CALLFLOW_STATUS_EARLYMEDIA) {
867 tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS;
868 tech_pvt->interface_state = SKYPOPEN_STATE_UP;
869
870 if (tech_pvt->tcp_cli_thread == NULL) {
871 DEBUGA_SKYPE("START start_audio_threads\n", SKYPOPEN_P_LOG);
872 if (start_audio_threads(tech_pvt)) {
873 WARNINGA("start_audio_threads FAILED\n", SKYPOPEN_P_LOG);
874 return CALLFLOW_INCOMING_HANGUP;
875 }
876 }
877 //skypopen_sleep(1000);
878 sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"%d\"", id, tech_pvt->tcp_cli_port);
879 skypopen_signaling_write(tech_pvt, msg_to_skype);
880 //skypopen_sleep(1000);
881 sprintf(msg_to_skype, "#output ALTER CALL %s SET_OUTPUT PORT=\"%d\"", id, tech_pvt->tcp_srv_port);
882 skypopen_signaling_write(tech_pvt, msg_to_skype);
883 }
884 tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS;
885 if (skypopen_answered(tech_pvt) != SWITCH_STATUS_SUCCESS) {
886 sprintf(msg_to_skype, "ALTER CALL %s HANGUP", id);
887 skypopen_signaling_write(tech_pvt, msg_to_skype);
888 }
889 } else {
890 DEBUGA_SKYPE("I'm on %s, skype_call %s is NOT MY call, ignoring\n", SKYPOPEN_P_LOG, tech_pvt->skype_call_id, id);
891 }
892 } else {
893 tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS;
894 DEBUGA_SKYPE("Back from REMOTEHOLD!\n", SKYPOPEN_P_LOG);
895 }
896
897 } else if (!strcasecmp(value, "LOCALHOLD")) {
898 char msg_to_skype[256];
899 DEBUGA_SKYPE("skype_call: %s is now LOCALHOLD, let's hangup\n", SKYPOPEN_P_LOG, id);
900 sprintf(msg_to_skype, "ALTER CALL %s HANGUP", id);
901 skypopen_signaling_write(tech_pvt, msg_to_skype);
902 } else if (!strcasecmp(value, "REMOTEHOLD")) {
903 tech_pvt->skype_callflow = CALLFLOW_STATUS_REMOTEHOLD;
904 DEBUGA_SKYPE("skype_call: %s is now REMOTEHOLD\n", SKYPOPEN_P_LOG, id);
905
906 } else if (!strcasecmp(value, "BUSY")) {
907 tech_pvt->skype_callflow = CALLFLOW_STATUS_FAILED;
908 DEBUGA_SKYPE
909 ("we tried to call Skype on skype_call %s and remote party (destination) was BUSY. Our outbound call has failed\n",
910 SKYPOPEN_P_LOG, id);
911 skypopen_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
912 tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
913 tech_pvt->skype_call_id[0] = '\0';
914 //skypopen_sleep(1000);
915 return CALLFLOW_INCOMING_HANGUP;
916 } else if (!strcasecmp(value, "WAITING_REDIAL_COMMAND")) {
917 tech_pvt->skype_callflow = CALLFLOW_STATUS_FAILED;
918 DEBUGA_SKYPE
919 ("we tried to call Skype on skype_call %s and remote party (destination) has rejected us (WAITING_REDIAL_COMMAND). Our outbound call has failed\n",
920 SKYPOPEN_P_LOG, id);
921 skypopen_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
922 tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
923 tech_pvt->skype_call_id[0] = '\0';
924 //skypopen_sleep(1000);
925 return CALLFLOW_INCOMING_HANGUP;
926 } else if (!strncmp(value, "VM_", 2)) {
927 DEBUGA_SKYPE ("Our skype_call %s is in Skype voicemail: %s\n", SKYPOPEN_P_LOG, id, value);
928 } else {
929 WARNINGA("skype_call: %s, STATUS: %s is not recognized\n", SKYPOPEN_P_LOG, id, value);
930 }
931 } //STATUS
932 } //CALL
933 /* the "numbered" messages that follows are used by the directory application, not yet ported */
934 if (!strcasecmp(message, "#333")) {
935 memset(tech_pvt->skype_friends, 0, 4096);
936 skypopen_strncpy(tech_pvt->skype_friends, &message_2[11], 4095);
937 }
938 if (!strcasecmp(message, "#222")) {
939 memset(tech_pvt->skype_fullname, 0, 512);
940 skypopen_strncpy(tech_pvt->skype_fullname, &message_2[10], 511);
941 }
942 if (!strcasecmp(message, "#765")) {
943 memset(tech_pvt->skype_displayname, 0, 512);
944 skypopen_strncpy(tech_pvt->skype_displayname, &message_2[10], 511);
945 }
946 a = 0;
947 } //message end
948 } //read_from_pipe
949 return 0;
950 }
951
skypopen_do_tcp_srv_thread_func(void * obj)952 void *skypopen_do_tcp_srv_thread_func(void *obj)
953 {
954 private_t *tech_pvt = obj;
955 int s;
956 unsigned int len;
957 #if defined(WIN32) && !defined(__CYGWIN__)
958 int sin_size;
959 int size = sizeof(int);
960 #else /* WIN32 */
961 unsigned int sin_size;
962 unsigned int size = sizeof(int);
963 #endif /* WIN32 */
964 unsigned int fd;
965 short srv_in[SAMPLES_PER_FRAME * 10];
966 struct sockaddr_in remote_addr;
967 int sockbufsize = 0;
968
969 s = skypopen_socket_create_and_bind(tech_pvt, &tech_pvt->tcp_srv_port);
970 if (s < 0) {
971 ERRORA("skypopen_socket_create_and_bind error!\n", SKYPOPEN_P_LOG);
972 return NULL;
973 }
974 DEBUGA_SKYPE("started tcp_srv_thread thread.\n", SKYPOPEN_P_LOG);
975
976 listen(s, 6);
977
978 sin_size = sizeof(remote_addr);
979
980 while (tech_pvt && tech_pvt->interface_state != SKYPOPEN_STATE_DOWN
981 && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
982 || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
983 || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPOPEN_STATE_UP)) {
984
985 unsigned int fdselectgio;
986 int rtgio;
987 fd_set fsgio;
988 struct timeval togio;
989
990 if (!(running && tech_pvt->running))
991 break;
992 FD_ZERO(&fsgio);
993 togio.tv_usec = MS_SKYPOPEN * 1000;
994 togio.tv_sec = 0;
995 fdselectgio = s;
996 FD_SET(fdselectgio, &fsgio);
997
998 rtgio = select(fdselectgio + 1, &fsgio, NULL, NULL, &togio);
999
1000 if (rtgio) {
1001
1002 while (s > 0 && (fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) {
1003 DEBUGA_SKYPE("ACCEPTED here I send you %d\n", SKYPOPEN_P_LOG, tech_pvt->tcp_srv_port);
1004
1005 sockbufsize = 0;
1006 size = sizeof(int);
1007 getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &sockbufsize, &size);
1008 DEBUGA_SKYPE("3 SO_RCVBUF is %d, size is %d\n", SKYPOPEN_P_LOG, sockbufsize, size);
1009 sockbufsize = 0;
1010 size = sizeof(int);
1011 getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *) &sockbufsize, &size);
1012 DEBUGA_SKYPE("3 SO_SNDBUF is %d, size is %d\n", SKYPOPEN_P_LOG, sockbufsize, size);
1013
1014
1015 if (!(running && tech_pvt->running))
1016 break;
1017 while (tech_pvt && tech_pvt->interface_state != SKYPOPEN_STATE_DOWN
1018 && tech_pvt->interface_state != SKYPOPEN_STATE_IDLE
1019 && tech_pvt->interface_state != SKYPOPEN_STATE_HANGUP_REQUESTED
1020 && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
1021 || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
1022 || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPOPEN_STATE_UP)) {
1023
1024 unsigned int fdselect;
1025 int rt = 1;
1026 fd_set fs;
1027 struct timeval to;
1028 int nospace;
1029
1030 if (!(running && tech_pvt->running))
1031 break;
1032 #if 1
1033 fdselect = fd;
1034 FD_ZERO(&fs);
1035 FD_SET(fdselect, &fs);
1036 to.tv_usec = MS_SKYPOPEN * 1000 * 3;
1037 to.tv_sec = 0;
1038 #endif //0
1039
1040 if (tech_pvt->timer_read_srv.timer_interface && tech_pvt->timer_read_srv.timer_interface->timer_next) {
1041 switch_core_timer_next(&tech_pvt->timer_read_srv);
1042 } else {
1043 skypopen_sleep(20000);
1044
1045 }
1046 rt = select(fdselect + 1, &fs, NULL, NULL, &to);
1047 if (rt > 0) {
1048
1049 if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
1050 len = recv(fd, (char *) srv_in, BYTES_PER_FRAME * 2, 0);
1051 } else {
1052 //skypopen_sleep(10000);
1053 continue;
1054 }
1055 if (tech_pvt->begin_to_read == 0) {
1056 DEBUGA_SKYPE("len=%d\n", SKYPOPEN_P_LOG, len);
1057 //skypopen_sleep(10000);
1058 continue;
1059 }
1060
1061 if (len == -1) {
1062 DEBUGA_SKYPE("len=%d, error: %s\n", SKYPOPEN_P_LOG, len, strerror(errno));
1063 break;
1064 }
1065 nospace = 0;
1066 if (len > 0) {
1067 switch_mutex_lock(tech_pvt->mutex_audio_srv);
1068 if (tech_pvt->read_buffer) {
1069 if (switch_buffer_freespace(tech_pvt->read_buffer) < len) {
1070 switch_buffer_zero(tech_pvt->read_buffer);
1071 switch_buffer_write(tech_pvt->read_buffer, srv_in, len);
1072 nospace = 1;
1073 } else {
1074 switch_buffer_write(tech_pvt->read_buffer, srv_in, len);
1075 }
1076 }
1077 switch_mutex_unlock(tech_pvt->mutex_audio_srv);
1078 if (nospace) {
1079 DEBUGA_SKYPE("NO SPACE in READ BUFFER: there was no space for: %d\n", SKYPOPEN_P_LOG, len);
1080 }
1081 } else if (len == 0) {
1082 DEBUGA_SKYPE("CLOSED\n", SKYPOPEN_P_LOG);
1083 break;
1084 } else {
1085 DEBUGA_SKYPE("len=%d\n", SKYPOPEN_P_LOG, len);
1086 }
1087
1088 } else if (rt == 0) {
1089 continue;
1090 } else {
1091 DEBUGA_SKYPE("SRV rt=%d\n", SKYPOPEN_P_LOG, rt);
1092 break;
1093 }
1094
1095 }
1096
1097 DEBUGA_SKYPE("Skype incoming audio GONE\n", SKYPOPEN_P_LOG);
1098 tech_pvt->skype_callflow = CALLFLOW_INCOMING_HANGUP;
1099 skypopen_close_socket(fd);
1100 break;
1101 }
1102 break;
1103 }
1104 }
1105
1106 DEBUGA_SKYPE("incoming audio (read) server (I am it) EXITING\n", SKYPOPEN_P_LOG);
1107 skypopen_close_socket(s);
1108 s = -1;
1109 //DEBUGA_SKYPE("debugging_hangup PRE srv lock\n", SKYPOPEN_P_LOG);
1110 switch_mutex_lock(tech_pvt->mutex_thread_audio_srv);
1111 //DEBUGA_SKYPE("debugging_hangup srv lock\n", SKYPOPEN_P_LOG);
1112 tech_pvt->tcp_srv_thread = NULL;
1113 switch_mutex_unlock(tech_pvt->mutex_thread_audio_srv);
1114 //DEBUGA_SKYPE("debugging_hangup srv unlock\n", SKYPOPEN_P_LOG);
1115 return NULL;
1116 }
1117
skypopen_do_tcp_cli_thread_func(void * obj)1118 void *skypopen_do_tcp_cli_thread_func(void *obj)
1119 {
1120 private_t *tech_pvt = obj;
1121 int s;
1122 struct sockaddr_in remote_addr;
1123 unsigned int len;
1124 unsigned int fd;
1125 short cli_out[SAMPLES_PER_FRAME * 2 * 10];
1126 #ifdef WIN32
1127 int sin_size;
1128 int size = sizeof(int);
1129 #else
1130 unsigned int sin_size;
1131 unsigned int size = sizeof(int);
1132 #endif /* WIN32 */
1133 int sockbufsize = 0;
1134
1135 s = skypopen_socket_create_and_bind(tech_pvt, &tech_pvt->tcp_cli_port);
1136 if (s < 0) {
1137 ERRORA("skypopen_socket_create_and_bind error!\n", SKYPOPEN_P_LOG);
1138 return NULL;
1139 }
1140
1141
1142
1143 DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPOPEN_P_LOG);
1144
1145 listen(s, 6);
1146
1147 sin_size = sizeof(remote_addr);
1148
1149 while (tech_pvt && tech_pvt->interface_state != SKYPOPEN_STATE_DOWN
1150 && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
1151 || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
1152 || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPOPEN_STATE_UP)) {
1153
1154 unsigned int fdselectgio;
1155 int rtgio;
1156 fd_set fsgio;
1157 struct timeval togio;
1158
1159 if (!(running && tech_pvt->running))
1160 break;
1161 FD_ZERO(&fsgio);
1162 togio.tv_usec = MS_SKYPOPEN * 1000 * 3;
1163 togio.tv_sec = 0;
1164 fdselectgio = s;
1165 FD_SET(fdselectgio, &fsgio);
1166
1167 rtgio = select(fdselectgio + 1, &fsgio, NULL, NULL, &togio);
1168
1169 if (rtgio) {
1170
1171 while (s > 0 && (fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) {
1172 DEBUGA_SKYPE("ACCEPTED here you send me %d\n", SKYPOPEN_P_LOG, tech_pvt->tcp_cli_port);
1173
1174 sockbufsize = 0;
1175 size = sizeof(int);
1176 getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &sockbufsize, &size);
1177 DEBUGA_SKYPE("4 SO_RCVBUF is %d, size is %d\n", SKYPOPEN_P_LOG, sockbufsize, size);
1178 sockbufsize = 0;
1179 size = sizeof(int);
1180 getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *) &sockbufsize, &size);
1181 DEBUGA_SKYPE("4 SO_SNDBUF is %d, size is %d\n", SKYPOPEN_P_LOG, sockbufsize, size);
1182
1183
1184
1185 if (!(running && tech_pvt->running))
1186 break;
1187 while (tech_pvt && tech_pvt->interface_state != SKYPOPEN_STATE_DOWN
1188 && tech_pvt->interface_state != SKYPOPEN_STATE_IDLE
1189 && tech_pvt->interface_state != SKYPOPEN_STATE_HANGUP_REQUESTED
1190 && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
1191 || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
1192 || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPOPEN_STATE_UP)) {
1193 size_t bytes_to_write;
1194
1195 if (!(running && tech_pvt->running))
1196 break;
1197
1198 if (tech_pvt->timer_write.timer_interface && tech_pvt->timer_write.timer_interface->timer_next
1199 && tech_pvt->interface_state != SKYPOPEN_STATE_HANGUP_REQUESTED) {
1200 switch_core_timer_next(&tech_pvt->timer_write);
1201 } else {
1202 skypopen_sleep(20000);
1203 }
1204
1205 if (tech_pvt->begin_to_write == 0) {
1206 memset(cli_out, 255, sizeof(cli_out));
1207 bytes_to_write = BYTES_PER_FRAME;
1208 len = send(fd, (char *) cli_out, bytes_to_write, 0);
1209 if (len == -1) {
1210 DEBUGA_SKYPE("len=%d, error: %s\n", SKYPOPEN_P_LOG, len, strerror(errno));
1211 break;
1212 }
1213 //skypopen_sleep(10000);
1214 continue;
1215 } else {
1216
1217 bytes_to_write = 0;
1218
1219 if (tech_pvt->skype_callflow == CALLFLOW_INCOMING_HANGUP) {
1220 break;
1221 }
1222 switch_mutex_lock(tech_pvt->mutex_audio_cli);
1223 if (tech_pvt->write_buffer && switch_buffer_inuse(tech_pvt->write_buffer)) {
1224 bytes_to_write = switch_buffer_read(tech_pvt->write_buffer, cli_out, BYTES_PER_FRAME);
1225 }
1226 switch_mutex_unlock(tech_pvt->mutex_audio_cli);
1227
1228 if (!bytes_to_write) {
1229 if (tech_pvt->write_silence_when_idle) {
1230 memset(cli_out, 255, sizeof(cli_out));
1231 bytes_to_write = BYTES_PER_FRAME;
1232 //DEBUGA_SKYPE("WRITE Silence!\n", SKYPOPEN_P_LOG);
1233 } else {
1234 continue;
1235 }
1236 }
1237 /* send the 16khz frame to the Skype client waiting for incoming audio to be sent to the remote party */
1238 if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
1239 len = send(fd, (char *) cli_out, bytes_to_write, 0);
1240 if (len == -1) {
1241 DEBUGA_SKYPE("len=%d, error: %s\n", SKYPOPEN_P_LOG, len, strerror(errno));
1242 break;
1243 }
1244 if (len != bytes_to_write) {
1245 DEBUGA_SKYPE("len=%d\n", SKYPOPEN_P_LOG, len);
1246 }
1247 }
1248 }
1249
1250 }
1251 DEBUGA_SKYPE("Skype outbound audio GONE\n", SKYPOPEN_P_LOG);
1252 tech_pvt->skype_callflow = CALLFLOW_INCOMING_HANGUP;
1253 skypopen_close_socket(fd);
1254 break;
1255 }
1256 break;
1257 }
1258 }
1259
1260 DEBUGA_SKYPE("outbound audio server (I am it) EXITING\n", SKYPOPEN_P_LOG);
1261 skypopen_close_socket(s);
1262 s = -1;
1263 //DEBUGA_SKYPE("debugging_hangup PRE cli lock\n", SKYPOPEN_P_LOG);
1264 switch_mutex_lock(tech_pvt->mutex_thread_audio_cli);
1265 //DEBUGA_SKYPE("debugging_hangup cli lock\n", SKYPOPEN_P_LOG);
1266 tech_pvt->tcp_cli_thread = NULL;
1267 switch_mutex_unlock(tech_pvt->mutex_thread_audio_cli);
1268 //DEBUGA_SKYPE("debugging_hangup cli unlock\n", SKYPOPEN_P_LOG);
1269 return NULL;
1270 }
1271
skypopen_senddigit(private_t * tech_pvt,char digit)1272 int skypopen_senddigit(private_t *tech_pvt, char digit)
1273 {
1274 char msg_to_skype[1024];
1275
1276 DEBUGA_SKYPE("DIGIT received: %c\n", SKYPOPEN_P_LOG, digit);
1277 if (digit != 'a' && digit != 'A' && digit != 'b' && digit != 'B' && digit != 'c' && digit != 'C' && digit != 'd' && digit != 'D') {
1278 sprintf(msg_to_skype, "SET CALL %s DTMF %c", tech_pvt->skype_call_id, digit);
1279 skypopen_signaling_write(tech_pvt, msg_to_skype);
1280 } else {
1281 WARNINGA("Received DTMF DIGIT \"%c\", but not relayed to Skype client because Skype client accepts only 0-9*#\n", SKYPOPEN_P_LOG, digit);
1282 }
1283
1284 return 0;
1285 }
1286
skypopen_call(private_t * tech_pvt,char * rdest,int timeout)1287 int skypopen_call(private_t *tech_pvt, char *rdest, int timeout)
1288 {
1289 char msg_to_skype[1024];
1290
1291 DEBUGA_SKYPE("Calling Skype, rdest is: %s\n", SKYPOPEN_P_LOG, rdest);
1292
1293 sprintf(msg_to_skype, "CALL %s", rdest);
1294 if (skypopen_signaling_write(tech_pvt, msg_to_skype) < 0) {
1295 ERRORA("failed to communicate with Skype client, now exit\n", SKYPOPEN_P_LOG);
1296 return -1;
1297 }
1298 return 0;
1299 }
1300
1301 /***************************/
1302 /* PLATFORM SPECIFIC */
1303 /***************************/
1304 #if defined(WIN32) && !defined(__CYGWIN__)
skypopen_pipe_read(switch_file_t * pipe,short * buf,int howmany)1305 int skypopen_pipe_read(switch_file_t *pipe, short *buf, int howmany)
1306 {
1307 switch_size_t quantity;
1308
1309 quantity = howmany;
1310
1311 switch_file_read(pipe, buf, &quantity);
1312
1313 howmany = (int)quantity;
1314
1315 return howmany;
1316 }
1317
skypopen_pipe_write(switch_file_t * pipe,short * buf,int howmany)1318 int skypopen_pipe_write(switch_file_t *pipe, short *buf, int howmany)
1319 {
1320 switch_size_t quantity;
1321
1322 quantity = howmany;
1323
1324 switch_file_write(pipe, buf, &quantity);
1325
1326 howmany = (int)quantity;
1327
1328 return howmany;
1329 }
1330
skypopen_close_socket(unsigned int fd)1331 int skypopen_close_socket(unsigned int fd)
1332 {
1333 int res;
1334
1335 res = closesocket(fd);
1336
1337 return res;
1338 }
1339
skypopen_audio_init(private_t * tech_pvt)1340 int skypopen_audio_init(private_t *tech_pvt)
1341 {
1342 switch_status_t rv;
1343 rv = switch_file_pipe_create(&tech_pvt->audiopipe_srv[0], &tech_pvt->audiopipe_srv[1], skypopen_module_pool);
1344 rv = switch_file_pipe_create(&tech_pvt->audiopipe_cli[0], &tech_pvt->audiopipe_cli[1], skypopen_module_pool);
1345 return 0;
1346 }
1347 #else /* WIN32 */
skypopen_pipe_read(int pipe,short * buf,int howmany)1348 int skypopen_pipe_read(int pipe, short *buf, int howmany)
1349 {
1350 howmany = read(pipe, buf, howmany);
1351 return howmany;
1352 }
1353
skypopen_pipe_write(int pipe,short * buf,int howmany)1354 int skypopen_pipe_write(int pipe, short *buf, int howmany)
1355 {
1356 if (buf) {
1357 howmany = write(pipe, buf, howmany);
1358 return howmany;
1359 } else {
1360 return 0;
1361 }
1362 }
1363
skypopen_close_socket(unsigned int fd)1364 int skypopen_close_socket(unsigned int fd)
1365 {
1366 int res;
1367
1368 res = close(fd);
1369
1370 return res;
1371 }
1372
skypopen_audio_init(private_t * tech_pvt)1373 int skypopen_audio_init(private_t *tech_pvt)
1374 {
1375 if (pipe(tech_pvt->audiopipe_srv)) {
1376 fcntl(tech_pvt->audiopipe_srv[0], F_SETFL, O_NONBLOCK);
1377 fcntl(tech_pvt->audiopipe_srv[1], F_SETFL, O_NONBLOCK);
1378 }
1379 if (pipe(tech_pvt->audiopipe_cli)) {
1380 fcntl(tech_pvt->audiopipe_cli[0], F_SETFL, O_NONBLOCK);
1381 fcntl(tech_pvt->audiopipe_cli[1], F_SETFL, O_NONBLOCK);
1382 }
1383
1384 /* this pipe is the audio fd for asterisk to poll on during a call. FS do not use it */
1385 tech_pvt->skypopen_sound_capt_fd = tech_pvt->audiopipe_srv[0];
1386
1387 return 0;
1388 }
1389 #endif /* WIN32 */
1390
1391 #ifdef WIN32
1392
1393 enum {
1394 SKYPECONTROLAPI_ATTACH_SUCCESS = 0, /* Client is successfully
1395 attached and API window handle can be found
1396 in wParam parameter */
1397 SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION = 1, /* Skype has acknowledged
1398 connection request and is waiting
1399 for confirmation from the user. */
1400 /* The client is not yet attached
1401 * and should wait for SKYPECONTROLAPI_ATTACH_SUCCESS message */
1402 SKYPECONTROLAPI_ATTACH_REFUSED = 2, /* User has explicitly
1403 denied access to client */
1404 SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE = 3, /* API is not available
1405 at the moment.
1406 For example, this happens when no user
1407 is currently logged in. */
1408 /* Client should wait for
1409 * SKYPECONTROLAPI_ATTACH_API_AVAILABLE
1410 * broadcast before making any further */
1411 /* connection attempts. */
1412 SKYPECONTROLAPI_ATTACH_API_AVAILABLE = 0x8001
1413 };
1414
1415 /* Visual C do not have strsep? */
1416 char
strsep(char ** stringp,const char * delim)1417 *strsep(char **stringp, const char *delim)
1418 {
1419 char *res;
1420
1421 if (!stringp || !*stringp || !**stringp)
1422 return (char *) 0;
1423
1424 res = *stringp;
1425 while (**stringp && !strchr(delim, **stringp))
1426 ++(*stringp);
1427
1428 if (**stringp) {
1429 **stringp = '\0';
1430 ++(*stringp);
1431 }
1432
1433 return res;
1434 }
1435
skypopen_signaling_write(private_t * tech_pvt,char * msg_to_skype)1436 int skypopen_signaling_write(private_t *tech_pvt, char *msg_to_skype)
1437 {
1438 static char acInputRow[1024];
1439 COPYDATASTRUCT oCopyData;
1440
1441 DEBUGA_SKYPE("SENDING: |||%s||||\n", SKYPOPEN_P_LOG, msg_to_skype);
1442
1443 sprintf(acInputRow, "%s", msg_to_skype);
1444 /* send command to skype */
1445 oCopyData.dwData = 0;
1446 oCopyData.lpData = acInputRow;
1447 oCopyData.cbData = strlen(acInputRow) + 1;
1448 if (oCopyData.cbData != 1) {
1449 if (SendMessage
1450 (tech_pvt->SkypopenHandles.win32_hGlobal_SkypeAPIWindowHandle, WM_COPYDATA,
1451 (WPARAM) tech_pvt->SkypopenHandles.win32_hInit_MainWindowHandle, (LPARAM) & oCopyData) == FALSE) {
1452 ERRORA("Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypopen, then launch Skypopen and try again.\n", SKYPOPEN_P_LOG);
1453 return -1;
1454 }
1455 }
1456
1457 return 0;
1458
1459 }
1460
skypopen_present(HWND hWindow,UINT uiMessage,WPARAM uiParam,LPARAM ulParam)1461 LRESULT APIENTRY skypopen_present(HWND hWindow, UINT uiMessage, WPARAM uiParam, LPARAM ulParam)
1462 {
1463 LRESULT lReturnCode;
1464 int fIssueDefProc;
1465 private_t *tech_pvt = NULL;
1466
1467 lReturnCode = 0;
1468 fIssueDefProc = 0;
1469 tech_pvt = (private_t *)(intptr_t) GetWindowLong(hWindow, GWLP_USERDATA);
1470
1471 if (!running) {
1472 DEBUGA_SKYPE("let's DIE!\n", SKYPOPEN_P_LOG);
1473 tech_pvt->SkypopenHandles.win32_hInit_MainWindowHandle = NULL;
1474 PostQuitMessage(0);
1475 return lReturnCode;
1476 }
1477 switch (uiMessage) {
1478 case WM_CREATE:
1479 tech_pvt = (private_t *) ((LPCREATESTRUCT) ulParam)->lpCreateParams;
1480 SetWindowLong(hWindow, GWLP_USERDATA, (LONG) (intptr_t)tech_pvt);
1481 DEBUGA_SKYPE("got CREATE\n", SKYPOPEN_P_LOG);
1482 break;
1483 case WM_DESTROY:
1484 DEBUGA_SKYPE("got DESTROY\n", SKYPOPEN_P_LOG);
1485 tech_pvt->SkypopenHandles.win32_hInit_MainWindowHandle = NULL;
1486 PostQuitMessage(0);
1487 break;
1488 case WM_COPYDATA:
1489 if (tech_pvt->SkypopenHandles.win32_hGlobal_SkypeAPIWindowHandle == (HWND) uiParam) {
1490 unsigned int howmany;
1491 char msg_from_skype[2048];
1492
1493 PCOPYDATASTRUCT poCopyData = (PCOPYDATASTRUCT) ulParam;
1494
1495 memset(msg_from_skype, '\0', sizeof(msg_from_skype));
1496 skypopen_strncpy(msg_from_skype, (const char *) poCopyData->lpData, sizeof(msg_from_skype) - 2);
1497
1498 howmany = strlen(msg_from_skype) + 1;
1499 howmany = skypopen_pipe_write(tech_pvt->SkypopenHandles.fdesc[1], (short *) msg_from_skype, howmany);
1500 lReturnCode = 1;
1501 }
1502 break;
1503 default:
1504 if (tech_pvt && tech_pvt->SkypopenHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach) {
1505 if (uiMessage == tech_pvt->SkypopenHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach) {
1506 switch (ulParam) {
1507 case SKYPECONTROLAPI_ATTACH_SUCCESS:
1508 if (!tech_pvt->SkypopenHandles.currentuserhandle) {
1509 //DEBUGA_SKYPE("\n\n\tConnected to Skype API!\n", SKYPOPEN_P_LOG);
1510 tech_pvt->SkypopenHandles.api_connected = 1;
1511 tech_pvt->SkypopenHandles.win32_hGlobal_SkypeAPIWindowHandle = (HWND) uiParam;
1512 tech_pvt->SkypopenHandles.win32_hGlobal_SkypeAPIWindowHandle = tech_pvt->SkypopenHandles.win32_hGlobal_SkypeAPIWindowHandle;
1513 }
1514 break;
1515 case SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION:
1516 skypopen_sleep(20000);
1517 break;
1518 case SKYPECONTROLAPI_ATTACH_REFUSED:
1519 ERRORA("Skype client refused to be connected by Skypopen!\n", SKYPOPEN_P_LOG);
1520 break;
1521 case SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE:
1522 ERRORA("Skype API not (yet?) available\n", SKYPOPEN_P_LOG);
1523 break;
1524 case SKYPECONTROLAPI_ATTACH_API_AVAILABLE:
1525 DEBUGA_SKYPE("Skype API available\n", SKYPOPEN_P_LOG);
1526 skypopen_sleep(20000);
1527 break;
1528 default:
1529 WARNINGA("GOT AN UNKNOWN SKYPE WINDOWS MSG\n", SKYPOPEN_P_LOG);
1530 }
1531 lReturnCode = 1;
1532 break;
1533 }
1534 }
1535 fIssueDefProc = 1;
1536 break;
1537 }
1538 if (fIssueDefProc)
1539 lReturnCode = DefWindowProc(hWindow, uiMessage, uiParam, ulParam);
1540 return (lReturnCode);
1541 }
1542
win32_Initialize_CreateWindowClass(private_t * tech_pvt)1543 int win32_Initialize_CreateWindowClass(private_t *tech_pvt)
1544 {
1545 unsigned char *paucUUIDString;
1546 RPC_STATUS lUUIDResult;
1547 int fReturnStatus;
1548 UUID oUUID;
1549
1550 fReturnStatus = 0;
1551 lUUIDResult = UuidCreate(&oUUID);
1552 tech_pvt->SkypopenHandles.win32_hInit_ProcessHandle = (HINSTANCE) OpenProcess(PROCESS_DUP_HANDLE, FALSE, GetCurrentProcessId());
1553 if (tech_pvt->SkypopenHandles.win32_hInit_ProcessHandle != NULL && (lUUIDResult == RPC_S_OK || lUUIDResult == RPC_S_UUID_LOCAL_ONLY)) {
1554 if (UuidToString(&oUUID, &paucUUIDString) == RPC_S_OK) {
1555 WNDCLASS oWindowClass;
1556
1557 strcpy(tech_pvt->SkypopenHandles.win32_acInit_WindowClassName, "Skype-API-Skypopen-");
1558 strcat(tech_pvt->SkypopenHandles.win32_acInit_WindowClassName, (char *) paucUUIDString);
1559
1560 oWindowClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
1561 oWindowClass.lpfnWndProc = (WNDPROC) & skypopen_present;
1562 oWindowClass.cbClsExtra = 0;
1563 oWindowClass.cbWndExtra = 0;
1564 oWindowClass.hInstance = tech_pvt->SkypopenHandles.win32_hInit_ProcessHandle;
1565 oWindowClass.hIcon = NULL;
1566 oWindowClass.hCursor = NULL;
1567 oWindowClass.hbrBackground = NULL;
1568 oWindowClass.lpszMenuName = NULL;
1569 oWindowClass.lpszClassName = tech_pvt->SkypopenHandles.win32_acInit_WindowClassName;
1570
1571 if (RegisterClass(&oWindowClass) != 0)
1572 fReturnStatus = 1;
1573
1574 RpcStringFree(&paucUUIDString);
1575 }
1576 }
1577 if (fReturnStatus == 0)
1578 CloseHandle(tech_pvt->SkypopenHandles.win32_hInit_ProcessHandle);
1579 tech_pvt->SkypopenHandles.win32_hInit_ProcessHandle = NULL;
1580 return (fReturnStatus);
1581 }
1582
win32_DeInitialize_DestroyWindowClass(private_t * tech_pvt)1583 void win32_DeInitialize_DestroyWindowClass(private_t *tech_pvt)
1584 {
1585 UnregisterClass(tech_pvt->SkypopenHandles.win32_acInit_WindowClassName, tech_pvt->SkypopenHandles.win32_hInit_ProcessHandle);
1586 CloseHandle(tech_pvt->SkypopenHandles.win32_hInit_ProcessHandle);
1587 tech_pvt->SkypopenHandles.win32_hInit_ProcessHandle = NULL;
1588 }
1589
win32_Initialize_CreateMainWindow(private_t * tech_pvt)1590 int win32_Initialize_CreateMainWindow(private_t *tech_pvt)
1591 {
1592 tech_pvt->SkypopenHandles.win32_hInit_MainWindowHandle =
1593 CreateWindowEx(WS_EX_APPWINDOW | WS_EX_WINDOWEDGE,
1594 tech_pvt->SkypopenHandles.win32_acInit_WindowClassName, "",
1595 WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT,
1596 128, 128, NULL, 0, tech_pvt->SkypopenHandles.win32_hInit_ProcessHandle, tech_pvt);
1597 return (tech_pvt->SkypopenHandles.win32_hInit_MainWindowHandle != NULL ? 1 : 0);
1598 }
1599
win32_DeInitialize_DestroyMainWindow(private_t * tech_pvt)1600 void win32_DeInitialize_DestroyMainWindow(private_t *tech_pvt)
1601 {
1602 if (tech_pvt->SkypopenHandles.win32_hInit_MainWindowHandle != NULL)
1603 DestroyWindow(tech_pvt->SkypopenHandles.win32_hInit_MainWindowHandle), tech_pvt->SkypopenHandles.win32_hInit_MainWindowHandle = NULL;
1604 }
1605
skypopen_do_skypeapi_thread_func(void * obj)1606 void *skypopen_do_skypeapi_thread_func(void *obj)
1607 {
1608 private_t *tech_pvt = obj;
1609 #if defined(WIN32) && !defined(__CYGWIN__)
1610 switch_status_t rv;
1611
1612 switch_file_pipe_create(&tech_pvt->SkypopenHandles.fdesc[0], &tech_pvt->SkypopenHandles.fdesc[1], skypopen_module_pool);
1613 rv = switch_file_pipe_create(&tech_pvt->SkypopenHandles.fdesc[0], &tech_pvt->SkypopenHandles.fdesc[1], skypopen_module_pool);
1614 #else /* WIN32 */
1615 if (pipe(tech_pvt->SkypopenHandles.fdesc)) {
1616 fcntl(tech_pvt->SkypopenHandles.fdesc[0], F_SETFL, O_NONBLOCK);
1617 fcntl(tech_pvt->SkypopenHandles.fdesc[1], F_SETFL, O_NONBLOCK);
1618 }
1619 #endif /* WIN32 */
1620
1621 tech_pvt->SkypopenHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach = RegisterWindowMessage("SkypeControlAPIAttach");
1622 tech_pvt->SkypopenHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover = RegisterWindowMessage("SkypeControlAPIDiscover");
1623
1624 skypopen_sleep(200000); //0,2 sec
1625
1626 if (tech_pvt->SkypopenHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach != 0
1627 && tech_pvt->SkypopenHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover != 0) {
1628 if (win32_Initialize_CreateWindowClass(tech_pvt)) {
1629 if (win32_Initialize_CreateMainWindow(tech_pvt)) {
1630 if (SendMessage
1631 (HWND_BROADCAST,
1632 tech_pvt->SkypopenHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover,
1633 (WPARAM) tech_pvt->SkypopenHandles.win32_hInit_MainWindowHandle, 0) != 0) {
1634 tech_pvt->SkypopenHandles.win32_hInit_MainWindowHandle = tech_pvt->SkypopenHandles.win32_hInit_MainWindowHandle;
1635 while (running && tech_pvt->running) {
1636 MSG oMessage;
1637 if (!(running && tech_pvt->running))
1638 break;
1639 while (GetMessage(&oMessage, 0, 0, 0)) {
1640 TranslateMessage(&oMessage);
1641 DispatchMessage(&oMessage);
1642 }
1643 }
1644 }
1645 win32_DeInitialize_DestroyMainWindow(tech_pvt);
1646 }
1647 win32_DeInitialize_DestroyWindowClass(tech_pvt);
1648 }
1649 }
1650 tech_pvt->skypopen_api_thread = NULL;
1651 DEBUGA_SKYPE("EXITING\n", SKYPOPEN_P_LOG);
1652 return NULL;
1653 }
1654
1655 #else /* NOT WIN32 */
1656
1657 // CLOUDTREE (Thomas Hazel)
xio_error_handler(Display * dpy)1658 int xio_error_handler(Display * dpy)
1659 {
1660 private_t *tech_pvt = NULL;
1661 struct SkypopenHandles *handle;
1662
1663 ERRORA("Fatal display error for %d, %s\n", SKYPOPEN_P_LOG, skypopen_list_size(&global_handles_list), dpy->display_name);
1664
1665 handle = skypopen_list_remove_by_value(&global_handles_list, dpy);
1666 if (handle != NULL) {
1667 #ifdef XIO_ERROR_BY_SETJMP
1668 siglongjmp(handle->ioerror_context, 1);
1669 #endif
1670 #ifdef XIO_ERROR_BY_UCONTEXT
1671 setcontext(&handle->ioerror_context);
1672 #endif
1673 }
1674
1675 ERRORA("Fatal display error for %p, %s - failed to siglongjmp\n", SKYPOPEN_P_LOG, (void *) handle, dpy->display_name);
1676
1677 return 0;
1678 }
1679
xio_error_handler2(Display * dpy,XErrorEvent * err)1680 int xio_error_handler2(Display * dpy, XErrorEvent * err)
1681 {
1682 private_t *tech_pvt = NULL;
1683 struct SkypopenHandles *handle;
1684 global_x_error = err->error_code;
1685
1686 ERRORA("Received error code %d from X Server\n\n", SKYPOPEN_P_LOG, global_x_error);
1687 ERRORA("Display error for %d, %s\n", SKYPOPEN_P_LOG, skypopen_list_size(&global_handles_list), dpy->display_name);
1688
1689 handle = skypopen_list_remove_by_value(&global_handles_list, dpy);
1690 if (handle != NULL) {
1691 #ifdef XIO_ERROR_BY_SETJMP
1692 siglongjmp(handle->ioerror_context, 1);
1693 #endif
1694 #ifdef XIO_ERROR_BY_UCONTEXT
1695 setcontext(&handle->ioerror_context);
1696 #endif
1697 }
1698
1699 ERRORA("Fatal display error for %p, %s - failed to siglongjmp\n", SKYPOPEN_P_LOG, (void *) handle, dpy->display_name);
1700
1701 return 0;
1702 }
1703
1704
X11_errors_handler(Display * dpy,XErrorEvent * err)1705 int X11_errors_handler(Display * dpy, XErrorEvent * err)
1706 {
1707 private_t *tech_pvt = NULL;
1708 (void) dpy;
1709
1710 global_x_error = err->error_code;
1711 ERRORA("Received error code %d from X Server\n\n", SKYPOPEN_P_LOG, global_x_error);
1712 return 0; /* ignore the error */
1713 }
1714
skypopen_send_message(private_t * tech_pvt,const char * message_P)1715 int skypopen_send_message(private_t *tech_pvt, const char *message_P)
1716 {
1717 struct SkypopenHandles *SkypopenHandles = &tech_pvt->SkypopenHandles;
1718 Window w_P = SkypopenHandles->skype_win;
1719 Display *disp = SkypopenHandles->disp;
1720 Window handle_P = SkypopenHandles->win;
1721
1722
1723 Atom atom1 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
1724 Atom atom2 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE", False);
1725 unsigned int pos = 0;
1726 unsigned int len = strlen(message_P);
1727 XEvent e;
1728
1729 //skypopen_sleep(1000);
1730 //XFlush(disp);
1731
1732 memset(&e, 0, sizeof(e));
1733 e.xclient.type = ClientMessage;
1734 e.xclient.message_type = atom1; /* leading message */
1735 e.xclient.display = disp;
1736 e.xclient.window = handle_P;
1737 e.xclient.format = 8;
1738
1739 // CLOUDTREE (Thomas Hazel)
1740 global_x_error = Success;
1741
1742 do {
1743 unsigned int i;
1744 for (i = 0; i < 20 && i + pos <= len; ++i)
1745 e.xclient.data.b[i] = message_P[i + pos];
1746 XSendEvent(disp, w_P, False, 0, &e);
1747
1748 e.xclient.message_type = atom2; /* following messages */
1749 pos += i;
1750 } while (pos <= len);
1751
1752 XFlush(disp);
1753
1754 // CLOUDTREE (Thomas Hazel)
1755 if (global_x_error != Success) {
1756 ERRORA("Sending message failed with status %d\n", SKYPOPEN_P_LOG, global_x_error);
1757 tech_pvt->running = 0;
1758 return 0;
1759 }
1760
1761 return 1;
1762 }
1763
skypopen_signaling_write(private_t * tech_pvt,char * msg_to_skype)1764 int skypopen_signaling_write(private_t *tech_pvt, char *msg_to_skype)
1765 {
1766
1767 DEBUGA_SKYPE("SENDING: |||%s||||\n", SKYPOPEN_P_LOG, msg_to_skype);
1768
1769
1770 if (!skypopen_send_message(tech_pvt, msg_to_skype)) {
1771 ERRORA
1772 ("Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypopen, then restart Skype, then launch Skypopen and try again.\n",
1773 SKYPOPEN_P_LOG);
1774 return -1;
1775 }
1776
1777 return 0;
1778
1779 }
1780
skypopen_present(struct SkypopenHandles * SkypopenHandles)1781 int skypopen_present(struct SkypopenHandles *SkypopenHandles)
1782 {
1783 Atom skype_inst = XInternAtom(SkypopenHandles->disp, "_SKYPE_INSTANCE", True);
1784
1785 Atom type_ret;
1786 int format_ret;
1787 unsigned long nitems_ret;
1788 unsigned long bytes_after_ret;
1789 unsigned char *prop;
1790 int status;
1791 private_t *tech_pvt = NULL;
1792
1793 status =
1794 XGetWindowProperty(SkypopenHandles->disp, DefaultRootWindow(SkypopenHandles->disp),
1795 skype_inst, 0, 1, False, XA_WINDOW, &type_ret, &format_ret, &nitems_ret, &bytes_after_ret, &prop);
1796
1797 /* sanity check */
1798 if (status != Success || format_ret != 32 || nitems_ret != 1) {
1799 SkypopenHandles->skype_win = (Window) - 1;
1800 DEBUGA_SKYPE("Skype instance not found\n", SKYPOPEN_P_LOG);
1801 running = 0;
1802 SkypopenHandles->api_connected = 0;
1803 return 0;
1804 }
1805
1806 SkypopenHandles->skype_win = *(const unsigned long *) prop & 0xffffffff;
1807 DEBUGA_SKYPE("Skype instance found with id #%d\n", SKYPOPEN_P_LOG, (unsigned int) SkypopenHandles->skype_win);
1808 SkypopenHandles->api_connected = 1;
1809 return 1;
1810 }
1811
skypopen_clean_disp(void * data)1812 void skypopen_clean_disp(void *data)
1813 {
1814
1815 int *dispptr;
1816 int disp;
1817 private_t *tech_pvt = NULL;
1818
1819 dispptr = data;
1820 disp = *dispptr;
1821
1822 if (disp) {
1823 DEBUGA_SKYPE("to be destroyed disp %d\n", SKYPOPEN_P_LOG, disp);
1824 close(disp);
1825 DEBUGA_SKYPE("destroyed disp\n", SKYPOPEN_P_LOG);
1826 } else {
1827 DEBUGA_SKYPE("NOT destroyed disp\n", SKYPOPEN_P_LOG);
1828 }
1829 DEBUGA_SKYPE("OUT destroyed disp\n", SKYPOPEN_P_LOG);
1830 skypopen_sleep(20000);
1831 }
1832
skypopen_do_skypeapi_thread_func(void * obj)1833 void *skypopen_do_skypeapi_thread_func(void *obj)
1834 {
1835
1836 private_t *tech_pvt = obj;
1837 struct SkypopenHandles *SkypopenHandles;
1838 char buf[512];
1839 Display *disp = NULL;
1840 Window root = -1;
1841 Window win = -1;
1842 int xfd;
1843 fd_set xfds;
1844
1845 if (!strlen(tech_pvt->X11_display))
1846 strcpy(tech_pvt->X11_display, getenv("DISPLAY"));
1847
1848 if (!tech_pvt->tcp_srv_port)
1849 tech_pvt->tcp_srv_port = 10160;
1850
1851 if (!tech_pvt->tcp_cli_port)
1852 tech_pvt->tcp_cli_port = 10161;
1853
1854 if (pipe(tech_pvt->SkypopenHandles.fdesc)) {
1855 fcntl(tech_pvt->SkypopenHandles.fdesc[0], F_SETFL, O_NONBLOCK);
1856 fcntl(tech_pvt->SkypopenHandles.fdesc[1], F_SETFL, O_NONBLOCK);
1857 }
1858 SkypopenHandles = &tech_pvt->SkypopenHandles;
1859 disp = XOpenDisplay(tech_pvt->X11_display);
1860 if (!disp) {
1861 ERRORA("Cannot open X Display '%s', exiting skype thread\n", SKYPOPEN_P_LOG, tech_pvt->X11_display);
1862 running = 0;
1863
1864 // CLOUDTREE (Thomas Hazel)
1865 tech_pvt->skypopen_api_thread = NULL;
1866 remove_interface(tech_pvt->skype_user, FALSE);
1867 return NULL;
1868 } else {
1869 DEBUGA_SKYPE("X Display '%s' opened\n", SKYPOPEN_P_LOG, tech_pvt->X11_display);
1870 }
1871
1872 // CLOUDTREE (Thomas Hazel)
1873 #ifndef WIN32
1874 {
1875 char interfacename[256];
1876
1877 skypopen_list_add(&global_handles_list, SkypopenHandles);
1878 sprintf(interfacename, "#%s", tech_pvt->name);
1879
1880 #ifdef XIO_ERROR_BY_SETJMP
1881 if (sigsetjmp(SkypopenHandles->ioerror_context, 1) != 0) {
1882 switch_core_session_t *session = NULL;
1883 tech_pvt->interface_state = SKYPOPEN_STATE_DEAD;
1884 ERRORA("Fatal display error for %s - successed to jump\n", SKYPOPEN_P_LOG, tech_pvt->X11_display);
1885
1886 session = switch_core_session_locate(tech_pvt->session_uuid_str);
1887 if (session) {
1888 switch_channel_t *channel = switch_core_session_get_channel(session);
1889
1890 if (channel) {
1891
1892 switch_mutex_lock(tech_pvt->flag_mutex);
1893 switch_clear_flag(tech_pvt, TFLAG_IO);
1894 switch_clear_flag(tech_pvt, TFLAG_VOICE);
1895 if (switch_test_flag(tech_pvt, TFLAG_PROGRESS)) {
1896 switch_clear_flag(tech_pvt, TFLAG_PROGRESS);
1897 }
1898 switch_mutex_unlock(tech_pvt->flag_mutex);
1899
1900
1901 switch_core_session_rwunlock(session);
1902 WARNINGA("Closing session for %s\n", SKYPOPEN_P_LOG, interfacename);
1903 switch_channel_hangup(channel, SWITCH_CAUSE_CRASH);
1904 } else {
1905 WARNINGA("NO CHANNEL ?\n", SKYPOPEN_P_LOG);
1906 switch_core_session_rwunlock(session);
1907 }
1908 }
1909
1910 WARNINGA("Removing skype interface %s\n", SKYPOPEN_P_LOG, interfacename);
1911 remove_interface(interfacename, TRUE);
1912 return NULL;
1913 }
1914 #endif
1915 #ifdef XIO_ERROR_BY_UCONTEXT
1916 getcontext(&SkypopenHandles->ioerror_context);
1917
1918 if (skypopen_list_find(&global_handles_list, SkypopenHandles) == NULL) {
1919 switch_core_session_t *session = NULL;
1920 tech_pvt->interface_state = SKYPOPEN_STATE_DEAD;
1921 ERRORA("Fatal display error for %s - successed to jump\n", SKYPOPEN_P_LOG, tech_pvt->X11_display);
1922
1923 session = switch_core_session_locate(tech_pvt->session_uuid_str);
1924 if (session) {
1925 switch_channel_t *channel = switch_core_session_get_channel(session);
1926
1927
1928 if (channel) {
1929 switch_mutex_lock(tech_pvt->flag_mutex);
1930 switch_clear_flag(tech_pvt, TFLAG_IO);
1931 switch_clear_flag(tech_pvt, TFLAG_VOICE);
1932 if (switch_test_flag(tech_pvt, TFLAG_PROGRESS)) {
1933 switch_clear_flag(tech_pvt, TFLAG_PROGRESS);
1934 }
1935 switch_mutex_unlock(tech_pvt->flag_mutex);
1936
1937
1938 switch_core_session_rwunlock(session);
1939 WARNINGA("Closing session for %s\n", SKYPOPEN_P_LOG, interfacename);
1940 switch_channel_hangup(channel, SWITCH_CAUSE_CRASH);
1941
1942 } else {
1943 WARNINGA("NO CHANNEL ?\n", SKYPOPEN_P_LOG);
1944 }
1945 //skypopen_sleep(500000);
1946 }
1947
1948 WARNINGA("Removing skype interface %s\n", SKYPOPEN_P_LOG, interfacename);
1949 //tech_pvt->skypopen_api_thread = NULL;
1950 remove_interface(interfacename, TRUE);
1951 //XCloseDisplay(disp);
1952 return NULL;
1953 }
1954 #endif
1955 }
1956 #endif /* NOT WIN32 */
1957
1958 xfd = XConnectionNumber(disp);
1959 fcntl(xfd, F_SETFD, FD_CLOEXEC);
1960
1961 SkypopenHandles->disp = disp;
1962
1963 if (skypopen_present(SkypopenHandles)) {
1964 root = DefaultRootWindow(disp);
1965 win = XCreateSimpleWindow(disp, root, 0, 0, 1, 1, 0, BlackPixel(disp, DefaultScreen(disp)), BlackPixel(disp, DefaultScreen(disp)));
1966
1967 SkypopenHandles->win = win;
1968
1969 snprintf(buf, 512, "NAME skypopen");
1970
1971 if (!skypopen_send_message(tech_pvt, buf)) {
1972 ERRORA("Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypopen again\n", SKYPOPEN_P_LOG);
1973
1974 // CLOUDTREE (Thomas Hazel)
1975 #ifndef WIN32
1976 skypopen_list_remove_by_reference(&global_handles_list, SkypopenHandles);
1977 #endif
1978
1979 XCloseDisplay(disp);
1980 running = 0;
1981 return NULL;
1982 }
1983
1984 snprintf(buf, 512, "PROTOCOL 999");
1985 if (!skypopen_send_message(tech_pvt, buf)) {
1986 ERRORA("Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypopen again\n", SKYPOPEN_P_LOG);
1987
1988 // CLOUDTREE (Thomas Hazel)
1989 #ifndef WIN32
1990 skypopen_list_remove_by_reference(&global_handles_list, SkypopenHandles);
1991 #endif
1992
1993 XCloseDisplay(disp);
1994 running = 0;
1995 return NULL;
1996 }
1997
1998 {
1999 /* perform an events loop */
2000 XEvent an_event;
2001 char buf[21]; /* can't be longer */
2002 char buffer[17000];
2003 char continuebuffer[17000];
2004 char *b;
2005 int i;
2006 int continue_is_broken = 0;
2007 int there_were_continues = 0;
2008 struct timeval tv;
2009 Atom atom_begin = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
2010 Atom atom_continue = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE", False);
2011
2012 memset(buffer, '\0', 17000);
2013 memset(continuebuffer, '\0', 17000);
2014 b = buffer;
2015
2016 while (running && tech_pvt->running) {
2017
2018
2019 FD_ZERO(&xfds);
2020 FD_SET(xfd, &xfds);
2021
2022 tv.tv_usec = 100000;
2023 tv.tv_sec = 0;
2024
2025
2026
2027 if (select(xfd + 1, &xfds, 0, 0, &tv)) {
2028
2029 while (XPending(disp)) {
2030
2031
2032
2033 XNextEvent(disp, &an_event);
2034 if (!(running && tech_pvt->running))
2035 break;
2036 switch (an_event.type) {
2037 case ClientMessage:
2038
2039 if (an_event.xclient.format != 8) {
2040 //skypopen_sleep(1000); //0.1 msec
2041 break;
2042 }
2043
2044 for (i = 0; i < 20 && an_event.xclient.data.b[i] != '\0'; ++i)
2045 buf[i] = an_event.xclient.data.b[i];
2046
2047 buf[i] = '\0';
2048
2049 if (an_event.xclient.message_type == atom_begin) {
2050 if (strlen(buffer)) {
2051 unsigned int howmany;
2052 howmany = strlen(b) + 1;
2053 howmany = write(SkypopenHandles->fdesc[1], b, howmany);
2054 WARNINGA
2055 ("A begin atom while the previous message is not closed???? value of previous message (between vertical bars) is=|||%s|||, will be lost\n",
2056 SKYPOPEN_P_LOG, buffer);
2057 memset(buffer, '\0', 17000);
2058 }
2059 if (continue_is_broken) {
2060 continue_is_broken = 0;
2061 there_were_continues = 1;
2062 }
2063 }
2064 if (an_event.xclient.message_type == atom_continue) {
2065 if (!strlen(buffer)) {
2066 WARNINGA
2067 ("Got a 'continue' XAtom without a previous 'begin'. It's value (between vertical bars) is=|||%s|||, let's store it and hope next 'begin' will be the good one\n",
2068 SKYPOPEN_P_LOG, buf);
2069 strcat(continuebuffer, buf);
2070 continue_is_broken = 1;
2071 if (!strncmp(buf, "ognised identity", 15)) {
2072 WARNINGA
2073 ("Got a 'continue' XAtom without a previous 'begin'. It's value (between vertical bars) is=|||%s|||. Let's introduce a 1 second delay.\n",
2074 SKYPOPEN_P_LOG, buf);
2075 skypopen_sleep(1000000); //1 sec
2076 }
2077 skypopen_sleep(20000); //20 msec
2078 break;
2079 }
2080 }
2081 if (continue_is_broken) {
2082 XFlush(disp);
2083 skypopen_sleep(20000); //20 msec
2084 WARNINGA("continue_is_broken\n", SKYPOPEN_P_LOG);
2085 continue;
2086 }
2087 strcat(buffer, buf);
2088 strcat(buffer, continuebuffer);
2089 memset(continuebuffer, '\0', 17000);
2090
2091 if (i < 20 || there_were_continues) { /* last fragment */
2092 unsigned int howmany;
2093
2094 howmany = strlen(b) + 1;
2095 howmany = write(SkypopenHandles->fdesc[1], b, howmany);
2096 memset(buffer, '\0', 17000);
2097 //XFlush(disp);
2098 there_were_continues = 0;
2099 }
2100 //skypopen_sleep(1000); //0.1 msec
2101 break;
2102 default:
2103 //skypopen_sleep(1000); //0.1 msec
2104 break;
2105 } //switch event.type
2106 } //while XPending
2107 XFlush(disp);
2108
2109 } // if select
2110 } //while running
2111
2112
2113
2114
2115
2116 }
2117 } else {
2118 ERRORA("Skype is not running, maybe crashed. Please run/restart Skype and relaunch Skypopen\n", SKYPOPEN_P_LOG);
2119 running = 0;
2120 }
2121
2122 DEBUGA_SKYPE("EXITING\n", SKYPOPEN_P_LOG);
2123
2124 // CLOUDTREE (Thomas Hazel)
2125 #ifndef WIN32
2126 skypopen_list_remove_by_reference(&global_handles_list, SkypopenHandles);
2127 #endif
2128
2129 tech_pvt->skypopen_api_thread = NULL;
2130 return NULL;
2131
2132 }
2133 #endif // WIN32
2134
inbound_channel_answered(private_t * tech_pvt)2135 int inbound_channel_answered(private_t *tech_pvt)
2136 {
2137 int res = 0;
2138 switch_core_session_t *session = NULL;
2139 switch_channel_t *channel = NULL;
2140
2141 session = switch_core_session_locate(tech_pvt->session_uuid_str);
2142 if (session) {
2143 channel = switch_core_session_get_channel(session);
2144
2145 if (channel) {
2146 switch_mutex_lock(tech_pvt->flag_mutex);
2147 switch_set_flag(tech_pvt, TFLAG_IO);
2148 switch_mutex_unlock(tech_pvt->flag_mutex);
2149 } else {
2150 ERRORA("no channel\n", SKYPOPEN_P_LOG);
2151 }
2152 switch_core_session_rwunlock(session);
2153 } else {
2154 ERRORA("no session\n", SKYPOPEN_P_LOG);
2155
2156 }
2157 return res;
2158 }
2159
2160
skypopen_answered(private_t * tech_pvt)2161 int skypopen_answered(private_t *tech_pvt)
2162 {
2163
2164 int res = SWITCH_STATUS_SUCCESS;
2165 switch_core_session_t *session = NULL;
2166 switch_channel_t *channel = NULL;
2167
2168 if (strlen(tech_pvt->session_uuid_str)) {
2169 session = switch_core_session_locate(tech_pvt->session_uuid_str);
2170 if (session) {
2171 channel = switch_core_session_get_channel(session);
2172
2173 if (channel) {
2174 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
2175 tech_pvt->interface_state = SKYPOPEN_STATE_UP;
2176 DEBUGA_SKYPE("Outbound Channel Answered! session_uuid_str=%s\n", SKYPOPEN_P_LOG, tech_pvt->session_uuid_str);
2177 outbound_channel_answered(tech_pvt);
2178 } else {
2179 DEBUGA_SKYPE("answered Inbound Channel!\n\n\n\n", SKYPOPEN_P_LOG);
2180 inbound_channel_answered(tech_pvt);
2181 }
2182
2183 } else {
2184 ERRORA("no channel after INPROGRESS?\n", SKYPOPEN_P_LOG);
2185 return SWITCH_STATUS_FALSE;
2186 }
2187 switch_core_session_rwunlock(session);
2188 } else {
2189 WARNINGA("no session after INPROGRESS, let's hangup\n", SKYPOPEN_P_LOG);
2190 return SWITCH_STATUS_FALSE;
2191 }
2192 } else {
2193 WARNINGA("no tech_pvt->session_uuid_str after INPROGRESS, let's hangup\n", SKYPOPEN_P_LOG);
2194 return SWITCH_STATUS_FALSE;
2195 }
2196 return res;
2197 }
2198