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