1 /* 2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application 3 * Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org> 4 * 5 * Version: MPL 1.1 6 * 7 * The contents of this file are subject to the Mozilla Public License Version 8 * 1.1 (the "License"); you may not use this file except in compliance with 9 * the License. You may obtain a copy of the License at 10 * http://www.mozilla.org/MPL/ 11 * 12 * Software distributed under the License is distributed on an "AS IS" basis, 13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 14 * for the specific language governing rights and limitations under the 15 * License. 16 * 17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application 18 * 19 * The Initial Developer of the Original Code is 20 * Anthony Minessale II <anthm@freeswitch.org> 21 * Portions created by the Initial Developer are Copyright (C) 22 * the Initial Developer. All Rights Reserved. 23 * 24 * This module (mod_gsmopen) has been contributed by: 25 * 26 * Giovanni Maruzzelli <gmaruzz@gmail.com> 27 * 28 * Maintainer: Giovanni Maruzzelli <gmaruzz@gmail.com> 29 * 30 * mod_skypopen.c -- Skype compatible Endpoint Module 31 * 32 */ 33 34 35 #include <switch.h> 36 37 #ifndef WIN32 38 #include <sys/time.h> 39 #include <X11/Xlib.h> 40 #include <X11/Xlibint.h> 41 #include <X11/Xatom.h> 42 43 // CLOUDTREE (Thomas Hazel) 44 #define XIO_ERROR_BY_SETJMP 45 //#define XIO_ERROR_BY_UCONTEXT 46 47 // CLOUDTREE (Thomas Hazel) 48 #ifdef XIO_ERROR_BY_SETJMP 49 #include "setjmp.h" 50 #endif 51 // CLOUDTREE (Thomas Hazel) 52 #ifdef XIO_ERROR_BY_UCONTEXT 53 #include "ucontext.h" 54 #endif 55 56 #endif //WIN32 57 58 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES 59 #include <spandsp.h> 60 #include <spandsp/version.h> 61 62 #ifndef WIN32 63 #include <netinet/tcp.h> 64 #endif 65 66 #ifdef _MSC_VER 67 //Windows macro for FD_SET includes a warning C4127: conditional expression is constant 68 #pragma warning(push) 69 #pragma warning(disable:4127) 70 #endif 71 72 #define MY_EVENT_INCOMING_CHATMESSAGE "skypopen::incoming_chatmessage" 73 #define MY_EVENT_INCOMING_RAW "skypopen::incoming_raw" 74 75 #define SAMPLERATE_SKYPOPEN 16000 76 #define MS_SKYPOPEN 20 77 #define SAMPLES_PER_FRAME (SAMPLERATE_SKYPOPEN/(1000/MS_SKYPOPEN)) 78 #define BYTES_PER_FRAME (SAMPLES_PER_FRAME * sizeof(short)) 79 80 #ifndef SKYPOPEN_SVN_VERSION 81 #define SKYPOPEN_SVN_VERSION switch_version_full() 82 #endif /* SKYPOPEN_SVN_VERSION */ 83 84 typedef enum { 85 TFLAG_IO = (1 << 0), 86 TFLAG_INBOUND = (1 << 1), 87 TFLAG_OUTBOUND = (1 << 2), 88 TFLAG_DTMF = (1 << 3), 89 TFLAG_VOICE = (1 << 4), 90 TFLAG_HANGUP = (1 << 5), 91 TFLAG_LINEAR = (1 << 6), 92 TFLAG_PROGRESS = (1 << 7), 93 TFLAG_BREAK = (1 << 8) 94 } TFLAGS; 95 96 typedef enum { 97 GFLAG_MY_CODEC_PREFS = (1 << 0) 98 } GFLAGS; 99 100 #define DEBUGA_SKYPE(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%-*s [%s ] [DEBUG_SKYPE %-5d][%-15s][%s,%s] " __VA_ARGS__ ); 101 #define DEBUGA_CALL(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%-*s [%s ] [DEBUG_CALL %-5d][%-15s][%s,%s] " __VA_ARGS__ ); 102 #define DEBUGA_PBX(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%-*s [%s ] [DEBUG_PBX %-5d][%-15s][%s,%s] " __VA_ARGS__ ); 103 #define ERRORA(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%-*s [%s ] [ERRORA %-5d][%-15s][%s,%s] " __VA_ARGS__ ); 104 #define WARNINGA(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%-*s[%s ] [WARNINGA %-5d][%-15s][%s,%s] " __VA_ARGS__ ); 105 #define NOTICA(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%-*s [%s ] [NOTICA %-5d][%-15s][%s,%s] " __VA_ARGS__ ); 106 107 #define SKYPOPEN_P_LOG (int)((20 - (strlen(__FILE__))) + ((__LINE__ - 1000) < 0) + ((__LINE__ - 100) < 0)), " ", SKYPOPEN_SVN_VERSION, __LINE__, tech_pvt ? tech_pvt->name ? tech_pvt->name : "none" : "none", tech_pvt ? interface_status[tech_pvt->interface_state] : "N/A", tech_pvt ? skype_callflow[tech_pvt->skype_callflow] : "N/A" 108 109 /*********************************/ 110 #define SKYPOPEN_CAUSE_NORMAL 1 111 /*********************************/ 112 #define SKYPOPEN_FRAME_DTMF 1 113 /*********************************/ 114 #define SKYPOPEN_CONTROL_RINGING 1 115 #define SKYPOPEN_CONTROL_ANSWER 2 116 117 /*********************************/ 118 // CLOUDTREE (Thomas Hazel) 119 #define SKYPOPEN_RINGING_INIT 0 120 #define SKYPOPEN_RINGING_PRE 1 121 122 /*********************************/ 123 #define SKYPOPEN_STATE_IDLE 0 124 #define SKYPOPEN_STATE_DOWN 1 125 #define SKYPOPEN_STATE_RING 2 126 #define SKYPOPEN_STATE_DIALING 3 127 #define SKYPOPEN_STATE_BUSY 4 128 #define SKYPOPEN_STATE_UP 5 129 #define SKYPOPEN_STATE_RINGING 6 130 #define SKYPOPEN_STATE_PRERING 7 131 #define SKYPOPEN_STATE_ERROR_DOUBLE_CALL 8 132 #define SKYPOPEN_STATE_SELECTED 9 133 #define SKYPOPEN_STATE_HANGUP_REQUESTED 10 134 #define SKYPOPEN_STATE_PREANSWER 11 135 #define SKYPOPEN_STATE_DEAD 12 136 /*********************************/ 137 /* call flow from the device */ 138 #define CALLFLOW_CALL_IDLE 0 139 #define CALLFLOW_CALL_DOWN 1 140 #define CALLFLOW_INCOMING_RING 2 141 #define CALLFLOW_CALL_DIALING 3 142 #define CALLFLOW_CALL_LINEBUSY 4 143 #define CALLFLOW_CALL_ACTIVE 5 144 #define CALLFLOW_INCOMING_HANGUP 6 145 #define CALLFLOW_CALL_RELEASED 7 146 #define CALLFLOW_CALL_NOCARRIER 8 147 #define CALLFLOW_CALL_INFLUX 9 148 #define CALLFLOW_CALL_INCOMING 10 149 #define CALLFLOW_CALL_FAILED 11 150 #define CALLFLOW_CALL_NOSERVICE 12 151 #define CALLFLOW_CALL_OUTGOINGRESTRICTED 13 152 #define CALLFLOW_CALL_SECURITYFAIL 14 153 #define CALLFLOW_CALL_NOANSWER 15 154 #define CALLFLOW_STATUS_FINISHED 16 155 #define CALLFLOW_STATUS_CANCELLED 17 156 #define CALLFLOW_STATUS_FAILED 18 157 #define CALLFLOW_STATUS_REFUSED 19 158 #define CALLFLOW_STATUS_RINGING 20 159 #define CALLFLOW_STATUS_INPROGRESS 21 160 #define CALLFLOW_STATUS_UNPLACED 22 161 #define CALLFLOW_STATUS_ROUTING 23 162 #define CALLFLOW_STATUS_EARLYMEDIA 24 163 #define CALLFLOW_INCOMING_CALLID 25 164 #define CALLFLOW_STATUS_REMOTEHOLD 26 165 166 /*********************************/ 167 168 #define SKYPOPEN_MAX_INTERFACES 64 169 170 #ifndef WIN32 171 struct SkypopenHandles { 172 Window skype_win; 173 Display *disp; 174 Window win; 175 int currentuserhandle; 176 int api_connected; 177 int fdesc[2]; 178 179 // CLOUDTREE (Thomas Hazel) 180 #ifdef XIO_ERROR_BY_SETJMP 181 jmp_buf ioerror_context; 182 #endif 183 #ifdef XIO_ERROR_BY_UCONTEXT 184 ucontext_t ioerror_context; 185 #endif 186 187 // CLOUDTREE (Thomas Hazel) - is there a capable freeswitch list? 188 switch_bool_t managed; 189 void *prev; 190 void *next; 191 }; 192 193 // CLOUDTREE (Thomas Hazel) - is there a capable freeswitch list? 194 struct SkypopenList { 195 int entries; 196 void *head; 197 void *tail; 198 }; 199 200 // CLOUDTREE (Thomas Hazel) - is there a capable freeswitch list? 201 struct SkypopenHandles *skypopen_list_add(struct SkypopenList *list, struct SkypopenHandles *x); 202 struct SkypopenHandles *skypopen_list_find(struct SkypopenList *list, struct SkypopenHandles *x); 203 struct SkypopenHandles *skypopen_list_remove_by_value(struct SkypopenList *list, Display * display); 204 struct SkypopenHandles *skypopen_list_remove_by_reference(struct SkypopenList *list, struct SkypopenHandles *x); 205 int skypopen_list_size(struct SkypopenList *list); 206 207 #else //WIN32 208 209 struct SkypopenHandles { 210 HWND win32_hInit_MainWindowHandle; 211 HWND win32_hGlobal_SkypeAPIWindowHandle; 212 HINSTANCE win32_hInit_ProcessHandle; 213 char win32_acInit_WindowClassName[128]; 214 UINT win32_uiGlobal_MsgID_SkypeControlAPIAttach; 215 UINT win32_uiGlobal_MsgID_SkypeControlAPIDiscover; 216 int currentuserhandle; 217 int api_connected; 218 switch_file_t *fdesc[2]; 219 }; 220 #endif //WIN32 221 222 #define MAX_CHATS 10 223 224 struct chat { 225 char chatname[256]; 226 char dialog_partner[256]; 227 }; 228 typedef struct chat chat_t; 229 230 #define MAX_CHATMESSAGES 10 231 232 struct chatmessage { 233 char id[256]; 234 char type[256]; 235 char chatname[256]; 236 char from_handle[256]; 237 char from_dispname[256]; 238 char body[512]; 239 }; 240 typedef struct chatmessage chatmessage_t; 241 struct private_object { 242 unsigned int flags; 243 switch_codec_t read_codec; 244 switch_codec_t write_codec; 245 switch_frame_t read_frame; 246 unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; 247 char session_uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; 248 switch_caller_profile_t *caller_profile; 249 switch_mutex_t *mutex; 250 switch_mutex_t *flag_mutex; 251 252 char interface_id[80]; 253 char name[80]; 254 char dialplan[80]; 255 char context[80]; 256 char dial_regex[256]; 257 char fail_dial_regex[256]; 258 char hold_music[256]; 259 char type[256]; 260 char X11_display[256]; 261 #ifdef WIN32 262 unsigned short tcp_cli_port; 263 unsigned short tcp_srv_port; 264 #else 265 int tcp_cli_port; 266 int tcp_srv_port; 267 #endif 268 struct SkypopenHandles SkypopenHandles; 269 270 // CLOUDTREE (Thomas Hazel) 271 char ringing_state; 272 273 int interface_state; 274 char language[80]; 275 char exten[80]; 276 int skypopen_sound_rate; 277 char callid_name[50]; 278 char callid_number[50]; 279 double playback_boost; 280 double capture_boost; 281 int stripmsd; 282 char skype_call_id[512]; 283 int skype_call_ongoing; 284 char skype_friends[4096]; 285 char skype_fullname[512]; 286 char skype_displayname[512]; 287 int skype_callflow; 288 int skype; 289 int control_to_send; 290 #ifdef WIN32 291 switch_file_t *audiopipe_srv[2]; 292 switch_file_t *audiopipe_cli[2]; 293 switch_file_t *skypopen_sound_capt_fd; 294 #else /* WIN32 */ 295 int audiopipe_srv[2]; 296 int audiopipe_cli[2]; 297 int skypopen_sound_capt_fd; 298 #endif /* WIN32 */ 299 switch_thread_t *tcp_srv_thread; 300 switch_thread_t *tcp_cli_thread; 301 switch_thread_t *skypopen_signaling_thread; 302 switch_thread_t *skypopen_api_thread; 303 short audiobuf[SAMPLES_PER_FRAME]; 304 int audiobuf_is_loaded; 305 short audiobuf_cli[SAMPLES_PER_FRAME]; 306 switch_mutex_t *mutex_audio_cli; 307 int flag_audio_cli; 308 short audiobuf_srv[SAMPLES_PER_FRAME]; 309 switch_mutex_t *mutex_audio_srv; 310 int flag_audio_srv; 311 switch_mutex_t *mutex_thread_audio_cli; 312 switch_mutex_t *mutex_thread_audio_srv; 313 314 FILE *phonebook_writing_fp; 315 int skypopen_dir_entry_extension_prefix; 316 char skype_user[256]; 317 char initial_skype_user[256]; 318 char skype_password[256]; 319 char destination[256]; 320 struct timeval answer_time; 321 struct timeval ring_time; 322 323 struct timeval transfer_time; 324 char transfer_callid_number[50]; 325 char skype_transfer_call_id[512]; 326 int running; 327 uint32_t ib_calls; 328 uint32_t ob_calls; 329 uint32_t ib_failed_calls; 330 uint32_t ob_failed_calls; 331 332 chatmessage_t chatmessages[MAX_CHATMESSAGES]; 333 chat_t chats[MAX_CHATS]; 334 uint32_t report_incoming_chatmessages; 335 switch_timer_t timer_read; 336 switch_timer_t timer_read_srv; 337 switch_timer_t timer_write; 338 int begin_to_write; 339 int begin_to_read; 340 dtmf_rx_state_t dtmf_state; 341 switch_time_t old_dtmf_timestamp; 342 switch_buffer_t *write_buffer; 343 switch_buffer_t *read_buffer; 344 int silent_mode; 345 int write_silence_when_idle; 346 int setsockopt; 347 char answer_id[256]; 348 char answer_value[256]; 349 char ring_id[256]; 350 char ring_value[256]; 351 352 char message[4096]; 353 char skype_voicemail_id[512]; 354 char skype_voicemail_id_greeting[512]; 355 }; 356 357 typedef struct private_object private_t; 358 359 void *SWITCH_THREAD_FUNC skypopen_api_thread_func(switch_thread_t *thread, void *obj); 360 int skypopen_audio_read(private_t *tech_pvt); 361 int skypopen_audio_init(private_t *tech_pvt); 362 int skypopen_signaling_write(private_t *tech_pvt, char *msg_to_skype); 363 int skypopen_signaling_read(private_t *tech_pvt); 364 365 int skypopen_call(private_t *tech_pvt, char *idest, int timeout); 366 int skypopen_senddigit(private_t *tech_pvt, char digit); 367 368 void *skypopen_do_tcp_srv_thread_func(void *obj); 369 void *SWITCH_THREAD_FUNC skypopen_do_tcp_srv_thread(switch_thread_t *thread, void *obj); 370 371 void *skypopen_do_tcp_cli_thread_func(void *obj); 372 void *SWITCH_THREAD_FUNC skypopen_do_tcp_cli_thread(switch_thread_t *thread, void *obj); 373 374 void *skypopen_do_skypeapi_thread_func(void *obj); 375 void *SWITCH_THREAD_FUNC skypopen_do_skypeapi_thread(switch_thread_t *thread, void *obj); 376 int dtmf_received(private_t *tech_pvt, char *value); 377 int start_audio_threads(private_t *tech_pvt); 378 int new_inbound_channel(private_t *tech_pvt); 379 int outbound_channel_answered(private_t *tech_pvt); 380 int skypopen_signaling_write(private_t *tech_pvt, char *msg_to_skype); 381 #if defined(WIN32) && !defined(__CYGWIN__) 382 int skypopen_pipe_read(switch_file_t *pipe, short *buf, int howmany); 383 int skypopen_pipe_write(switch_file_t *pipe, short *buf, int howmany); 384 /* Visual C do not have strsep ? */ 385 char *strsep(char **stringp, const char *delim); 386 #else 387 int skypopen_pipe_read(int pipe, short *buf, int howmany); 388 int skypopen_pipe_write(int pipe, short *buf, int howmany); 389 #endif /* WIN32 */ 390 int skypopen_close_socket(unsigned int fd); 391 private_t *find_available_skypopen_interface_rr(private_t *tech_pvt_calling); 392 int remote_party_is_ringing(private_t *tech_pvt); 393 int remote_party_is_early_media(private_t *tech_pvt); 394 int skypopen_answer(private_t *tech_pvt); 395 int skypopen_transfer(private_t *tech_pvt); 396 #ifndef WIN32 397 int skypopen_socket_create_and_bind(private_t *tech_pvt, int *which_port); 398 #else 399 int skypopen_socket_create_and_bind(private_t *tech_pvt, unsigned short *which_port); 400 #endif //WIN32 401 int incoming_chatmessage(private_t *tech_pvt, int which); 402 int next_port(void); 403 int skypopen_partner_handle_ring(private_t *tech_pvt); 404 int skypopen_answered(private_t *tech_pvt); 405 int inbound_channel_answered(private_t *tech_pvt); 406