[server] / trunk / clients / freeswitch / mod_woomera / mod_woomera.c Repository:
ViewVC logotype

View of /trunk/clients/freeswitch/mod_woomera/mod_woomera.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 811 - (download) (annotate)
Wed Jul 14 16:52:35 2010 UTC (2 years, 10 months ago) by amartin
File size: 99591 byte(s)
(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