Parent Directory
|
Revision Log
(mod_woomera) Added RTP bridging
1 /* 2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application 3 * 4 * Copyright (C) 2009-2010 Dialogic Corp. 5 * Copyright (C) 2005-2006, Anthony Minessale II <anthmct@yahoo.com> 6 * 7 * Version: MPL 1.1 8 * 9 * The contents of this file are subject to the Mozilla Public License Version 10 * 1.1 (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * http://www.mozilla.org/MPL/ 13 * 14 * Software distributed under the License is distributed on an "AS IS" basis, 15 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 16 * for the specific language governing rights and limitations under the 17 * License. 18 * 19 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application 20 * 21 * The Initial Developer of the Original Code is 22 * Anthony Minessale II <anthmct@yahoo.com> 23 * Portions created by the Initial Developer are Copyright (C) 24 * the Initial Developer. All Rights Reserved. 25 * 26 * Contributor(s): 27 * 28 * Anthony Minessale II <anthmct@yahoo.com> 29 * Antony Martin <antony.martin@dialogic.com> 30 * 31 * 32 * mod_woomera.c -- Woomera Endpoint Module 33 * 34 */ 35 #include <switch.h> 36 #include <sys/time.h> 37 38 #define WOOMERA_STRLEN 256 39 #define WOOMERA_ARRAY_LEN 25 40 #define WOOMERA_MIN_PORT 9900 41 #define WOOMERA_MAX_PORT 9999 42 #define WOOMERA_BODYLEN 2048 43 #define WOOMERA_LINE_SEPERATOR "\r\n" 44 #define WOOMERA_RECORD_SEPERATOR "\r\n\r\n" 45 #define WOOMERA_DEBUG_PREFIX "**[DEBUG]** " 46 #define WOOMERA_DEBUG_LINE "--------------------------------------------------------------------------------" 47 #define WOOMERA_HARD_TIMEOUT -10000 48 #define WOOMERA_QLEN 10 49 #define WOOMERA_RECONNECT_TIME 5000000 50 51 SWITCH_MODULE_LOAD_FUNCTION(mod_woomera_load); 52 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_woomera_shutdown); 53 SWITCH_MODULE_RUNTIME_FUNCTION(mod_woomera_runtime); 54 SWITCH_MODULE_DEFINITION(mod_woomera, mod_woomera_load, mod_woomera_shutdown, mod_woomera_runtime); 55 56 static switch_memory_pool_t *module_pool = NULL; 57 switch_endpoint_interface_t *woomera_endpoint_interface; 58 59 #define STRLEN 15 60 #define FRAME_LEN 480 61 62 static char *woomeraplaybackdesc = "Play audio and / or video on the Woomera Server\n"; 63 static char *woomeraplaybackapp = "WoomeraPlayback"; 64 static char *woomeraplaybacksynopsis = "Execute a play on chan_woomera"; 65 66 static char *woomerabackgrounddesc = "Play audio and / or video in the background on the Woomera Server\n"; 67 static char *woomerabackgroundapp = "WoomeraBackground"; 68 static char *woomerabackgroundsynopsis = "Execute a background play on chan_woomera"; 69 70 static char *woomerarecorddesc = "Record audio and / or video on the Woomera Server\n"; 71 static char *woomerarecordapp = "WoomeraRecord"; 72 static char *woomerarecordsynopsis = "Execute a Record on chan_woomera"; 73 74 static char *woomerastopdesc = "Stop the current background play on the Woomera Server\n"; 75 static char *woomerastopapp = "WoomeraStop"; 76 static char *woomerastopsynopsis = "Stop the current WoomeraBackground "; 77 78 static char *woomeraringbackdesc = "Play audio and / or video ringback until the call is answered\n"; 79 static char *woomeraringbackapp = "WoomeraRingback"; 80 static char *woomeraringbacksynopsis = "Execute a play ringback on chan_woomera"; 81 82 static char *woomerawaitfortonedesc = "Wait for a tone to be detected\n"; 83 static char *woomerawaitfortoneapp = "WoomeraWaitForTone"; 84 static char *woomerawaitfortonesynopsis = "Execute a wait-for-tone on chan_woomera"; 85 86 87 typedef enum { 88 WFLAG_EXISTS = (1 << 0), 89 WFLAG_EVENT = (1 << 1), 90 WFLAG_CONTENT = (1 << 2), 91 } WFLAGS; 92 93 94 typedef enum { 95 WCFLAG_NOWAIT = (1 << 0) 96 } WCFLAGS; 97 98 99 typedef enum { 100 PFLAG_INBOUND = (1 << 0), 101 PFLAG_OUTBOUND = (1 << 1), 102 PFLAG_DYNAMIC = (1 << 2), 103 PFLAG_DISABLED = (1 << 3), 104 PFLAG_RTP = (1 << 4), 105 PFLAG_VIDEORTP = (1 << 5) 106 } PFLAGS; 107 108 typedef enum { 109 TFLAG_MEDIA = (1 << 0), 110 TFLAG_INBOUND = (1 << 1), 111 TFLAG_OUTBOUND = (1 << 2), 112 TFLAG_INCOMING = (1 << 3), 113 TFLAG_PARSE_INCOMING = (1 << 4), 114 TFLAG_ACTIVATE = (1 << 5), 115 TFLAG_DTMF = (1 << 6), 116 TFLAG_DESTROY = (1 << 7), 117 TFLAG_ABORT = (1 << 8), 118 TFLAG_SWITCH = (1 << 9), 119 TFLAG_ANSWER = (1 << 10), 120 TFLAG_WRITING = (1 << 11), 121 TFLAG_PLAY = (1 << 12), 122 TFLAG_PLAY_COMPLETED = (1 << 13), 123 TFLAG_RECORD = (1 << 14), 124 TFLAG_RECORD_COMPLETED = (1 << 15), 125 TFLAG_STOP = (1 << 16), 126 TFLAG_STOP_COMPLETED = (1 << 17), 127 TFLAG_TONE_EVENTS_ON = (1 << 18), 128 TFLAG_TONE_EVENTS_OFF = (1 << 19), 129 TFLAG_WAITFORTONE = (1 << 20), 130 TFLAG_BRIDGE = (1 << 21), 131 TFLAG_CONNECTED = (1 << 22) 132 } TFLAGS; 133 134 struct woomera_message { 135 char callid[WOOMERA_STRLEN]; 136 int mval; 137 char command[WOOMERA_STRLEN]; 138 char command_args[WOOMERA_STRLEN]; 139 char names[WOOMERA_ARRAY_LEN][WOOMERA_STRLEN]; 140 char values[WOOMERA_ARRAY_LEN][WOOMERA_STRLEN]; 141 char body[WOOMERA_BODYLEN]; 142 unsigned int flags; 143 int last; 144 struct woomera_message *next; 145 }; 146 147 148 static struct { 149 switch_port_t next_woomera_port; 150 int debug; 151 int panic; 152 int rtpmode; 153 } globals; 154 155 static struct { 156 int woomeraplayback; 157 int woomerabackground; 158 int woomerarecord; 159 int woomeraringback; 160 int woomerawaitfortone; 161 int woomerastop; 162 } capabilities; 163 164 165 struct woomera_event_queue { 166 struct woomera_message *head; 167 }; 168 169 struct woomera_profile { 170 char *name; 171 switch_socket_t *woomera_socket; 172 switch_mutex_t *iolock; 173 char woomera_host[WOOMERA_STRLEN]; 174 switch_port_t woomera_port; 175 char audio_ip[WOOMERA_STRLEN]; 176 char dialplan[WOOMERA_STRLEN]; 177 char context[WOOMERA_STRLEN]; 178 char language[WOOMERA_STRLEN]; 179 unsigned int flags; 180 int thread_running; 181 struct woomera_event_queue event_queue; 182 char *timer_name; 183 }; 184 185 186 struct private_object { 187 188 switch_core_session_t *session; 189 struct woomera_profile *profile; 190 switch_caller_profile_t *caller_profile; 191 struct woomera_message call_info; 192 193 unsigned int flags; 194 switch_mutex_t *iolock; 195 switch_mutex_t *flag_mutex; 196 197 //Woomera Socket 198 switch_socket_t *woomera_socket; 199 char dtmfbuf[WOOMERA_STRLEN]; 200 struct woomera_event_queue event_queue; 201 //Audio UDP 202 // switch_pollfd_t *read_poll; 203 // switch_pollfd_t *write_poll; 204 switch_socket_t *audio_udp_socket; 205 switch_sockaddr_t *audio_udpread; 206 switch_sockaddr_t *audio_udpwrite; 207 char audio_udpbuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; 208 //Audio RTP 209 switch_codec_t audio_codec; 210 switch_rtp_t *rtp_session; 211 switch_port_t audio_local_port; 212 switch_port_t audio_remote_port; 213 switch_port_t audio_bridge_port; 214 switch_payload_t audio_codec_num; 215 char *audio_codec_name; 216 char *audio_codec_format; 217 switch_frame_t audio_frame; 218 //Video RTP 219 switch_codec_t video_codec; 220 switch_rtp_t *vrtp_session; 221 switch_port_t video_local_port; 222 switch_port_t video_remote_port; 223 switch_port_t video_bridge_port; 224 switch_payload_t video_codec_num; 225 char *video_codec_name; 226 char *video_codec_format; 227 switch_frame_t video_frame; 228 //Woomera Application Data 229 char audio_uri[WOOMERA_STRLEN]; 230 char video_uri[WOOMERA_STRLEN]; 231 char overlay[WOOMERA_STRLEN]; 232 char stop_digits[12+1]; 233 char repeat[WOOMERA_STRLEN]; /* Integer string (1..n) or "infinite" */ 234 int beep; 235 time_t wait_start; 236 int wait_timeout; 237 238 }; 239 240 typedef struct private_object private_object; 241 typedef struct woomera_message woomera_message; 242 typedef struct woomera_profile woomera_profile; 243 typedef struct woomera_event_queue woomera_event_queue; 244 245 static woomera_profile default_profile; 246 247 static char svrversion_init = 0; 248 static char svrversion[100] = "N/A"; 249 250 static switch_status_t woomera_on_init(switch_core_session_t *session); 251 static switch_status_t woomera_on_hangup(switch_core_session_t *session); 252 static switch_status_t woomera_on_routing(switch_core_session_t *session); 253 static switch_status_t woomera_on_exchange_media(switch_core_session_t *session); 254 static switch_status_t woomera_on_soft_execute(switch_core_session_t *session); 255 static switch_status_t woomera_on_reset(switch_core_session_t *session); 256 static switch_status_t woomera_on_destroy(switch_core_session_t *session); 257 258 static switch_call_cause_t woomera_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, 259 switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session, 260 switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause); 261 262 static switch_status_t woomera_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); 263 static switch_status_t woomera_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); 264 static switch_status_t woomera_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); 265 static switch_status_t woomera_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); 266 267 static switch_status_t woomera_kill_channel(switch_core_session_t *session, int sig); 268 static switch_status_t woomera_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf); 269 static switch_status_t woomera_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg); 270 static switch_status_t woomera_receive_event(switch_core_session_t *session, switch_event_t *event); 271 static switch_status_t woomera_answer_channel(switch_core_session_t *session); 272 273 static int setup_local_rtp_ports(private_object * tech_pvt); 274 static int create_rtp(private_object * tech_pvt); 275 static int woomera_parse_hello(private_object *tech_pvt, woomera_message wmsg); 276 static int woomera_setup_codec(private_object *tech_pvt); 277 static void woomera_printf(woomera_profile * profile, switch_socket_t *socket, char *fmt, ...); 278 static char *woomera_message_header(woomera_message * wmsg, char *key); 279 static int woomera_enqueue_event(woomera_event_queue * event_queue, woomera_message * wmsg); 280 static int woomera_dequeue_event(woomera_event_queue * event_queue, woomera_message * wmsg); 281 static int woomera_message_parse(switch_socket_t *fd, woomera_message * wmsg, int timeout, woomera_profile * profile, woomera_event_queue * event_queue); 282 static int connect_woomera(switch_socket_t **new_sock, woomera_profile * profile, int flags); 283 static int woomera_profile_thread_running(woomera_profile * profile, int set, int new); 284 static int woomera_locate_socket(woomera_profile * profile, switch_socket_t **woomera_socket); 285 286 static void *woomera_channel_thread_run(switch_thread_t *thread, void *obj); 287 static void *woomera_thread_run(void *obj); 288 289 static void woomera_playback(switch_core_session_t *session, const char *data); 290 static void woomera_background(switch_core_session_t *session, const char *data); 291 static void woomera_ringback(switch_core_session_t *session, const char *data); 292 static void woomera_stop(switch_core_session_t *session, const char *data); 293 static void woomera_waitfortone(switch_core_session_t *session, const char *data); 294 295 static void tech_destroy(private_object * tech_pvt); 296 static int tech_create_read_socket(private_object * tech_pvt); 297 static int tech_activate(private_object * tech_pvt); 298 299 300 301 /* 302 State methods they get called when the state changes to the specific state 303 returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next 304 so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it. 305 */ 306 static switch_status_t woomera_on_init(switch_core_session_t *session) 307 { 308 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_on_init()\n"); 309 310 switch_channel_t *channel = switch_core_session_get_channel(session); 311 struct private_object *tech_pvt = switch_core_session_get_private(session); 312 313 switch_assert(tech_pvt != NULL); 314 tech_pvt->audio_frame.data = tech_pvt->audio_udpbuf; 315 switch_set_flag_locked(tech_pvt, TFLAG_ACTIVATE); 316 switch_core_session_launch_thread(session, woomera_channel_thread_run, session); 317 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s WOOMERA INIT\n", switch_channel_get_name(channel)); 318 switch_channel_set_state(channel, CS_ROUTING); 319 return SWITCH_STATUS_SUCCESS; 320 } 321 322 static switch_status_t woomera_on_routing(switch_core_session_t *session) 323 { 324 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_on_routing()\n"); 325 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s WOOMERA ROUTING\n", switch_channel_get_name(switch_core_session_get_channel(session))); 326 return SWITCH_STATUS_SUCCESS; 327 } 328 329 static switch_status_t woomera_on_execute(switch_core_session_t *session) 330 { 331 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_on_execute()\n"); 332 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s WOOMERA EXECUTE\n", switch_channel_get_name(switch_core_session_get_channel(session))); 333 return SWITCH_STATUS_SUCCESS; 334 } 335 336 static switch_status_t woomera_on_reset(switch_core_session_t *session) 337 { 338 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_on_reset()\n"); 339 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s WOOMERA RESET\n", switch_channel_get_name(switch_core_session_get_channel(session))); 340 return SWITCH_STATUS_SUCCESS; 341 } 342 343 344 static switch_status_t woomera_on_hangup(switch_core_session_t *session) 345 { 346 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_on_hangup()\n"); 347 struct private_object *tech_pvt = switch_core_session_get_private(session); 348 switch_assert(tech_pvt != NULL); 349 350 switch_core_codec_destroy(&tech_pvt->audio_codec); 351 switch_core_codec_destroy(&tech_pvt->video_codec); 352 353 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s WOOMERA HANGUP\n", switch_channel_get_name(switch_core_session_get_channel(session))); 354 tech_destroy(tech_pvt); 355 356 return SWITCH_STATUS_SUCCESS; 357 } 358 359 static switch_status_t woomera_on_destroy(switch_core_session_t *session) 360 { 361 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_on_destroy()\n"); 362 struct private_object *tech_pvt = switch_core_session_get_private(session); 363 364 if (tech_pvt) { 365 if (tech_pvt->rtp_session) { 366 switch_rtp_destroy(&tech_pvt->rtp_session); 367 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NUKE Audio RTP\n"); 368 tech_pvt->rtp_session = NULL; 369 } 370 371 if (tech_pvt->vrtp_session) { 372 switch_rtp_destroy(&tech_pvt->vrtp_session); 373 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NUKE Video RTP\n"); 374 tech_pvt->vrtp_session = NULL; 375 } 376 377 if (switch_core_codec_ready(&tech_pvt->audio_codec)) { 378 switch_core_codec_destroy(&tech_pvt->audio_codec); 379 } 380 if (switch_core_codec_ready(&tech_pvt->video_codec)) { 381 switch_core_codec_destroy(&tech_pvt->video_codec); 382 } 383 } 384 385 return SWITCH_STATUS_SUCCESS; 386 } 387 388 389 static void woomera_socket_close(switch_socket_t **socket) 390 { 391 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_socket_close()\n"); 392 if (*socket) { 393 switch_socket_close(*socket); 394 *socket = NULL; 395 } 396 } 397 398 399 static void audio_udp_socket_close(struct private_object *tech_pvt) 400 { 401 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "udp_socket_close()\n"); 402 if (tech_pvt->audio_udp_socket) { 403 switch_socket_shutdown(tech_pvt->audio_udp_socket, SWITCH_SHUTDOWN_READWRITE); 404 woomera_socket_close(&tech_pvt->audio_udp_socket); 405 } 406 407 } 408 409 410 static switch_status_t woomera_kill_channel(switch_core_session_t *session, int sig) 411 { 412 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_kill_channel()\n"); 413 struct private_object *tech_pvt = switch_core_session_get_private(session); 414 switch_assert(tech_pvt != NULL); 415 416 if (!tech_pvt->audio_udp_socket) { 417 return SWITCH_STATUS_FALSE; 418 } 419 420 switch (sig) { 421 case SWITCH_SIG_KILL: 422 audio_udp_socket_close(tech_pvt); 423 if (switch_rtp_ready(tech_pvt->rtp_session)) { 424 switch_rtp_kill_socket(tech_pvt->rtp_session); 425 } 426 if (switch_rtp_ready(tech_pvt->vrtp_session)) { 427 switch_rtp_kill_socket(tech_pvt->vrtp_session); 428 } 429 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_kill_channel() SWITCH_SIG_KILL channel[%s]\n", switch_channel_get_name(switch_core_session_get_channel(session))); 430 break; 431 case SWITCH_SIG_BREAK: 432 { 433 if (switch_rtp_ready(tech_pvt->rtp_session)) { 434 switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_BREAK); 435 } 436 if (switch_rtp_ready(tech_pvt->vrtp_session)) { 437 switch_rtp_set_flag(tech_pvt->vrtp_session, SWITCH_RTP_FLAG_BREAK); 438 } 439 const char p = 0; 440 switch_size_t len = sizeof(p); 441 if (tech_pvt->audio_udp_socket && tech_pvt->audio_udpwrite) { 442 switch_socket_sendto(tech_pvt->audio_udp_socket, tech_pvt->audio_udpwrite, 0, &p, &len); 443 } 444 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_kill_channel() SWITCH_SIG_BREAK channel[%s]\n", switch_channel_get_name(switch_core_session_get_channel(session))); 445 } 446 break; 447 } 448 return SWITCH_STATUS_SUCCESS; 449 } 450 451 452 static switch_status_t woomera_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf) 453 { 454 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_send_dtmf()\n"); 455 /*TODO*/ 456 return SWITCH_STATUS_SUCCESS; 457 458 } 459 460 static switch_status_t woomera_answer_channel(switch_core_session_t *session) 461 { 462 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_answer_channel()\n"); 463 switch_channel_t *channel = switch_core_session_get_channel(session); 464 struct private_object *tech_pvt = switch_core_session_get_private(session); 465 466 switch_assert(tech_pvt != NULL); 467 468 if (!switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) { 469 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_answer_channel() - Set TFLAG_ANSWER\n"); 470 switch_set_flag_locked(tech_pvt, TFLAG_ANSWER); 471 } 472 473 while(switch_test_flag(tech_pvt, TFLAG_ANSWER)) { 474 switch_yield(10000); 475 switch_cond_next(); 476 } 477 switch_channel_mark_answered(channel); 478 return SWITCH_STATUS_SUCCESS; 479 } 480 481 482 static switch_status_t woomera_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg) 483 { 484 switch_channel_t *channel = switch_core_session_get_channel(session); 485 struct private_object *tech_pvt = switch_core_session_get_private(session); 486 487 switch_assert(tech_pvt != NULL); 488 489 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_receive_message() - channel:%s msg: %d\n", switch_channel_get_name(channel), msg->message_id); 490 491 switch (msg->message_id) { 492 case SWITCH_MESSAGE_INDICATE_ANSWER: 493 woomera_answer_channel(session); 494 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_ANSWER\n"); 495 break; 496 case SWITCH_MESSAGE_INDICATE_BRIDGE: 497 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_BRIDGE\n"); 498 if (switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) { 499 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - BRIDGE CALL\n"); 500 501 switch_core_session_message_t smsg = { 0 }; 502 smsg.message_id = SWITCH_MESSAGE_INDICATE_SIMPLIFY; 503 smsg.from = __FILE__; 504 switch_core_session_receive_message(session, &smsg); 505 } 506 break; 507 case SWITCH_MESSAGE_INDICATE_UNBRIDGE: 508 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_UNBRIDGE\n"); 509 break; 510 511 case SWITCH_MESSAGE_INDICATE_AUDIO_SYNC: 512 if (switch_rtp_ready(tech_pvt->rtp_session)) { 513 rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_ONCE); 514 } 515 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_AUDIO_SYNC\n"); 516 break; 517 518 519 case SWITCH_MESSAGE_REDIRECT_AUDIO: 520 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_REDIRECT_AUDIO\n"); 521 break; 522 case SWITCH_MESSAGE_TRANSMIT_TEXT: 523 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_TRANSMIT_TEXT\n"); 524 break; 525 526 case SWITCH_MESSAGE_INDICATE_PROGRESS: 527 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_PROGRESS\n"); 528 break; 529 530 case SWITCH_MESSAGE_INDICATE_TRANSFER: 531 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_TRANSFER\n"); 532 break; 533 case SWITCH_MESSAGE_INDICATE_RINGING: 534 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_RINGING\n"); 535 break; 536 case SWITCH_MESSAGE_INDICATE_MEDIA: 537 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_MEDIA\n"); 538 break; 539 case SWITCH_MESSAGE_INDICATE_NOMEDIA: 540 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_NOMEDIA\n"); 541 break; 542 case SWITCH_MESSAGE_INDICATE_HOLD: 543 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_HOLD\n"); 544 break; 545 case SWITCH_MESSAGE_INDICATE_UNHOLD: 546 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_UNHOLD\n"); 547 break; 548 case SWITCH_MESSAGE_INDICATE_REDIRECT: 549 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_REDIRECT\n"); 550 break; 551 case SWITCH_MESSAGE_INDICATE_RESPOND: 552 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_RESPOND\n"); 553 break; 554 case SWITCH_MESSAGE_INDICATE_BROADCAST: 555 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_BROADCAST\n"); 556 break; 557 case SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT: 558 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT\n"); 559 break; 560 case SWITCH_MESSAGE_INDICATE_DEFLECT: 561 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_DEFLECT\n"); 562 break; 563 case SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ: 564 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ\n"); 565 break; 566 case SWITCH_MESSAGE_INDICATE_DISPLAY: 567 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_DISPLAY\n"); 568 break; 569 case SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY: 570 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY\n"); 571 break; 572 case SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA: 573 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA\n"); 574 break; 575 case SWITCH_MESSAGE_INDICATE_UUID_CHANGE: 576 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_UUID_CHANGE\n"); 577 break; 578 case SWITCH_MESSAGE_INDICATE_SIMPLIFY: 579 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_SIMPLIFY\n"); 580 const char *uuid; 581 if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) { 582 switch_core_session_t *rsession; 583 if ((rsession = switch_core_session_locate(uuid))) { 584 struct private_object *rtech_pvt = switch_core_session_get_private(rsession); 585 switch_assert(rtech_pvt != NULL); 586 587 tech_pvt->audio_bridge_port = rtech_pvt->audio_remote_port; 588 tech_pvt->video_bridge_port = rtech_pvt->video_remote_port; 589 590 rtech_pvt->audio_bridge_port = tech_pvt->audio_remote_port; 591 rtech_pvt->video_bridge_port = tech_pvt->video_remote_port; 592 593 switch_set_flag(tech_pvt, TFLAG_BRIDGE); 594 switch_set_flag(rtech_pvt, TFLAG_BRIDGE); 595 switch_core_session_rwunlock(rsession); 596 } 597 } 598 break; 599 case SWITCH_MESSAGE_INDICATE_DEBUG_AUDIO: 600 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_DEBUG_AUDIO\n"); 601 break; 602 case SWITCH_MESSAGE_INDICATE_PROXY_MEDIA: 603 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_PROXY_MEDIA\n"); 604 break; 605 case SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC: 606 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC\n"); 607 break; 608 case SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC_COMPLETE: 609 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC_COMPLETE\n"); 610 break; 611 case SWITCH_MESSAGE_INVALID: 612 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE_INVALID\n"); 613 break; 614 615 default: 616 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "woomera_receive_message() - SWITCH_MESSAGE NOT SUPPORTED\n"); 617 break; 618 } 619 620 621 return SWITCH_STATUS_SUCCESS; 622 } 623 624 static switch_status_t woomera_receive_event(switch_core_session_t *session, switch_event_t *event) 625 { 626 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_receive_event()\n"); 627 return SWITCH_STATUS_SUCCESS; 628 } 629 630 631 static switch_status_t woomera_on_exchange_media(switch_core_session_t *session) 632 { 633 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "WOOMERA LOOPBACK\n"); 634 return SWITCH_STATUS_SUCCESS; 635 } 636 637 static switch_status_t woomera_on_soft_execute(switch_core_session_t *session) 638 { 639 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "WOOMERA TRANSMIT\n"); 640 return SWITCH_STATUS_SUCCESS; 641 } 642 643 static switch_status_t woomera_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) 644 { 645 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%lu] woomera_read_frame()\n", pthread_self()); 646 struct private_object *tech_pvt = switch_core_session_get_private(session); 647 switch_channel_t *channel = switch_core_session_get_channel(session); 648 switch_frame_t *pframe; 649 switch_status_t status; 650 651 switch_assert(tech_pvt != NULL); 652 653 while (!(tech_pvt->audio_codec.implementation && switch_rtp_ready(tech_pvt->rtp_session))) { 654 if (switch_channel_ready(channel)) { 655 switch_yield(10000); 656 } else { 657 return SWITCH_STATUS_GENERR; 658 } 659 } 660 661 switch_assert(tech_pvt->rtp_session != NULL); 662 pframe = &tech_pvt->audio_frame; 663 664 pframe->datalen = 0; 665 666 while (pframe->datalen == 0) 667 { 668 pframe->flags = SFF_NONE; 669 status = switch_rtp_zerocopy_read_frame(tech_pvt->rtp_session, pframe, flags); 670 if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) { 671 return status; 672 } 673 } 674 675 size_t bytes = 0; 676 int frames = 1; 677 678 if (!switch_test_flag((pframe), SFF_CNG)) { 679 if ((bytes = tech_pvt->audio_codec.implementation->encoded_bytes_per_packet)) { 680 frames = (pframe->datalen / bytes); 681 } 682 pframe->samples = (int) (frames * tech_pvt->audio_codec.implementation->samples_per_packet); 683 } 684 685 *frame = pframe; 686 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%lu] woomera_read_frame - EXIT - len:%d\n", pthread_self(), pframe->datalen); 687 return SWITCH_STATUS_SUCCESS; 688 } 689 690 691 static switch_status_t woomera_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id) 692 { 693 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%lu] woomera_write_frame()\n", pthread_self()); 694 struct private_object *tech_pvt = switch_core_session_get_private(session);; 695 switch_channel_t *channel = switch_core_session_get_channel(session); 696 697 switch_assert(tech_pvt != NULL); 698 699 while (!(tech_pvt->audio_codec.implementation && switch_rtp_ready(tech_pvt->rtp_session))) 700 { 701 if (switch_channel_ready(channel)) { 702 switch_yield(10000); 703 } 704 else { 705 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_write_frame - SWITCH_STATUS_GENERR4\n"); 706 return SWITCH_STATUS_GENERR; 707 } 708 } 709 if (!switch_core_codec_ready(&tech_pvt->audio_codec) || !tech_pvt->audio_codec.implementation) { 710 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_write_frame - SWITCH_STATUS_GENERR5\n"); 711 return SWITCH_STATUS_GENERR; 712 } 713 714 if (switch_rtp_write_frame(tech_pvt->rtp_session, frame) < 0) { 715 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_write_frame - SWITCH_STATUS_GENERR6\n"); 716 return SWITCH_STATUS_GENERR; 717 } 718 719 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%lu] woomera_write_frame() - EXIT \n", pthread_self()); 720 return SWITCH_STATUS_SUCCESS; 721 } 722 723 724 725 static switch_status_t woomera_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) 726 { 727 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%lu] woomera_read_video_frame()\n", pthread_self()); 728 struct private_object *tech_pvt = switch_core_session_get_private(session); 729 switch_channel_t *channel = switch_core_session_get_channel(session); 730 switch_frame_t *pframe; 731 switch_status_t status; 732 733 switch_assert(tech_pvt != NULL); 734 735 if (!tech_pvt->vrtp_session) { 736 return SWITCH_STATUS_GENERR; 737 } 738 739 while (!(tech_pvt->video_codec.implementation && switch_rtp_ready(tech_pvt->vrtp_session))) { 740 if (switch_channel_ready(channel)) { 741 switch_yield(10000); 742 } else { 743 return SWITCH_STATUS_GENERR; 744 } 745 } 746 747 pframe = &tech_pvt->video_frame; 748 switch_assert(tech_pvt->vrtp_session != NULL); 749 750 pframe->datalen = 0; 751 752 while (pframe->datalen == 0) 753 { 754 pframe->flags = SFF_NONE; 755 756 status = switch_rtp_zerocopy_read_frame(tech_pvt->vrtp_session, pframe, flags); 757 if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) { 758 if (status == SWITCH_STATUS_TIMEOUT) { 759 switch_channel_hangup(channel, SWITCH_CAUSE_MEDIA_TIMEOUT); 760 } 761 return status; 762 } 763 } 764 765 *frame = pframe; 766 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%lu] woomera_read_video_frame() - EXIT\n", pthread_self()); 767 return SWITCH_STATUS_SUCCESS; 768 } 769 770 771 static switch_status_t woomera_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id) 772 { 773 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%lu] woomera_write_video_frame()\n", pthread_self()); 774 struct private_object *tech_pvt = switch_core_session_get_private(session); 775 switch_channel_t *channel = switch_core_session_get_channel(session); 776 777 switch_assert(tech_pvt != NULL); 778 779 while (!(tech_pvt->video_codec.implementation && switch_rtp_ready(tech_pvt->vrtp_session))) { 780 if (switch_channel_ready(channel)) { 781 switch_yield(10000); 782 } else { 783 return SWITCH_STATUS_GENERR; 784 } 785 } 786 787 if (!switch_core_codec_ready(&tech_pvt->video_codec) || !tech_pvt->video_codec.implementation) { 788 return SWITCH_STATUS_GENERR; 789 } 790 791 if (switch_rtp_write_frame(tech_pvt->vrtp_session, frame) < 0 ) { 792 return SWITCH_STATUS_GENERR; 793 } 794 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%lu] woomera_write_video_frame() - EXIT\n", pthread_self()); 795 return SWITCH_STATUS_SUCCESS; 796 } 797 798 static switch_state_handler_table_t woomera_event_handlers = { 799 /*.on_init */ woomera_on_init, 800 /*.on_routing */ woomera_on_routing, 801 /*.on_execute */ woomera_on_execute, 802 /*.on_hangup */ woomera_on_hangup, 803 /*.on_exchange_media */ woomera_on_exchange_media, 804 /*.on_soft_execute */ woomera_on_soft_execute, 805 /*.on_consume_media*/ NULL, 806 /*.on_hibernate*/ NULL, 807 /*.on_reset*/ woomera_on_reset, 808 /*.on_park*/ NULL, 809 /*.on_reporting*/ NULL, 810 /*.on_destroy*/ woomera_on_destroy 811 }; 812 813 static switch_io_routines_t woomera_io_routines = { 814 /*.outgoing_channel */ woomera_outgoing_channel, 815 /*.read_frame */ woomera_read_frame, 816 /*.write_frame */ woomera_write_frame, 817 /*.kill_channel */ woomera_kill_channel, 818 /*.send_dtmf */ woomera_send_dtmf, 819 /*.receive_message */ woomera_receive_message, 820 /*.receive_event */ woomera_receive_event, 821 /*.state_change */ NULL, 822 /*.read_video_frame */ woomera_read_video_frame, 823 /*.write_video_frame */ woomera_write_video_frame 824 }; 825 826 /* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines 827 that allocate memory or you will have 1 channel with memory allocated from another channel's pool! 828 */ 829 static switch_call_cause_t woomera_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, 830 switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session, 831 switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause) 832 { 833 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_outgoing_channel()\n"); 834 if ((*new_session = switch_core_session_request(woomera_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, pool)) != 0) { 835 struct private_object *tech_pvt; 836 switch_channel_t *channel; 837 838 switch_core_session_add_stream(*new_session, NULL); 839 if ((tech_pvt = (struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object))) != 0) { 840 memset(tech_pvt, 0, sizeof(*tech_pvt)); 841 switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(*new_session)); 842 tech_pvt->profile = &default_profile; 843 channel = switch_core_session_get_channel(*new_session); 844 switch_core_session_set_private(*new_session, tech_pvt); 845 tech_pvt->session = *new_session; 846 } else { 847 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n"); 848 switch_core_session_destroy(new_session); 849 return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; 850 } 851 852 if (outbound_profile) { 853 char name[128]; 854 switch_caller_profile_t *caller_profile; 855 856 switch_snprintf(name, sizeof(name), "woomera/%s-%04x", outbound_profile->destination_number, rand() & 0xffff); 857 switch_channel_set_name(channel, name); 858 859 caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); 860 switch_channel_set_caller_profile(channel, caller_profile); 861 tech_pvt->caller_profile = caller_profile; 862 } else { 863 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh! no caller profile\n"); 864 switch_core_session_destroy(new_session); 865 return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; 866 } 867 868 switch_channel_set_flag(channel, CF_OUTBOUND); 869 switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND); 870 switch_channel_set_state(channel, CS_INIT); 871 return SWITCH_CAUSE_SUCCESS; 872 } 873 874 return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; 875 876 } 877 878 static void tech_destroy(private_object * tech_pvt) 879 { 880 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "tech_destroy()\n"); 881 woomera_message wmsg; 882 883 if (globals.debug > 1) { 884 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, WOOMERA_DEBUG_PREFIX "+++DESTROY\n"); 885 } 886 887 woomera_printf(tech_pvt->profile, tech_pvt->woomera_socket, 888 "HANGUP %s%s" 889 "Unique-Call-Id: %s%s" 890 "Reason: 16%s", 891 tech_pvt->call_info.callid, 892 WOOMERA_LINE_SEPERATOR, 893 tech_pvt->call_info.callid, 894 WOOMERA_LINE_SEPERATOR, 895 WOOMERA_RECORD_SEPERATOR); 896 897 if (woomera_message_parse(tech_pvt->woomera_socket, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, &tech_pvt->event_queue) < 0) { 898 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "{%s} HELP! Woomera is broken!\n", tech_pvt->profile->name); 899 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 900 globals.panic = 1; 901 } 902 903 //woomera_printf(tech_pvt->profile, tech_pvt->woomera_socket, "BYE%s", WOOMERA_RECORD_SEPERATOR); 904 905 woomera_socket_close(&tech_pvt->woomera_socket); 906 audio_udp_socket_close(tech_pvt); 907 } 908 909 910 static void woomera_printf(woomera_profile * profile, switch_socket_t *socket, char *fmt, ...) 911 { 912 char *stuff = NULL; 913 size_t res = 0, len = 0; 914 915 va_list ap; 916 va_start(ap, fmt); 917 #ifndef vasprintf 918 stuff = (char *) malloc(10240); 919 switch_assert(stuff); 920 res = vsnprintf(stuff, 10240, fmt, ap); 921 #else 922 res = vasprintf(&stuff, fmt, ap); 923 switch_assert(stuff); 924 #endif 925 va_end(ap); 926 if (res < 0) { 927 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Out of memory\n"); 928 } else { 929 if (profile && globals.debug) { 930 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send Message: {%s} [%s/%d]\n%s\n%s\n", profile->name, 931 profile->woomera_host, profile->woomera_port, WOOMERA_DEBUG_LINE, stuff); 932 } 933 len = strlen(stuff); 934 switch_socket_send(socket, stuff, &len); 935 } 936 937 if (stuff) { 938 free(stuff); 939 } 940 } 941 942 static char *woomera_message_header(woomera_message * wmsg, char *key) 943 { 944 int x = 0; 945 char *value = NULL; 946 947 for (x = 0; x < wmsg->last; x++) { 948 if (!strcasecmp(wmsg->names[x], key)) { 949 value = wmsg->values[x]; 950 break; 951 } 952 } 953 954 return value; 955 } 956 957 static int woomera_enqueue_event(woomera_event_queue * event_queue, woomera_message * wmsg) 958 { 959 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_enqueue_event()\n"); 960 woomera_message *new, *mptr; 961 962 if ((new = malloc(sizeof(woomera_message))) != 0) { 963 memcpy(new, wmsg, sizeof(woomera_message)); 964 new->next = NULL; 965 966 if (!event_queue->head) { 967 event_queue->head = new; 968 } else { 969 for (mptr = event_queue->head; mptr && mptr->next; mptr = mptr->next); 970 mptr->next = new; 971 } 972 return 1; 973 } else { 974 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Allocation Error!\n"); 975 } 976 977 return 0; 978 } 979 980 static int woomera_dequeue_event(woomera_event_queue * event_queue, woomera_message * wmsg) 981 { 982 woomera_message *mptr = NULL; 983 984 if (event_queue->head) { 985 mptr = event_queue->head; 986 event_queue->head = mptr->next; 987 } 988 989 if (mptr) { 990 memcpy(wmsg, mptr, sizeof(woomera_message)); 991 free(mptr); 992 return 1; 993 } else { 994 memset(wmsg, 0, sizeof(woomera_message)); 995 } 996 997 return 0; 998 } 999 1000 static int woomera_message_parse(switch_socket_t *fd, woomera_message * wmsg, int timeout, woomera_profile * profile, woomera_event_queue * event_queue) 1001 { 1002 char *cur, *cr, *next = NULL; 1003 char buf[2048] = "", *ptr; 1004 int bytes = 0; 1005 1006 memset(wmsg, 0, sizeof(woomera_message)); 1007 1008 if (!fd) { 1009 return -1; 1010 } 1011 1012 ptr = buf; 1013 bytes = 0; 1014 while (!strstr(buf, WOOMERA_RECORD_SEPERATOR)) { 1015 size_t len = 1; 1016 switch_status_t status; 1017 1018 if (!profile->thread_running) { 1019 return -1; 1020 } 1021 1022 switch_socket_timeout_set(fd, 1000000); 1023 status = switch_socket_recv(fd, ptr, &len); 1024 if (status == 70007) { 1025 return 0; 1026 } 1027 1028 if (status != SWITCH_STATUS_SUCCESS) { 1029 return -1; 1030 } 1031 ptr++; 1032 bytes++; 1033 } 1034 next = buf; 1035 1036 if (globals.debug) { 1037 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Receive Message: {%s} [%s/%d]\n%s\n%s\n", profile->name, 1038 profile->woomera_host, profile->woomera_port, WOOMERA_DEBUG_LINE, buf); 1039 } 1040 1041 while ((cur = next) != 0) { 1042 if ((cr = strstr(cur, WOOMERA_LINE_SEPERATOR)) != 0) { 1043 *cr = '\0'; 1044 next = cr + (sizeof(WOOMERA_LINE_SEPERATOR) - 1); 1045 if (!strcmp(next, WOOMERA_RECORD_SEPERATOR)) { 1046 break; 1047 } 1048 } 1049 if (wmsg->last > WOOMERA_ARRAY_LEN) { 1050 break; 1051 } 1052 1053 if (!cur || !cur[0]) { 1054 break; 1055 } 1056 1057 if (!wmsg->last) { 1058 switch_set_flag(wmsg, WFLAG_EXISTS); 1059 if (!strncasecmp(cur, "EVENT", 5)) { 1060 cur += 6; 1061 switch_set_flag(wmsg, WFLAG_EVENT); 1062 1063 if (cur && (cr = strchr(cur, ' ')) != 0) { 1064 char *id; 1065 1066 *cr = '\0'; 1067 cr++; 1068 id = cr; 1069 if (cr && (cr = strchr(cr, ' ')) != 0) { 1070 *cr = '\0'; 1071 cr++; 1072 switch_copy_string(wmsg->command_args, cr, WOOMERA_STRLEN); 1073 } 1074 if (id) { 1075 switch_copy_string(wmsg->callid, id, sizeof(wmsg->callid) - 1); 1076 } 1077 } 1078 } else { 1079 if (cur && (cur = strchr(cur, ' ')) != 0) { 1080 *cur = '\0'; 1081 cur++; 1082 wmsg->mval = atoi(buf); 1083 } else { 1084 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Malformed Message!\n"); 1085 break; 1086 } 1087 } 1088 if (cur) { 1089 switch_copy_string(wmsg->command, cur, WOOMERA_STRLEN); 1090 } else { 1091 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Malformed Message!\n"); 1092 break; 1093 } 1094 } else { 1095 char *name, *val; 1096 name = cur; 1097 if ((val = strchr(name, ':')) != 0) { 1098 *val = '\0'; 1099 val++; 1100 while (*val == ' ') { 1101 *val = '\0'; 1102 val++; 1103 } 1104 switch_copy_string(wmsg->values[wmsg->last - 1], val, WOOMERA_STRLEN); 1105 } 1106 switch_copy_string(wmsg->names[wmsg->last - 1], name, WOOMERA_STRLEN); 1107 if (name && val && !strcasecmp(name, "content-type")) { 1108 switch_set_flag(wmsg, WFLAG_CONTENT); 1109 bytes = atoi(val); 1110 } 1111 if (name && val && !strcasecmp(name, "content-length")) { 1112 switch_set_flag(wmsg, WFLAG_CONTENT); 1113 bytes = atoi(val); 1114 } 1115 1116 } 1117 wmsg->last++; 1118 } 1119 1120 wmsg->last--; 1121 if (bytes && switch_test_flag(wmsg, WFLAG_CONTENT)) { 1122 size_t len = (bytes > sizeof(wmsg->body)) ? sizeof(wmsg->body) : bytes; 1123 switch_socket_recv(fd, wmsg->body, &len); 1124 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s\n", wmsg->body); 1125 } 1126 1127 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "command:%s\n", wmsg->command); 1128 if (event_queue && switch_test_flag(wmsg, WFLAG_EVENT)) { 1129 if (globals.debug) { 1130 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Queue Event: {%s} [%s]\n", profile->name, wmsg->command); 1131 } 1132 /* we don't want events we want a reply so we will stash them for later */ 1133 woomera_enqueue_event(event_queue, wmsg); 1134 1135 /* call ourself recursively to find the reply. we'll keep doing this as long we get events. 1136 * wmsg will be overwritten but it's ok we just queued it. 1137 */ 1138 return woomera_message_parse(fd, wmsg, timeout, profile, event_queue); 1139 1140 } else if (wmsg->mval > 99 && wmsg->mval < 200) { 1141 /* reply in the 100's are nice but we need to wait for another reply 1142 call ourself recursively to find the reply > 199 and forget this reply. 1143 */ 1144 return woomera_message_parse(fd, wmsg, timeout, profile, event_queue); 1145 1146 } else { //200 complete 1147 return switch_test_flag(wmsg, WFLAG_EXISTS); 1148 } 1149 } 1150 1151 1152 static int connect_woomera(switch_socket_t **new_sock, woomera_profile * profile, int flags) 1153 { 1154 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "connect_woomera()\n"); 1155 switch_sockaddr_t *sa; 1156 1157 if (switch_sockaddr_info_get(&sa, profile->woomera_host, AF_INET, profile->woomera_port, 0, module_pool) != SWITCH_STATUS_SUCCESS) { 1158 return -1; 1159 } 1160 1161 if (switch_socket_create(new_sock, AF_INET, SOCK_STREAM, 0, module_pool) != SWITCH_STATUS_SUCCESS) { 1162 return -1; 1163 } 1164 1165 switch_socket_timeout_set((*new_sock), 10000000); 1166 switch_socket_opt_set((*new_sock), SWITCH_SO_KEEPALIVE, 1); 1167 1168 if (switch_socket_connect((*new_sock), sa) != SWITCH_STATUS_SUCCESS) { 1169 return -1; 1170 } 1171 1172 return 1; 1173 } 1174 1175 static int woomera_profile_thread_running(woomera_profile * profile, int set, int new) 1176 { 1177 int running = 0; 1178 1179 switch_mutex_lock(profile->iolock); 1180 if (set) { 1181 profile->thread_running = new; 1182 } 1183 running = profile->thread_running; 1184 switch_mutex_unlock(profile->iolock); 1185 return running; 1186 1187 } 1188 1189 static int woomera_locate_socket(woomera_profile * profile, switch_socket_t **woomera_socket) 1190 { 1191 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_locate_socket()\n"); 1192 woomera_message wmsg; 1193 1194 for (;;) { 1195 1196 while (connect_woomera(woomera_socket, profile, 0) < 0) { 1197 if (!woomera_profile_thread_running(profile, 0, 0)) { 1198 break; 1199 } 1200 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "{%s} Cannot Reconnect to Woomera! retry in 5 seconds\n", profile->name); 1201 switch_sleep(WOOMERA_RECONNECT_TIME); 1202 } 1203 1204 if (*woomera_socket) { 1205 if (switch_test_flag(profile, PFLAG_INBOUND)) { 1206 woomera_printf(profile, *woomera_socket, "LISTEN%s", WOOMERA_RECORD_SEPERATOR); 1207 if (woomera_message_parse(*woomera_socket, &wmsg, WOOMERA_HARD_TIMEOUT, profile, &profile->event_queue) < 0) { 1208 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "{%s} HELP! Woomera is broken!\n", profile->name); 1209 globals.panic = 1; 1210 woomera_profile_thread_running(&default_profile, 1, 0); 1211 svrversion_init = 0; 1212 switch_sleep(WOOMERA_RECONNECT_TIME); 1213 if (*woomera_socket) { 1214 woomera_socket_close(woomera_socket); 1215 } 1216 continue; 1217 } 1218 } 1219 1220 } 1221 switch_sleep(100); 1222 break; 1223 } 1224 return *woomera_socket ? 1 : 0; 1225 } 1226 1227 1228 /*! 1229 * \brief Setup local rtp ports 1230 */ 1231 static int setup_local_rtp_ports(private_object * tech_pvt) 1232 { 1233 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "setup_local_rtp_ports()\n"); 1234 1235 // Local audio rtp port 1236 if (switch_test_flag(tech_pvt->profile, PFLAG_RTP)) { 1237 if (!(tech_pvt->audio_local_port = switch_rtp_request_port(tech_pvt->profile->audio_ip))) { 1238 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No RTP port available!\n"); 1239 return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; 1240 } 1241 } 1242 // Local video rtp port 1243 if (switch_test_flag(tech_pvt->profile, PFLAG_VIDEORTP)) { 1244 if (!(tech_pvt->video_local_port = switch_rtp_request_port(tech_pvt->profile->audio_ip))) { 1245 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No RTP port available!\n"); 1246 return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; 1247 } 1248 } 1249 return 0; 1250 } 1251 1252 /*! 1253 * \brief Create an rtp session. 1254 */ 1255 static int create_rtp(private_object * tech_pvt) 1256 { 1257 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "create_rtp()\n"); 1258 const char *err; 1259 switch_rtp_flag_t flags = SWITCH_RTP_FLAG_DATAWAIT | SWITCH_RTP_FLAG_GOOGLEHACK | SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_RAW_WRITE | SWITCH_RTP_FLAG_AUTO_CNG; 1260 switch_channel_t *channel = switch_core_session_get_channel(tech_pvt->session); 1261 1262 tech_pvt->audio_udp_socket = NULL; 1263 1264 // Create Audio RTP 1265 if (switch_test_flag(tech_pvt->profile, PFLAG_RTP)) { 1266 tech_pvt->profile->timer_name = switch_core_strdup(module_pool, "soft"); 1267 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "create_rtp()- Audio RTP \n ip:%s\n port:%d\n woomera_host:%s\n audio_remote_port:%d\n audio_codec_num:%d\n samples_per_packet:%d\n microseconds_per_packet:%d\n timer_name:%s\n", 1268 tech_pvt->profile->audio_ip, 1269 tech_pvt->audio_local_port, 1270 tech_pvt->profile->woomera_host, 1271 tech_pvt->audio_remote_port, 1272 tech_pvt->audio_codec_num, 1273 tech_pvt->audio_codec.implementation->samples_per_packet, 1274 tech_pvt->audio_codec.implementation->microseconds_per_packet, 1275 tech_pvt->profile->timer_name); 1276 1277 if (!(tech_pvt->rtp_session = switch_rtp_new(tech_pvt->profile->audio_ip, 1278 tech_pvt->audio_local_port, 1279 tech_pvt->profile->woomera_host, 1280 tech_pvt->audio_remote_port, 1281 tech_pvt->audio_codec_num, 1282 tech_pvt->audio_codec.implementation->samples_per_packet, 1283 tech_pvt->audio_codec.implementation->microseconds_per_packet, 1284 flags, tech_pvt->profile->timer_name, &err, switch_core_session_get_pool(tech_pvt->session)))) 1285 { 1286 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "RTP ERROR %s\n", err); 1287 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); 1288 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 1289 return 0; 1290 } 1291 else 1292 { 1293 switch_rtp_set_cng_pt(tech_pvt->rtp_session, 13); 1294 switch_rtp_set_telephony_event(tech_pvt->rtp_session, 101); 1295 } 1296 } 1297 // Create Video RTP 1298 if (switch_test_flag(tech_pvt->profile, PFLAG_VIDEORTP)) { 1299 // tech_pvt->profile->timer_name = switch_core_strdup(module_pool, "none"); 1300 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "create_rtp() - Video RTP \n ip:%s\n port:%d\n woomera_host:%s\n remote_port:%d\n video_codec_num:%d\n samples_per_packet:%d\n microseconds_per_packet:%d\n timer_name:%s\n", 1301 tech_pvt->profile->audio_ip, 1302 tech_pvt->video_local_port, 1303 tech_pvt->profile->woomera_host, 1304 tech_pvt->video_remote_port, 1305 tech_pvt->video_codec_num, 1306 tech_pvt->video_codec.implementation->samples_per_packet, 1307 tech_pvt->video_codec.implementation->microseconds_per_packet, 1308 tech_pvt->profile->timer_name); 1309 1310 if (!(tech_pvt->vrtp_session = switch_rtp_new(tech_pvt->profile->audio_ip, 1311 tech_pvt->video_local_port, 1312 tech_pvt->profile->woomera_host, 1313 tech_pvt->video_remote_port, 1314 tech_pvt->video_codec_num, 1315 tech_pvt->video_codec.implementation->samples_per_packet, 1316 tech_pvt->video_codec.implementation->microseconds_per_packet, 1317 flags, tech_pvt->profile->timer_name, &err, switch_core_session_get_pool(tech_pvt->session)))) 1318 { 1319 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "RTP ERROR %s\n", err); 1320 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); 1321 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 1322 return 0; 1323 } 1324 else 1325 { 1326 switch_channel_set_flag(channel, CF_VIDEO); 1327 } 1328 } 1329 switch_set_flag_locked(tech_pvt, TFLAG_MEDIA); 1330 return 0; 1331 } 1332 1333 static int tech_create_read_socket(private_object * tech_pvt) 1334 { 1335 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "tech_create_read_socket()\n"); 1336 1337 switch_memory_pool_t *pool = switch_core_session_get_pool(tech_pvt->session); 1338 1339 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "connect raw audio %s:%d\n", tech_pvt->profile->audio_ip, tech_pvt->audio_local_port); 1340 switch_sockaddr_info_get(&tech_pvt->audio_udpread, tech_pvt->profile->audio_ip, SWITCH_UNSPEC, tech_pvt->audio_local_port, 0, pool); 1341 if (switch_socket_create(&tech_pvt->audio_udp_socket, AF_INET, SOCK_DGRAM, 0, pool) == SWITCH_STATUS_SUCCESS) { 1342 switch_socket_bind(tech_pvt->audio_udp_socket, tech_pvt->audio_udpread); 1343 // switch_socket_create_pollfd(&tech_pvt->read_poll, tech_pvt->audio_udp_socket, SWITCH_POLLIN | SWITCH_POLLERR, pool); 1344 // switch_socket_create_pollfd(&tech_pvt->write_poll, tech_pvt->audio_udp_socket, SWITCH_POLLOUT | SWITCH_POLLERR, pool); 1345 switch_set_flag_locked(tech_pvt, TFLAG_MEDIA); 1346 } else { 1347 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 1348 } 1349 return 0; 1350 } 1351 1352 static int woomera_parse_hello(private_object *tech_pvt, woomera_message wmsg) 1353 { 1354 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_parse_hello()\n"); 1355 char *audio_format, *video_format; 1356 1357 if (!svrversion_init && woomera_message_header(&wmsg, "Version")) { 1358 svrversion_init = 1; 1359 strncpy(svrversion, woomera_message_header(&wmsg, "Version"), sizeof(svrversion)-1); 1360 } 1361 1362 audio_format = woomera_message_header(&wmsg, "Raw-Format"); 1363 if (!audio_format) { 1364 audio_format = woomera_message_header(&wmsg, "Raw-Audio-Format"); 1365 } 1366 if (!audio_format) { 1367 audio_format = woomera_message_header(&wmsg, "RTP-Audio-Format"); 1368 } 1369 1370 if (audio_format) { 1371 tech_pvt->audio_codec_num = 0; 1372 tech_pvt->audio_codec_format = audio_format; 1373 tech_pvt->audio_codec_name = "PCMU"; 1374 1375 if (strncasecmp(audio_format, "PCM-16", 6) == 0) { 1376 tech_pvt->audio_codec_num = 118; 1377 tech_pvt->audio_codec_name = "L16"; 1378 } else if (strncasecmp(audio_format, "ULAW", 4) == 0) { 1379 tech_pvt->audio_codec_num = 0; 1380 tech_pvt->audio_codec_name = "PCMU"; 1381 } else if (strncasecmp(audio_format, "PCMU", 4) == 0) { 1382 tech_pvt->audio_codec_num = 0; 1383 tech_pvt->audio_codec_name = "PCMU"; 1384 } else if (strncasecmp(audio_format, "ALAW", 4) == 0) { 1385 tech_pvt->audio_codec_num = 8; 1386 tech_pvt->audio_codec_name = "PCMA"; 1387 } else if (strncasecmp(audio_format, "PCMA", 4) == 0) { 1388 tech_pvt->audio_codec_num = 8; 1389 tech_pvt->audio_codec_name = "PCMA"; 1390 } else { 1391 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Error: Invalid audio format %s\n", 1392 tech_pvt->audio_codec_name); 1393 } 1394 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Setting audio format to:%s coding:%i\n", 1395 tech_pvt->audio_codec_name, tech_pvt->audio_codec_num); 1396 } 1397 1398 video_format = woomera_message_header(&wmsg, "RTP-Video-Format"); 1399 if (video_format) { 1400 tech_pvt->video_codec_num = 31; 1401 tech_pvt->video_codec_format = video_format; 1402 tech_pvt->video_codec_name = "PROXY-VID"; 1403 1404 if (strncasecmp(video_format, "H261", 4) == 0) { 1405 tech_pvt->video_codec_num = 31; 1406 tech_pvt->video_codec_name = "PROXY-VID"; 1407 } else if (strncasecmp(video_format, "H263", 4) == 0) { 1408 tech_pvt->video_codec_num = 31; 1409 tech_pvt->video_codec_name = "PROXY-VID"; 1410 } else if (strncasecmp(video_format, "H263-1998", 9) == 0) { 1411 tech_pvt->video_codec_num = 31; 1412 tech_pvt->video_codec_name = "PROXY-VID"; 1413 } else if (strncasecmp(video_format, "H264", 4) == 0) { 1414 tech_pvt->video_codec_num = 31; 1415 tech_pvt->video_codec_name = "PROXY-VID"; 1416 } else if (strncasecmp(video_format, "MPV4-ES", 5) == 0) { 1417 tech_pvt->video_codec_num = 31; 1418 tech_pvt->video_codec_name = "PROXY-VID"; 1419 } else { 1420 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Error: Invalid video format %s\n", tech_pvt->video_codec_name); 1421 } 1422 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Setting video format to:%s coding:%i\n", 1423 tech_pvt->video_codec_name, tech_pvt->video_codec_num); 1424 1425 } 1426 return 0; 1427 } 1428 1429 static int woomera_setup_codec(private_object *tech_pvt) 1430 { 1431 switch_channel_t *channel = switch_core_session_get_channel(tech_pvt->session); 1432 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_setup_codec()\n"); 1433 1434 // Setup the audio codec 1435 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_setup_codec() audio_codec_name:%s\n", tech_pvt->audio_codec_name); 1436 tech_pvt->audio_frame.rate = 8000; 1437 if (switch_core_codec_init 1438 (&tech_pvt->audio_codec, tech_pvt->audio_codec_name, NULL, tech_pvt->audio_frame.rate, 20, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, 1439 switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) 1440 { 1441 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s Cannot set audio codec\n", switch_channel_get_name(channel)); 1442 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); 1443 return SWITCH_STATUS_FALSE; 1444 } 1445 tech_pvt->audio_frame.codec = &tech_pvt->audio_codec; 1446 switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->audio_codec); 1447 switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->audio_codec); 1448 1449 // Setup the video codec 1450 if (switch_test_flag(tech_pvt->profile, PFLAG_VIDEORTP)) { 1451 tech_pvt->video_frame.rate = 90000; 1452 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_setup_codec() video_codec_name:%s\n", tech_pvt->video_codec_name); 1453 if (switch_core_codec_init 1454 (&tech_pvt->video_codec, tech_pvt->video_codec_name, NULL, tech_pvt->video_frame.rate, 0, 1, SWITCH_CODEC_FLAG_PASSTHROUGH, NULL, 1455 switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) 1456 { 1457 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s Cannot set video codec\n", switch_channel_get_name(channel)); 1458 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); 1459 return SWITCH_STATUS_FALSE; 1460 } 1461 1462 tech_pvt->video_frame.codec = &tech_pvt->video_codec; 1463 switch_core_session_set_video_read_codec(tech_pvt->session, &tech_pvt->video_codec); 1464 switch_core_session_set_video_write_codec(tech_pvt->session, &tech_pvt->video_codec); 1465 1466 } 1467 return 0; 1468 } 1469 1470 static int tech_activate(private_object * tech_pvt) 1471 { 1472 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "tech_activate()\n"); 1473 woomera_message wmsg; 1474 1475 if (tech_pvt) { 1476 1477 if ((connect_woomera(&tech_pvt->woomera_socket, tech_pvt->profile, 0))) { 1478 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "connected to woomera!\n"); 1479 /* Wait for the HELLO back from Woomera */ 1480 if (woomera_message_parse(tech_pvt->woomera_socket, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, NULL) < 0) { 1481 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "{%s} HELP! Woomera is broken!\n", tech_pvt->profile->name); 1482 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 1483 globals.panic = 1; 1484 } 1485 woomera_parse_hello(tech_pvt, wmsg); 1486 woomera_setup_codec(tech_pvt); 1487 if ((switch_test_flag(tech_pvt->profile, PFLAG_RTP)) || (switch_test_flag(tech_pvt->profile, PFLAG_VIDEORTP))) { 1488 setup_local_rtp_ports(tech_pvt); 1489 } 1490 else { 1491 tech_create_read_socket(tech_pvt); 1492 } 1493 } else { 1494 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't connect to woomera!\n"); 1495 switch_sleep(WOOMERA_RECONNECT_TIME); 1496 return -1; 1497 } 1498 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Got my HELLO. Crack on!\n"); 1499 if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) { 1500 1501 if (switch_test_flag(tech_pvt->profile, PFLAG_RTP)) { 1502 1503 woomera_printf(tech_pvt->profile, tech_pvt->woomera_socket, 1504 "CALL %s%s" 1505 "RTP-Audio: %s:%d%s" 1506 "RTP-Video: %s:%d%s" 1507 "Local-Name: %s!%s%s" 1508 "Local-Number:%s%s", 1509 tech_pvt->caller_profile->destination_number, 1510 WOOMERA_LINE_SEPERATOR, 1511 tech_pvt->profile->audio_ip, 1512 tech_pvt->audio_local_port, 1513 WOOMERA_LINE_SEPERATOR, 1514 tech_pvt->profile->audio_ip, 1515 tech_pvt->video_local_port, 1516 WOOMERA_LINE_SEPERATOR, 1517 tech_pvt->caller_profile->caller_id_name, 1518 tech_pvt->caller_profile->caller_id_number, 1519 WOOMERA_LINE_SEPERATOR, 1520 tech_pvt->caller_profile->caller_id_number, 1521 WOOMERA_RECORD_SEPERATOR 1522 ); 1523 } else { 1524 woomera_printf(tech_pvt->profile, tech_pvt->woomera_socket, 1525 "CALL %s%s" 1526 "Raw-Audio: %s:%d%s" 1527 "Local-Name: %s!%s%s" 1528 "Local-Number:%s%s", 1529 tech_pvt->caller_profile->destination_number, 1530 WOOMERA_LINE_SEPERATOR, 1531 tech_pvt->profile->audio_ip, 1532 tech_pvt->audio_local_port, 1533 WOOMERA_LINE_SEPERATOR, 1534 tech_pvt->caller_profile->caller_id_name, 1535 tech_pvt->caller_profile->caller_id_number, 1536 WOOMERA_LINE_SEPERATOR, 1537 tech_pvt->caller_profile->caller_id_number, 1538 WOOMERA_RECORD_SEPERATOR 1539 ); 1540 } 1541 woomera_message_parse(tech_pvt->woomera_socket, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, &tech_pvt->event_queue); 1542 } 1543 } 1544 else 1545 { 1546 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Where's my tech_pvt?\n"); 1547 } 1548 return 0; 1549 } 1550 1551 1552 static void *woomera_channel_thread_run(switch_thread_t *thread, void *obj) 1553 { 1554 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_channel_thread_run()\n"); 1555 switch_core_session_t *session = obj; 1556 switch_channel_t *channel = switch_core_session_get_channel(session); 1557 struct private_object *tech_pvt = switch_core_session_get_private(session); 1558 woomera_message wmsg; 1559 int res = 0; 1560 1561 switch_assert(tech_pvt != NULL); 1562 1563 for (;;) { 1564 if (globals.panic) { 1565 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 1566 } 1567 1568 if (switch_test_flag(tech_pvt, TFLAG_ABORT)) { 1569 switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); 1570 audio_udp_socket_close(tech_pvt); 1571 break; 1572 } 1573 1574 if (switch_test_flag(tech_pvt, TFLAG_ACTIVATE)) { 1575 switch_clear_flag_locked(tech_pvt, TFLAG_ACTIVATE); 1576 tech_activate(tech_pvt); 1577 } 1578 1579 if (switch_test_flag(tech_pvt, TFLAG_INCOMING)) { 1580 switch_clear_flag_locked(tech_pvt, TFLAG_INCOMING); 1581 1582 if (switch_test_flag(tech_pvt->profile, PFLAG_VIDEORTP)) { 1583 woomera_printf(tech_pvt->profile, tech_pvt->woomera_socket, 1584 "ACCEPT %s%s" 1585 "RTP-Audio: %s:%d%s" 1586 "RTP-Audio-Format: %s%s" 1587 "RTP-Video: %s:%d%s" 1588 "RTP-Video-Format: %s%s" 1589 "Unique-Call-Id: %s%s", 1590 tech_pvt->call_info.callid, 1591 WOOMERA_LINE_SEPERATOR, 1592 tech_pvt->profile->audio_ip, 1593 tech_pvt->audio_local_port, 1594 WOOMERA_LINE_SEPERATOR, 1595 tech_pvt->audio_codec_format, 1596 WOOMERA_LINE_SEPERATOR, 1597 tech_pvt->profile->audio_ip, 1598 tech_pvt->video_local_port, 1599 WOOMERA_LINE_SEPERATOR, 1600 tech_pvt->video_codec_format, 1601 WOOMERA_LINE_SEPERATOR, 1602 tech_pvt->call_info.callid, 1603 WOOMERA_RECORD_SEPERATOR); 1604 } else { 1605 woomera_printf(tech_pvt->profile, tech_pvt->woomera_socket, 1606 "ACCEPT %s%s" 1607 "RTP-Audio: %s:%d%s" 1608 "RTP-Audio-Format: %s%s" 1609 "Unique-Call-Id: %s%s", 1610 tech_pvt->call_info.callid, 1611 WOOMERA_LINE_SEPERATOR, 1612 tech_pvt->profile->audio_ip, 1613 tech_pvt->audio_local_port, 1614 WOOMERA_LINE_SEPERATOR, 1615 tech_pvt->audio_codec_format, 1616 WOOMERA_LINE_SEPERATOR, 1617 tech_pvt->call_info.callid, 1618 WOOMERA_RECORD_SEPERATOR); 1619 } 1620 1621 if (woomera_message_parse(tech_pvt->woomera_socket, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, &tech_pvt->event_queue) < 0) { 1622 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "{%s} HELP! Woomera is broken!\n", tech_pvt->profile->name); 1623 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 1624 globals.panic = 1; 1625 continue; 1626 } 1627 if ( 200 == wmsg.mval ) 1628 { 1629 for (int n=0; n < wmsg.last; n++) 1630 { 1631 if ( !strcasecmp(wmsg.names[n], "RTP-Audio")) 1632 { 1633 char* port = strchr(wmsg.values[n], ':'); 1634 if (port) 1635 { 1636 *port = '\0'; 1637 port++; 1638 tech_pvt->audio_remote_port = atoi(port); 1639 } 1640 } 1641 if ( (!strcasecmp(wmsg.names[n], "RTP-Video")) && switch_test_flag(tech_pvt->profile, PFLAG_VIDEORTP) ) 1642 { 1643 char* port = strchr(wmsg.values[n], ':'); 1644 if (port) 1645 { 1646 *port = '\0'; 1647 port++; 1648 tech_pvt->video_remote_port = atoi(port); 1649 } 1650 } 1651 } 1652 } 1653 create_rtp(tech_pvt); 1654 } 1655 1656 if (switch_test_flag(tech_pvt, TFLAG_ANSWER)) { 1657 if (switch_test_flag(tech_pvt->profile, PFLAG_VIDEORTP)) { 1658 woomera_printf(tech_pvt->profile, tech_pvt->woomera_socket, 1659 "ANSWER %s%s" 1660 "RTP-Audio: %s:%d%s" 1661 "RTP-Audio-Format: %s%s" 1662 "RTP-Video: %s:%d%s" 1663 "RTP-Video-Format: %s%s" 1664 "Unique-Call-Id: %s%s", 1665 tech_pvt->call_info.callid, 1666 WOOMERA_LINE_SEPERATOR, 1667 tech_pvt->profile->audio_ip, 1668 tech_pvt->audio_local_port, 1669 WOOMERA_LINE_SEPERATOR, 1670 tech_pvt->audio_codec_format, 1671 WOOMERA_LINE_SEPERATOR, 1672 tech_pvt->profile->audio_ip, 1673 tech_pvt->video_local_port, 1674 WOOMERA_LINE_SEPERATOR, 1675 tech_pvt->video_codec_format, 1676 WOOMERA_LINE_SEPERATOR, 1677 tech_pvt->call_info.callid, 1678 WOOMERA_RECORD_SEPERATOR); 1679 } else { 1680 woomera_printf(tech_pvt->profile, tech_pvt->woomera_socket, 1681 "ANSWER %s%s" 1682 "RTP-Audio: %s:%d%s" 1683 "RTP-Audio-Format: %s%s" 1684 "Unique-Call-Id: %s%s", 1685 tech_pvt->call_info.callid, 1686 WOOMERA_LINE_SEPERATOR, 1687 tech_pvt->profile->audio_ip, 1688 tech_pvt->audio_local_port, 1689 WOOMERA_LINE_SEPERATOR, 1690 tech_pvt->audio_codec_format, 1691 WOOMERA_LINE_SEPERATOR, 1692 tech_pvt->call_info.callid, 1693 WOOMERA_RECORD_SEPERATOR); 1694 } 1695 if (woomera_message_parse(tech_pvt->woomera_socket, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, &tech_pvt->event_queue) < 0) { 1696 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "{%s} HELP! Woomera is broken!\n", tech_pvt->profile->name); 1697 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 1698 globals.panic = 1; 1699 continue; 1700 } 1701 switch_clear_flag_locked(tech_pvt, TFLAG_ANSWER); 1702 switch_set_flag_locked(tech_pvt, TFLAG_CONNECTED); 1703 } 1704 1705 if (switch_test_flag(tech_pvt, TFLAG_DTMF)) { 1706 switch_mutex_lock(tech_pvt->iolock); 1707 woomera_printf(tech_pvt->profile, tech_pvt->woomera_socket, "DTMF %s %s%s", tech_pvt->call_info.callid, 1708 tech_pvt->dtmfbuf, WOOMERA_RECORD_SEPERATOR); 1709 if (woomera_message_parse(tech_pvt->woomera_socket, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, &tech_pvt->event_queue) < 0) { 1710 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "{%s} HELP! Woomera is broken!\n", tech_pvt->profile->name); 1711 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 1712 globals.panic = 1; 1713 continue; 1714 } 1715 switch_clear_flag_locked(tech_pvt, TFLAG_DTMF); 1716 memset(tech_pvt->dtmfbuf, 0, sizeof(tech_pvt->dtmfbuf)); 1717 switch_mutex_unlock(tech_pvt->iolock); 1718 } 1719 1720 if (switch_test_flag(tech_pvt, TFLAG_PLAY)) { 1721 woomera_printf(tech_pvt->profile, tech_pvt->woomera_socket, 1722 "PLAY%s" 1723 "Unique-Call-Id: %s%s" 1724 "Audio-Uri: %s%s" 1725 "Video-Uri: %s%s" 1726 "Overlay: %s%s" 1727 "Stop-Digits: %s%s" 1728 "Language: %s%s" 1729 "Repeat: %s%s", 1730 WOOMERA_LINE_SEPERATOR, 1731 tech_pvt->call_info.callid, 1732 WOOMERA_LINE_SEPERATOR, 1733 tech_pvt->audio_uri, 1734 WOOMERA_LINE_SEPERATOR, 1735 tech_pvt->video_uri, 1736 WOOMERA_LINE_SEPERATOR, 1737 tech_pvt->overlay, 1738 WOOMERA_LINE_SEPERATOR, 1739 tech_pvt->stop_digits, 1740 WOOMERA_LINE_SEPERATOR, 1741 tech_pvt->profile->language, 1742 WOOMERA_LINE_SEPERATOR, 1743 tech_pvt->repeat, 1744 WOOMERA_RECORD_SEPERATOR 1745 ); 1746 switch_clear_flag_locked(tech_pvt, TFLAG_PLAY); 1747 if (woomera_message_parse(tech_pvt->woomera_socket, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, &tech_pvt->event_queue) < 0) { 1748 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "{%s} PLAY ABORT!\n", tech_pvt->profile->name); 1749 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 1750 globals.panic = 1; 1751 continue; 1752 } 1753 if ( wmsg.mval > 200 ) { 1754 switch_channel_set_variable(channel, "WOOMERAPLAYSTATUS", "error"); 1755 switch_channel_set_variable(channel, "WOOMERAPLAYDURATION", "0"); 1756 switch_set_flag_locked(tech_pvt, TFLAG_PLAY_COMPLETED); 1757 } 1758 } 1759 if (switch_test_flag(tech_pvt, TFLAG_RECORD)) { 1760 woomera_printf(tech_pvt->profile, tech_pvt->woomera_socket, 1761 "RECORD%s" 1762 "Unique-Call-Id: %s%s" 1763 "Audio-Uri: %s%s" 1764 "Video-Uri: %s%s" 1765 "Stop-Digits: %s%s" 1766 "Beep: %s%s" 1767 "Language: %s%s", 1768 WOOMERA_LINE_SEPERATOR, 1769 tech_pvt->call_info.callid, 1770 WOOMERA_LINE_SEPERATOR, 1771 tech_pvt->audio_uri, 1772 WOOMERA_LINE_SEPERATOR, 1773 tech_pvt->video_uri, 1774 WOOMERA_LINE_SEPERATOR, 1775 tech_pvt->stop_digits, 1776 WOOMERA_LINE_SEPERATOR, 1777 (tech_pvt->beep ? "yes" : "no"), 1778 WOOMERA_LINE_SEPERATOR, 1779 tech_pvt->profile->language, 1780 WOOMERA_RECORD_SEPERATOR 1781 ); 1782 switch_clear_flag(tech_pvt, TFLAG_RECORD); 1783 if (woomera_message_parse(tech_pvt->woomera_socket, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, &tech_pvt->event_queue) < 0) { 1784 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "{%s} RECORD ABORT!\n", tech_pvt->profile->name); 1785 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 1786 globals.panic = 1; 1787 continue; 1788 } 1789 if ( wmsg.mval > 200 ) { 1790 switch_channel_set_variable(channel, "WOOMERARECORDSTATUS", "error"); 1791 switch_channel_set_variable(channel, "WOOMERARECORDDURATION", "0"); 1792 switch_set_flag_locked(tech_pvt, TFLAG_RECORD_COMPLETED); 1793 } 1794 } 1795 1796 if (switch_test_flag(tech_pvt, TFLAG_STOP)) { 1797 woomera_printf(tech_pvt->profile, tech_pvt->woomera_socket, 1798 "STOP%s" 1799 "Unique-Call-Id: %s%s", 1800 WOOMERA_LINE_SEPERATOR, 1801 tech_pvt->call_info.callid, 1802 WOOMERA_RECORD_SEPERATOR 1803 ); 1804 1805 switch_clear_flag(tech_pvt, TFLAG_STOP); 1806 if (woomera_message_parse(tech_pvt->woomera_socket, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, &tech_pvt->event_queue) < 0) { 1807 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "{%s} STOP ABORT!\n", tech_pvt->profile->name); 1808 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 1809 globals.panic = 1; 1810 continue; 1811 } 1812 switch_set_flag_locked(tech_pvt, TFLAG_STOP_COMPLETED); 1813 if ( wmsg.mval > 200 ) { 1814 /* prevents us getting stuck in woomera_stop_exec() */ 1815 switch_set_flag_locked(tech_pvt, TFLAG_PLAY_COMPLETED); 1816 } 1817 } 1818 if (switch_test_flag(tech_pvt, TFLAG_TONE_EVENTS_ON)) { 1819 woomera_printf(tech_pvt->profile, tech_pvt->woomera_socket, 1820 "UPDATE%s" 1821 "Unique-Call-Id: %s%s" 1822 "Tone-Events: %s%s", 1823 WOOMERA_LINE_SEPERATOR, 1824 tech_pvt->call_info.callid, 1825 WOOMERA_LINE_SEPERATOR, 1826 "enable", 1827 WOOMERA_RECORD_SEPERATOR 1828 ); 1829 1830 switch_clear_flag_locked(tech_pvt, TFLAG_TONE_EVENTS_ON); 1831 if (woomera_message_parse(tech_pvt->woomera_socket, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, &tech_pvt->event_queue) < 0) { 1832 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "{%s} UPDATE ABORT!\n", tech_pvt->profile->name); 1833 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 1834 globals.panic = 1; 1835 continue; 1836 } 1837 if ( wmsg.mval > 200 ) { 1838 switch_channel_set_variable(channel, "WOOMERATONESTATUS", "error"); 1839 switch_clear_flag_locked(tech_pvt, TFLAG_WAITFORTONE); 1840 } 1841 } 1842 1843 if (switch_test_flag(tech_pvt, TFLAG_TONE_EVENTS_OFF)) { 1844 woomera_printf(tech_pvt->profile, tech_pvt->woomera_socket, 1845 "UPDATE%s" 1846 "Unique-Call-Id: %s%s" 1847 "Tone-Events: %s%s", 1848 WOOMERA_LINE_SEPERATOR, 1849 tech_pvt->call_info.callid, 1850 WOOMERA_LINE_SEPERATOR, 1851 "disable", 1852 WOOMERA_RECORD_SEPERATOR 1853 ); 1854 1855 switch_clear_flag_locked(tech_pvt, TFLAG_TONE_EVENTS_OFF); 1856 if (woomera_message_parse(tech_pvt->woomera_socket, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, &tech_pvt->event_queue) < 0) { 1857 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "{%s} UPDATE ABORT!\n", tech_pvt->profile->name); 1858 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 1859 globals.panic = 1; 1860 continue; 1861 } 1862 } 1863 if (switch_test_flag(tech_pvt, TFLAG_BRIDGE) && switch_test_flag(tech_pvt, TFLAG_CONNECTED)) { 1864 woomera_printf(tech_pvt->profile, tech_pvt->woomera_socket, 1865 "UPDATE%s" 1866 "Unique-Call-Id: %s%s" 1867 "RTP-Audio: %s:%d%s" 1868 "RTP-Video: %s:%d%s", 1869 WOOMERA_LINE_SEPERATOR, 1870 tech_pvt->call_info.callid, 1871 WOOMERA_LINE_SEPERATOR, 1872 tech_pvt->profile->woomera_host, 1873 tech_pvt->audio_bridge_port, 1874 WOOMERA_LINE_SEPERATOR, 1875 tech_pvt->profile->woomera_host, 1876 tech_pvt->video_bridge_port, 1877 WOOMERA_RECORD_SEPERATOR 1878 ); 1879 switch_clear_flag_locked(tech_pvt, TFLAG_BRIDGE); 1880 if (woomera_message_parse(tech_pvt->woomera_socket, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, &tech_pvt->event_queue) < 0) { 1881 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "{%s} BRIDGE ABORT!\n", tech_pvt->profile->name); 1882 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 1883 globals.panic = 1; 1884 continue; 1885 } 1886 } 1887 1888 if (!tech_pvt->woomera_socket) { 1889 break; 1890 } 1891 1892 /**************************************************************/ 1893 /* Check for events */ 1894 /**************************************************************/ 1895 if ((res = woomera_dequeue_event(&tech_pvt->event_queue, &wmsg)) != 0 || 1896 (res = woomera_message_parse(tech_pvt->woomera_socket, &wmsg, 100, tech_pvt->profile, NULL)) != 0) { 1897 1898 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "New command = %s\n", wmsg.command); 1899 if (res < 0 || !strcasecmp(wmsg.command, "HANGUP")) { 1900 if (!switch_channel_media_ready(channel)) { 1901 /* pre-connect result, SIT etc */ 1902 char *connection_type = woomera_message_header(&wmsg, "Connection-Type"); 1903 if (connection_type) { 1904 switch_channel_set_variable(channel, "CONNECTIONTYPE", connection_type); 1905 /* TODO Signal to API? */ 1906 } 1907 } 1908 switch_set_flag_locked(tech_pvt, TFLAG_ABORT); 1909 continue; 1910 1911 } else if (!strcasecmp(wmsg.command, "DTMF")) { 1912 char *content_len = woomera_message_header(&wmsg, "Content-Length"); 1913 if (content_len && atoi(content_len) > 0) { 1914 if (switch_test_flag(tech_pvt, TFLAG_WAITFORTONE)) { 1915 switch_channel_set_variable(channel, "WOOMERATONESTATUS", wmsg.body); 1916 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "GOT DTMF digit%s\n", wmsg.body); 1917 switch_clear_flag_locked(tech_pvt, TFLAG_WAITFORTONE); 1918 } 1919 } 1920 1921 } else if (!strcasecmp(wmsg.command, "PROCEED")) { 1922 /* This packet has lots of info so well keep it */ 1923 tech_pvt->call_info = wmsg; 1924 char *callid = woomera_message_header(&wmsg, "Unique-Call-Id"); 1925 if (callid) 1926 { 1927 switch_copy_string(tech_pvt->call_info.callid, callid, sizeof(wmsg.callid)); 1928 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "OUTBOUND CallID:%s\n", tech_pvt->call_info.callid); 1929 } 1930 // switch_channel_mark_pre_answered(channel); 1931 1932 } else if (!strcasecmp(wmsg.command, "RING")) { 1933 // switch_channel_mark_ring_ready(channel); 1934 1935 } else if (!strcasecmp(wmsg.command, "CONNECT")) { 1936 1937 char *connection_type = woomera_message_header(&wmsg, "Connection-Type"); 1938 if (connection_type) { 1939 switch_channel_set_variable(channel, "CONNECTIONTYPE", connection_type); 1940 /* TODO Signal to API? */ 1941 } 1942 switch_set_flag_locked(tech_pvt, TFLAG_CONNECTED); 1943 switch_channel_mark_answered(channel); 1944 1945 } else if (!strcasecmp(wmsg.command, "MEDIA")) { 1946 char *raw_audio_header; 1947 if ((raw_audio_header = woomera_message_header(&wmsg, "Raw-Audio")) != 0) { 1948 char ip[25]; 1949 char *ptr; 1950 switch_port_t port = 0; 1951 1952 switch_copy_string(ip, raw_audio_header, sizeof(ip) - 1); 1953 if ((ptr = strchr(ip, '/')) != 0) { 1954 *ptr = '\0'; 1955 ptr++; 1956 port = (switch_port_t) atoi(ptr); 1957 } 1958 1959 if (switch_sockaddr_info_get(&tech_pvt->audio_udpwrite, 1960 ip, SWITCH_UNSPEC, port, 0, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { 1961 if (globals.debug) { 1962 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, 1963 WOOMERA_DEBUG_PREFIX "{%s} Cannot resolve %s\n", tech_pvt->profile->name, ip); 1964 } 1965 switch_channel_hangup(channel, SWITCH_CAUSE_NETWORK_OUT_OF_ORDER); 1966 } 1967 } else { 1968 char *rtp_audio = woomera_message_header(&wmsg, "RTP-Audio"); 1969 if (rtp_audio) { 1970 char* port = strchr(rtp_audio, ':'); 1971 if (port) 1972 { 1973 *port = '\0'; 1974 port++; 1975 tech_pvt->audio_remote_port = atoi(port); 1976 } 1977 } 1978 char *rtp_video = woomera_message_header(&wmsg, "RTP-Video"); 1979 if (rtp_video) { 1980 char* port = strchr(rtp_video, ':'); 1981 if (port) 1982 { 1983 *port = '\0'; 1984 port++; 1985 tech_pvt->video_remote_port = atoi(port); 1986 } 1987 } 1988 create_rtp(tech_pvt); 1989 } 1990 1991 } else if (!strcasecmp(wmsg.command, "COMPLETED")) { 1992 char *command = woomera_message_header(&wmsg, "Command"); 1993 if (!strcmp(command, "PLAY")) { 1994 char *reason = woomera_message_header(&wmsg, "Reason"); 1995 if (reason) { 1996 switch_channel_set_variable(channel, "WOOMERAPLAYSTATUS", reason); 1997 } 1998 char *duration = woomera_message_header(&wmsg, "Duration"); 1999 if (duration) { 2000 switch_channel_set_variable(channel, "WOOMERAPLAYDURATION", duration); 2001 } 2002 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PLAY COMPLETE\n"); 2003 switch_set_flag(tech_pvt, TFLAG_PLAY_COMPLETED); 2004 } 2005 else if (!strcmp(command, "RECORD")) { 2006 char *reason = woomera_message_header(&wmsg, "Reason"); 2007 if (reason) { 2008 switch_channel_set_variable(channel, "WOOMERARECORDSTATUS", reason); 2009 } 2010 char *duration = woomera_message_header(&wmsg, "Duration"); 2011 if (duration) { 2012 switch_channel_set_variable(channel, "WOOMERARECORDDURATION", duration); 2013 } 2014 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RECORD COMPLETE\n"); 2015 switch_set_flag(tech_pvt, TFLAG_RECORD_COMPLETED); 2016 } 2017 } 2018 } 2019 } 2020 if (globals.debug > 1) { 2021 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, WOOMERA_DEBUG_PREFIX "Monitor thread for %s done.\n", tech_pvt->profile->name); 2022 } 2023 2024 return NULL; 2025 } 2026 2027 static void *woomera_thread_run(void *obj) 2028 { 2029 int res = 0; 2030 woomera_message wmsg; 2031 woomera_profile *profile; 2032 2033 profile = obj; 2034 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Started Woomera Thread {%s}.\n", profile->name); 2035 2036 profile->thread_running = 1; 2037 profile->woomera_socket = NULL; 2038 2039 2040 while (woomera_profile_thread_running(profile, 0, 0)) { 2041 /* listen on socket and handle events */ 2042 if (globals.panic == 2) { 2043 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Woomera is disabled!\n"); 2044 switch_sleep(WOOMERA_RECONNECT_TIME); 2045 continue; 2046 } 2047 2048 if (!profile->woomera_socket) { 2049 if (woomera_locate_socket(profile, &profile->woomera_socket)) { 2050 globals.panic = 0; 2051 } 2052 if (!woomera_profile_thread_running(profile, 0, 0)) { 2053 break; 2054 } 2055 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Woomera Thread Up {%s} %s/%d\n", profile->name, 2056 profile->woomera_host, profile->woomera_port); 2057 2058 } 2059 2060 if (globals.panic) { 2061 if (globals.panic != 2) { 2062 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "Help I'm in a state of panic!\n"); 2063 globals.panic = 0; //fix 2064 } 2065 woomera_socket_close(&profile->woomera_socket); 2066 2067 2068 continue; 2069 } 2070 2071 if ((((res = woomera_dequeue_event(&profile->event_queue, &wmsg)) != 0) 2072 || ((res = woomera_message_parse(profile->woomera_socket, &wmsg, 0, profile, NULL))) != 0)) { 2073 /* if we are not stingy with threads we can block forever */ 2074 if (res < 0) { 2075 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "{%s} HELP! I lost my connection to woomera!\n", profile->name); 2076 woomera_socket_close(&profile->woomera_socket); 2077 2078 globals.panic = 1; 2079 continue; 2080 } 2081 2082 if (!strcasecmp(wmsg.command, "INCOMING")) { 2083 char *name; 2084 switch_core_session_t *session; 2085 2086 if ((name = woomera_message_header(&wmsg, "Remote-Address")) == 0) { 2087 name = woomera_message_header(&wmsg, "Channel-Name"); 2088 } 2089 2090 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "New Inbound Channel %s!\n", name); 2091 if ((session = switch_core_session_request(woomera_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, NULL)) != 0) { 2092 struct private_object *tech_pvt; 2093 switch_channel_t *channel; 2094 2095 switch_core_session_add_stream(session, NULL); 2096 2097 if ((tech_pvt = (struct private_object *) switch_core_session_alloc(session, sizeof(struct private_object))) != 0) { 2098 memset(tech_pvt, 0, sizeof(*tech_pvt)); 2099 switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); 2100 tech_pvt->profile = &default_profile; 2101 channel = switch_core_session_get_channel(session); 2102 switch_core_session_set_private(session, tech_pvt); 2103 tech_pvt->session = session; 2104 2105 } else { 2106 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n"); 2107 switch_core_session_destroy(&session); 2108 break; 2109 } 2110 switch_channel_set_state(channel, CS_INIT); 2111 if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { 2112 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error spawning thread\n"); 2113 switch_core_session_destroy(&session); 2114 break; 2115 } 2116 2117 /* Save the Incoming call details */ 2118 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "INCOMING\n"); 2119 char *exten; 2120 char cid_name[512] = ""; 2121 char *cid_num; 2122 char *ip; 2123 char *p; 2124 //switch_clear_flag_locked(tech_pvt, TFLAG_PARSE_INCOMING); 2125 switch_set_flag_locked(tech_pvt, TFLAG_INCOMING); 2126 tech_pvt->call_info = wmsg; 2127 2128 char *callid = woomera_message_header(&wmsg, "Unique-Call-Id"); 2129 if (callid) 2130 { 2131 switch_copy_string(tech_pvt->call_info.callid, callid, sizeof(wmsg.callid)); 2132 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "INCOMING CallID:%s\n", tech_pvt->call_info.callid); 2133 } 2134 2135 exten = woomera_message_header(&wmsg, "Local-Number"); 2136 if (switch_strlen_zero(exten)) { 2137 exten = "s"; 2138 } 2139 2140 if ((p = woomera_message_header(&wmsg, "Remote-Name")) != 0) { 2141 switch_copy_string(cid_name, p, sizeof(cid_name)); 2142 } 2143 2144 if ((cid_num = strchr(cid_name, '!')) != 0) { 2145 *cid_num = '\0'; 2146 cid_num++; 2147 } else { 2148 cid_num = woomera_message_header(&wmsg, "Remote-Number"); 2149 } 2150 ip = woomera_message_header(&wmsg, "Remote-Address"); 2151 2152 if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), 2153 NULL, 2154 tech_pvt->profile->dialplan, 2155 cid_name, cid_num, ip, NULL, NULL, NULL, modname, tech_pvt->profile->context, exten)) != 0) 2156 { 2157 char name[128]; 2158 switch_snprintf(name, sizeof(name), "woomera/%s-%04x", tech_pvt->caller_profile->destination_number, rand() & 0xffff); 2159 switch_channel_set_name(channel, name); 2160 switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); 2161 } 2162 /* AM END */ 2163 } 2164 } 2165 } 2166 switch_yield(100); 2167 } 2168 2169 if (profile->woomera_socket) { 2170 woomera_printf(profile, profile->woomera_socket, "BYE%s", WOOMERA_RECORD_SEPERATOR); 2171 woomera_socket_close(&profile->woomera_socket); 2172 } 2173 2174 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Ended Woomera Thread {%s}.\n", profile->name); 2175 woomera_profile_thread_running(profile, 1, -1); 2176 return NULL; 2177 } 2178 2179 /*============================================================================== 2180 Woomera specific Applications 2181 =============================================================================*/ 2182 2183 /*! 2184 * \brief WoomeraPlayback application. 2185 * Usage: WoomeraPlayback(AudioUri, VideoUri) 2186 */ 2187 static void woomera_playback(switch_core_session_t *session, const char *data) 2188 { 2189 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_playback()\n"); 2190 switch_channel_t *channel = switch_core_session_get_channel(session); 2191 struct private_object *tech_pvt = switch_core_session_get_private(session); 2192 2193 char *audio_uri, *video_uri; 2194 2195 if (data) { 2196 audio_uri = (char *)data; 2197 video_uri = strstr((char *)data, "|"); 2198 if ( video_uri ) { 2199 *video_uri = '\0'; 2200 video_uri++; 2201 } else { 2202 video_uri = strstr((char *)data, ","); 2203 if ( video_uri ) { 2204 *video_uri = '\0'; 2205 video_uri++; 2206 } 2207 } 2208 } 2209 else { 2210 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "woomera_playback() - No arguments specified\n"); 2211 return; 2212 } 2213 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_playback() audio uri:%s video uri:%s\n", audio_uri, video_uri); 2214 2215 /* Answer if necessary */ 2216 if (!switch_channel_media_ready(channel)) { 2217 switch_channel_answer(channel); 2218 } 2219 2220 if (!tech_pvt) { 2221 return; 2222 } 2223 2224 /* Guard against this being called _immediately_ after a WoomeraBackground */ 2225 if (switch_test_flag(tech_pvt, TFLAG_PLAY)) { 2226 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "woomera_playback() - Play command is already active\n"); 2227 return; 2228 } 2229 /* Save the play details for the monitor thread to send the PLAY command. 2230 */ 2231 snprintf(tech_pvt->audio_uri, sizeof(tech_pvt->audio_uri), "%s", audio_uri ? audio_uri : ""); 2232 snprintf(tech_pvt->video_uri, sizeof(tech_pvt->video_uri), "%s", video_uri ? video_uri : ""); 2233 snprintf(tech_pvt->stop_digits, sizeof(tech_pvt->stop_digits), "%s", ""); 2234 snprintf(tech_pvt->repeat, sizeof(tech_pvt->repeat), "%s", "1"); 2235 switch_set_flag_locked(tech_pvt, TFLAG_PLAY); 2236 switch_clear_flag_locked(tech_pvt, TFLAG_PLAY_COMPLETED); 2237 2238 /* Wait for play to finish 2239 */ 2240 while (!switch_test_flag(tech_pvt, TFLAG_PLAY_COMPLETED)) { 2241 switch_yield(10000); 2242 } 2243 } 2244 2245 2246 /*! 2247 * \brief WoomeraBackground application. 2248 * Usage: WoomeraBackground(AudioUri, VideoUri) 2249 */ 2250 static void woomera_background(switch_core_session_t *session, const char *data) 2251 { 2252 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_background()\n"); 2253 switch_channel_t *channel = switch_core_session_get_channel(session); 2254 struct private_object *tech_pvt = switch_core_session_get_private(session); 2255 2256 char *audio_uri, *video_uri; 2257 char *overlay = NULL; 2258 2259 if (data) { 2260 audio_uri = (char *)data; 2261 video_uri = strstr((char *)data, "|"); 2262 if ( video_uri ) { 2263 *video_uri = '\0'; 2264 video_uri++; 2265 } else { 2266 video_uri = strstr((char *)data, ","); 2267 if ( video_uri ) { 2268 *video_uri = '\0'; 2269 video_uri++; 2270 } 2271 } 2272 if ( video_uri ) { 2273 overlay = strstr(video_uri, "|"); 2274 if ( overlay ) { 2275 *overlay = '\0'; 2276 overlay++; 2277 } else { 2278 overlay = strstr(video_uri, ","); 2279 if ( overlay ) { 2280 *overlay = '\0'; 2281 overlay++; 2282 } 2283 } 2284 } 2285 } 2286 else { 2287 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "woomera_background() - No arguments specified\n"); 2288 return; 2289 } 2290 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "woomera_background(): overlay=\"%s\"\n", overlay); 2291 2292 /* Answer if necessary */ 2293 if (!switch_channel_media_ready(channel)) { 2294 switch_channel_answer(channel); 2295 } 2296 2297 if (!tech_pvt) { 2298 return; 2299 } 2300 2301 /* Save the play details for the monitor thread to send the PLAY command. 2302 */ 2303 snprintf(tech_pvt->audio_uri, sizeof(tech_pvt->audio_uri), "%s", audio_uri ? audio_uri : ""); 2304 snprintf(tech_pvt->video_uri, sizeof(tech_pvt->video_uri), "%s", video_uri ? video_uri : ""); 2305 snprintf(tech_pvt->overlay, sizeof(tech_pvt->overlay), "%s", overlay ? overlay : ""); 2306 snprintf(tech_pvt->stop_digits, sizeof(tech_pvt->stop_digits), "%s", "0123456789*#"); 2307 snprintf(tech_pvt->repeat, sizeof(tech_pvt->repeat), "%s", "1"); 2308 switch_set_flag_locked(tech_pvt, TFLAG_PLAY); 2309 switch_clear_flag_locked(tech_pvt, TFLAG_PLAY_COMPLETED); 2310 } 2311 2312 /*! 2313 * \brief WoomeraRingback application. 2314 * Usage: WoomeraRingback(AudioUri, VideoUri) 2315 */ 2316 static void woomera_ringback(switch_core_session_t *session, const char *data) 2317 { 2318 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_ringback()\n"); 2319 switch_channel_t *channel = switch_core_session_get_channel(session); 2320 struct private_object *tech_pvt = switch_core_session_get_private(session); 2321 2322 char *audio_uri, *video_uri; 2323 2324 if (data) { 2325 audio_uri = (char *)data; 2326 video_uri = strstr((char *)data, "|"); 2327 if ( video_uri ) { 2328 *video_uri = '\0'; 2329 video_uri++; 2330 } else { 2331 video_uri = strstr((char *)data, ","); 2332 if ( video_uri ) { 2333 *video_uri = '\0'; 2334 video_uri++; 2335 } 2336 } 2337 } 2338 else { 2339 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "woomera_ringback() - No arguments specified\n"); 2340 return; 2341 } 2342 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_ringback() audio uri:%s video uri:%s\n", audio_uri, video_uri); 2343 2344 /* Pre-answer only */ 2345 if (switch_channel_media_ready(channel)) { 2346 return; 2347 } 2348 2349 if (!tech_pvt) { 2350 return; 2351 } 2352 2353 /* Guard against this being called _immediately_ after a WoomeraBackground */ 2354 if (switch_test_flag(tech_pvt, TFLAG_PLAY)) { 2355 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "woomera_playback() - Play command is already active\n"); 2356 return; 2357 } 2358 /* Save the play details for the monitor thread to send the PLAY command. 2359 */ 2360 snprintf(tech_pvt->audio_uri, sizeof(tech_pvt->audio_uri), "%s", audio_uri ? audio_uri : ""); 2361 snprintf(tech_pvt->video_uri, sizeof(tech_pvt->video_uri), "%s", video_uri ? video_uri : ""); 2362 snprintf(tech_pvt->stop_digits, sizeof(tech_pvt->stop_digits), "%s", ""); 2363 snprintf(tech_pvt->repeat, sizeof(tech_pvt->repeat), "%s", "infinite"); 2364 switch_set_flag_locked(tech_pvt, TFLAG_PLAY); 2365 switch_clear_flag_locked(tech_pvt, TFLAG_PLAY_COMPLETED); 2366 2367 } 2368 2369 /*! 2370 * \brief WoomeraRecord application. 2371 * Usage: WoomeraRecord(Audio URI, Video URI) 2372 */ 2373 static void woomera_record(switch_core_session_t *session, const char *data) 2374 { 2375 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_record()\n"); 2376 switch_channel_t *channel = switch_core_session_get_channel(session); 2377 struct private_object *tech_pvt = switch_core_session_get_private(session); 2378 2379 char *audio_uri, *video_uri; 2380 2381 if (data) { 2382 audio_uri = (char *)data; 2383 video_uri = strstr((char *)data, "|"); 2384 if ( video_uri ) { 2385 *video_uri = '\0'; 2386 video_uri++; 2387 } else { 2388 video_uri = strstr((char *)data, ","); 2389 if ( video_uri ) { 2390 *video_uri = '\0'; 2391 video_uri++; 2392 } 2393 } 2394 } 2395 else { 2396 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "woomera_record_exec - No arguments specified\n"); 2397 return; 2398 } 2399 2400 /* Answer if necessary */ 2401 if (!switch_channel_media_ready(channel)) { 2402 switch_channel_answer(channel); 2403 } 2404 2405 if (!tech_pvt) { 2406 return; 2407 } 2408 2409 /* Save the record details for the monitor thread to send the RECORD command. 2410 */ 2411 snprintf(tech_pvt->audio_uri, sizeof(tech_pvt->audio_uri), "%s", audio_uri ? audio_uri : ""); 2412 snprintf(tech_pvt->video_uri, sizeof(tech_pvt->video_uri), "%s", video_uri ? video_uri : ""); 2413 snprintf(tech_pvt->stop_digits, sizeof(tech_pvt->stop_digits), "%s", "#"); 2414 tech_pvt->beep = 1; 2415 2416 switch_set_flag_locked(tech_pvt, TFLAG_RECORD); 2417 switch_clear_flag_locked(tech_pvt, TFLAG_RECORD_COMPLETED); 2418 2419 /* Wait for record to finish 2420 */ 2421 while (!switch_test_flag(tech_pvt, TFLAG_RECORD_COMPLETED)) { 2422 switch_yield(10000); 2423 } 2424 switch_clear_flag_locked(tech_pvt, TFLAG_RECORD_COMPLETED); 2425 } 2426 2427 /*! 2428 * \brief WoomeraStop application. 2429 * Usage: WoomeraStop 2430 */ 2431 static void woomera_stop(switch_core_session_t *session, const char *data) 2432 { 2433 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_record()\n"); 2434 struct private_object *tech_pvt = switch_core_session_get_private(session); 2435 2436 if (!tech_pvt) { 2437 return; 2438 } 2439 2440 /* Flag request for the monitor thread to send the STOP command. 2441 */ 2442 switch_set_flag_locked(tech_pvt, TFLAG_STOP); 2443 switch_clear_flag_locked(tech_pvt, TFLAG_STOP_COMPLETED); 2444 2445 /* Wait for stop to finish 2446 */ 2447 while (!switch_test_flag(tech_pvt, TFLAG_STOP_COMPLETED)) { 2448 switch_yield(10000); 2449 } 2450 switch_clear_flag_locked(tech_pvt, TFLAG_STOP_COMPLETED); 2451 2452 /* Wait for play (WoomeraBackground) to finish. 2453 */ 2454 while (!switch_test_flag(tech_pvt, TFLAG_PLAY_COMPLETED)) { 2455 switch_yield(10000); 2456 } 2457 switch_clear_flag_locked(tech_pvt, TFLAG_PLAY_COMPLETED); 2458 2459 return; 2460 } 2461 2462 /*! 2463 * \brief WoomeraWaitForTone application. 2464 * Usage: WoomeraWaitForTone(timeout) 2465 */ 2466 static void woomera_waitfortone(switch_core_session_t *session, const char *data) 2467 { 2468 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "woomera_waitfortone()\n"); 2469 switch_channel_t *channel = switch_core_session_get_channel(session); 2470 struct private_object *tech_pvt = switch_core_session_get_private(session); 2471 2472 if (!tech_pvt) { 2473 return; 2474 } 2475 2476 int timeout = 0; 2477 if (data) { 2478 timeout = atoi((char *)data); 2479 } 2480 2481 /* Answer if necessary */ 2482 if (!switch_channel_media_ready(channel)) { 2483 switch_channel_answer(channel); 2484 } 2485 2486 /* Save the details for the monitor thread to send the command. 2487 */ 2488 tech_pvt->wait_timeout = timeout; 2489 time(&tech_pvt->wait_start); 2490 2491 switch_clear_flag_locked(tech_pvt, TFLAG_TONE_EVENTS_OFF); 2492 switch_set_flag_locked(tech_pvt, TFLAG_TONE_EVENTS_ON); 2493 switch_set_flag_locked(tech_pvt, TFLAG_WAITFORTONE); 2494 2495 /* Wait for tone event 2496 */ 2497 while (switch_test_flag(tech_pvt, TFLAG_WAITFORTONE)) { 2498 if (tech_pvt->wait_timeout && (difftime(time(0), tech_pvt->wait_start) >= tech_pvt->wait_timeout)) { 2499 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "woomera_waitfortone() - Timeout\n"); 2500 switch_channel_set_variable(channel, "WOOMERATONESTATUS", "timeout"); 2501 switch_clear_flag_locked(tech_pvt, TFLAG_WAITFORTONE); 2502 return; 2503 } 2504 switch_yield(10000); 2505 } 2506 switch_set_flag_locked(tech_pvt, TFLAG_TONE_EVENTS_OFF); 2507 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "woomera_waitfortone() - EXIT\n"); 2508 } 2509 2510 2511 SWITCH_MODULE_RUNTIME_FUNCTION(mod_woomera_runtime) 2512 { 2513 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SWITCH_MODULE_RUNTIME_FUNCTION()\n"); 2514 woomera_thread_run(&default_profile); 2515 2516 return SWITCH_STATUS_TERM; 2517 } 2518 2519 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_woomera_shutdown) 2520 { 2521 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SWITCH_MODULE_SHUTDOWN_FUNCTION()\n"); 2522 int x = 0; 2523 woomera_profile_thread_running(&default_profile, 1, 0); 2524 while (!woomera_profile_thread_running(&default_profile, 0, 0)) { 2525 woomera_socket_close(&default_profile.woomera_socket); 2526 if (x++ > 10) { 2527 break; 2528 } 2529 switch_yield(1); 2530 } 2531 return SWITCH_STATUS_SUCCESS; 2532 } 2533 2534 SWITCH_STANDARD_APP(woomera_playback_exec) 2535 { 2536 woomera_playback(session, data); 2537 } 2538 2539 SWITCH_STANDARD_APP(woomera_background_exec) 2540 { 2541 woomera_background(session, data); 2542 } 2543 2544 SWITCH_STANDARD_APP(woomera_record_exec) 2545 { 2546 woomera_record(session, data); 2547 } 2548 2549 SWITCH_STANDARD_APP(woomera_ringback_exec) 2550 { 2551 woomera_ringback(session, data); 2552 } 2553 2554 SWITCH_STANDARD_APP(woomera_stop_exec) 2555 { 2556 woomera_stop(session, data); 2557 } 2558 2559 SWITCH_STANDARD_APP(woomera_waitfortone_exec) 2560 { 2561 woomera_waitfortone(session, data); 2562 } 2563 2564 SWITCH_MODULE_LOAD_FUNCTION(mod_woomera_load) 2565 { 2566 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SWITCH_MODULE_LOAD_FUNCTION()\n"); 2567 struct woomera_profile *profile = &default_profile; 2568 char *cf = "woomera.conf"; 2569 switch_xml_t cfg, xml, settings, applications, param, xmlp; 2570 2571 memset(&globals, 0, sizeof(globals)); 2572 globals.next_woomera_port = WOOMERA_MIN_PORT; 2573 2574 if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { 2575 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf); 2576 return SWITCH_STATUS_TERM; 2577 } 2578 2579 // Setup default configuaration 2580 switch_set_flag(profile, PFLAG_INBOUND | PFLAG_OUTBOUND); 2581 profile->name = "main"; 2582 switch_copy_string(profile->dialplan, "XML", sizeof(profile->dialplan) - 1); 2583 switch_copy_string(profile->context, "default", sizeof(profile->context) - 1); 2584 switch_copy_string(profile->audio_ip, "127.0.0.1", sizeof(profile->audio_ip) - 1); 2585 switch_copy_string(profile->woomera_host, "127.0.0.1", sizeof(profile->woomera_host) - 1); 2586 switch_copy_string(profile->language, "en_US", sizeof(profile->language) - 1); 2587 switch_clear_flag(profile, PFLAG_DISABLED); 2588 switch_set_flag(profile, PFLAG_INBOUND); 2589 switch_set_flag(profile, PFLAG_OUTBOUND); 2590 switch_set_flag(profile, PFLAG_RTP); 2591 switch_set_flag(profile, PFLAG_VIDEORTP); 2592 2593 profile->woomera_port = (switch_port_t) 42420; 2594 2595 if ((settings = switch_xml_child(cfg, "settings"))) { 2596 for (param = switch_xml_child(settings, "param"); param; param = param->next) { 2597 char *var = (char *) switch_xml_attr_soft(param, "name"); 2598 char *val = (char *) switch_xml_attr_soft(param, "value"); 2599 2600 if (!strcmp(var, "noload") && atoi(val)) { 2601 return SWITCH_STATUS_TERM; 2602 } 2603 if (!strcmp(var, "debug")) { 2604 globals.debug = atoi(val); 2605 } 2606 } 2607 } 2608 2609 if ((applications = switch_xml_child(cfg, "applications"))) { 2610 for (param = switch_xml_child(applications, "param"); param; param = param->next) { 2611 char *var = (char *) switch_xml_attr_soft(param, "name"); 2612 char *val = (char *) switch_xml_attr_soft(param, "value"); 2613 2614 if (!strcasecmp(var, "woomeraplayback")) { 2615 capabilities.woomeraplayback = atoi(val); 2616 } else if (!strcasecmp(var, "woomerabackground")) { 2617 capabilities.woomerabackground = atoi(val); 2618 } else if (!strcasecmp(var, "woomerarecord")) { 2619 capabilities.woomerarecord = atoi(val); 2620 } else if (!strcasecmp(var, "woomeraringback")) { 2621 capabilities.woomeraringback = atoi(val); 2622 } else if (!strcasecmp(var, "woomerawaitfortone")) { 2623 capabilities.woomerawaitfortone = atoi(val); 2624 } else if (!strcasecmp(var, "woomerastop")) { 2625 capabilities.woomerastop = atoi(val); 2626 } 2627 } 2628 } 2629 2630 for (xmlp = switch_xml_child(cfg, "interface"); xmlp; xmlp = xmlp->next) { 2631 for (param = switch_xml_child(xmlp, "param"); param; param = param->next) { 2632 char *var = (char *) switch_xml_attr_soft(param, "name"); 2633 char *val = (char *) switch_xml_attr_soft(param, "value"); 2634 if (!strcmp(var, "audio-ip")) { 2635 switch_copy_string(profile->audio_ip, val, sizeof(profile->audio_ip) - 1); 2636 } else if (!strcmp(var, "host")) { 2637 switch_copy_string(profile->woomera_host, val, sizeof(profile->woomera_host) - 1); 2638 } else if (!strcmp(var, "port")) { 2639 profile->woomera_port = (switch_port_t) atoi(val); 2640 } else if (!strcmp(var, "disabled")) { 2641 if (atoi(val) > 0) { 2642 switch_set_flag(profile, PFLAG_DISABLED); 2643 } 2644 } else if (!strcmp(var, "inbound")) { 2645 if (atoi(val) < 1) { 2646 switch_clear_flag(profile, PFLAG_INBOUND); 2647 } 2648 } else if (!strcmp(var, "outbound")) { 2649 if (atoi(val) < 1) { 2650 switch_clear_flag(profile, PFLAG_OUTBOUND); 2651 } 2652 } else if (!strcmp(var, "rtp")) { 2653 if (atoi(val) < 1) { 2654 switch_clear_flag(profile, PFLAG_RTP); 2655 } 2656 } else if (!strcmp(var, "video-rtp")) { 2657 if (atoi(val) < 1) { 2658 switch_clear_flag(profile, PFLAG_VIDEORTP); 2659 } 2660 } else if (!strcmp(var, "dialplan")) { 2661 switch_copy_string(profile->dialplan, val, sizeof(profile->dialplan) - 1); 2662 2663 } else if (!strcmp(var, "context")) { 2664 switch_copy_string(profile->context, val, sizeof(profile->context) - 1); 2665 2666 } else if (!strcmp(var, "language")) { 2667 switch_copy_string(profile->language, val, sizeof(profile->language) - 1); 2668 } 2669 } 2670 } 2671 2672 switch_xml_free(xml); 2673 2674 module_pool = pool; 2675 2676 if (switch_mutex_init(&default_profile.iolock, SWITCH_MUTEX_NESTED, module_pool) != SWITCH_STATUS_SUCCESS) { 2677 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "OH OH no lock\n"); 2678 return SWITCH_STATUS_TERM; 2679 } 2680 2681 /* connect my internal structure to the blank pointer passed to me */ 2682 *module_interface = switch_loadable_module_create_module_interface(pool, modname); 2683 woomera_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE); 2684 woomera_endpoint_interface->interface_name = "woomera"; 2685 woomera_endpoint_interface->io_routines = &woomera_io_routines; 2686 woomera_endpoint_interface->state_handler = &woomera_event_handlers; 2687 2688 /* Register dialplan applications */ 2689 switch_application_interface_t *app_interface; 2690 2691 if (capabilities.woomeraplayback) { 2692 SWITCH_ADD_APP(app_interface, woomeraplaybackapp, woomeraplaybackdesc, woomeraplaybacksynopsis, woomera_playback_exec, NULL, SAF_SUPPORT_NOMEDIA); 2693 } 2694 if (capabilities.woomerabackground) { 2695 SWITCH_ADD_APP(app_interface, woomerabackgroundapp, woomerabackgrounddesc, woomerabackgroundsynopsis, woomera_background_exec, NULL, SAF_SUPPORT_NOMEDIA); 2696 } 2697 if (capabilities.woomerarecord) { 2698 SWITCH_ADD_APP(app_interface, woomerarecordapp, woomerarecorddesc, woomerarecordsynopsis, woomera_record_exec, NULL, SAF_SUPPORT_NOMEDIA); 2699 } 2700 if (capabilities.woomeraringback) { 2701 SWITCH_ADD_APP(app_interface, woomeraringbackapp, woomeraringbackdesc, woomeraringbacksynopsis, woomera_ringback_exec, NULL, SAF_SUPPORT_NOMEDIA); 2702 } 2703 if (capabilities.woomerabackground || capabilities.woomeraringback) { 2704 SWITCH_ADD_APP(app_interface, woomerastopapp, woomerastopdesc, woomerastopsynopsis, woomera_stop_exec, NULL, SAF_SUPPORT_NOMEDIA); 2705 } 2706 if (capabilities.woomerawaitfortone) { 2707 SWITCH_ADD_APP(app_interface, woomerawaitfortoneapp, woomerawaitfortonedesc, woomerawaitfortonesynopsis, woomera_waitfortone_exec, NULL, SAF_SUPPORT_NOMEDIA); 2708 } 2709 if (capabilities.woomerastop) { 2710 SWITCH_ADD_APP(app_interface, woomerastopapp, woomerastopdesc, woomerastopsynopsis, woomera_stop_exec, NULL, SAF_SUPPORT_NOMEDIA); 2711 } 2712 2713 /* indicate that the module should continue to be loaded */ 2714 return SWITCH_STATUS_SUCCESS; 2715 } 2716 2717 /* For Emacs: 2718 * Local Variables: 2719 * mode:c 2720 * indent-tabs-mode:t 2721 * tab-width:4 2722 * c-basic-offset:4 2723 * End: 2724 * For VIM: 2725 * vim:set softtabstop=4 shiftwidth=4 tabstop=4: 2726 */
| No admin address has been configured | ViewVC Help |
| Powered by ViewVC 1.0.8 |