[server] / trunk / server / src / appdiastar.cxx Repository:
ViewVC logotype

View of /trunk/server/src/appdiastar.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1218 - (download) (annotate)
Wed Jun 6 13:16:07 2012 UTC (12 months, 1 week ago) by jtarlton
File size: 46375 byte(s)
Pass/store rtp information in RtpIpInfo objects. These include the media direction in addition to the ip address and port number.
    1 /*
    2  * This file is part of Project DiaStar Server.
    3  *
    4  * More information about this project can be found at:
    5  * http://www.projectdiastar.org.
    6  *
    7  * Copyright (C) 2009,2010 Dialogic Corp.
    8  *
    9  * This program is free software; you can redistribute it and/or
   10  * modify it under the terms of the GNU General Public License
   11  * as published by the Free Software Foundation; either version 2
   12  * of the License, or (at your option) any later version.
   13  *
   14  * This program is distributed in the hope that it will be useful,
   15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17  * GNU General Public License for more details.
   18  *
   19  * You should have received a copy of the GNU General Public License
   20  * along with this program; if not, write to the Free Software
   21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   22  * 02110-1301, USA.
   23  * Alternatively see <http://www.gnu.org/licenses/>.
   24  * Or see the LICENSE file included within the source tree.
   25  *
   26  */
   27 
   28 /*!
   29  * \file    appdiastar.cxx
   30  * \brief   Project DiaStar server. Manages all interactions between the Woomera
   31  *          protocol layer and the Dialogic channel driver.
   32  * \author  John Tarlton  <john.tarlton@dialogic.com>
   33  * \author  Antony Martin <antony.martin@dialogic.com>
   34  * \version 0.1
   35  */
   36 
   37 /*------------------------------ Dependencies --------------------------------*/
   38 
   39 #include <climits>
   40 
   41 #include <woomera.h>
   42 
   43 #include "logger.h"
   44 #include "getoption.h"
   45 #include "string-util.h"
   46 #include "net-util.h"
   47 
   48 #include <srllib.h>
   49 #include <gclib.h>
   50 #include <ipmlib.h>
   51 
   52 #include "dialogicchannelmanager.h"
   53 #include "appevent.h"
   54 #include "appdiastar.h"
   55 
   56 /*----------------------------------------------------------------------------*/
   57 
   58 /*!
   59  * Woomera callback for protocol messages (isdn,sip etc).
   60  * Forward message to its dedicated handler function.
   61  */
   62 woomera_server_response* protocol_message_handler( woomera_callctlr_command* msg,
   63                                                    void* prot_user_data )
   64 {
   65   if ( (!msg) || (!prot_user_data) )
   66   {
   67     LOGERROR("protocol_message_handler() bad params");
   68     return 0;
   69   }
   70 
   71   AppDiaStar* app_woomera = static_cast<AppDiaStar*>(prot_user_data);
   72 
   73   switch ( msg->e )
   74   {
   75     case WOOMERA_CALLCTL_COMMAND_MAKE_CALL:
   76       return app_woomera->makeCall(msg);
   77 
   78     case WOOMERA_CALLCTL_COMMAND_HANGUP_CALL:
   79       return app_woomera->hangupCall(msg);
   80 
   81     case WOOMERA_CALLCTL_COMMAND_ACCEPT_CALL:
   82       return app_woomera->acceptCall(msg);
   83 
   84     case WOOMERA_CALLCTL_COMMAND_ANSWER_CALL:
   85       return app_woomera->answerCall(msg);
   86 
   87     case WOOMERA_CALLCTL_COMMAND_SEIZE_CALL:
   88       /* Not used here */
   89       break;
   90 
   91     case WOOMERA_CALLCTL_COMMAND_DTMF:
   92       return app_woomera->sendDtmf(msg);
   93 
   94     case WOOMERA_CALLCTL_COMMAND_PLAY:
   95       return app_woomera->play(msg);
   96 
   97     case WOOMERA_CALLCTL_COMMAND_RECORD:
   98       return app_woomera->record(msg);
   99 
  100     case WOOMERA_CALLCTL_COMMAND_STOP:
  101       return app_woomera->stop(msg);
  102 
  103     case WOOMERA_CALLCTL_COMMAND_UPDATE:
  104       return app_woomera->update(msg);
  105 
  106     default:
  107       LOGERROR("protocol_message_handler() Got unsupported cmd");
  108       break;
  109   }
  110   return 0;
  111 }
  112 
  113 
  114 /*!
  115  * Protocol definition for Woomera.
  116  */
  117 static woomera_protocol_def protocol_def = {
  118   0,
  119   protocol_message_handler
  120 };
  121 
  122 
  123 /*!
  124  * Callback for Dialogic events.
  125  */
  126 void dialogic_event_callback( woomera_server_attr* attr )
  127 {
  128   if ( (!attr) || (!attr->user_data) )
  129   {
  130     LOGERROR("dialogic_event_callback() bad attr");
  131     return;
  132   }
  133 
  134   if ( sr_waitevt(0) < 0 )
  135   {
  136     return;
  137   }
  138   METAEVENT metaevent;
  139   if ( gc_GetMetaEvent(&metaevent) != GC_SUCCESS )
  140   {
  141     /* serious problem - should never fail.
  142      */
  143     LOGERROR("dialogic_event_callback() gc_GetMetaEvent() failed");
  144   }
  145   else
  146   {
  147     DialogicChannelManager* channelMgr;
  148     channelMgr = static_cast<DialogicChannelManager*>(attr->user_data);
  149     channelMgr->dispatchEvent(metaevent);
  150   }
  151 }
  152 
  153 
  154 /*
  155  * Callback for ImageMaker events.
  156  * Forward the event to its target device (ipm) via the srl event api.
  157  */
  158 void imagemaker_event_callback( const ImageMakerThreadResponse* response )
  159 {
  160   /* merge response data with the request (event) data */
  161   ImageMakerEvent* imageMakerEvent = static_cast<ImageMakerEvent*>(response->userdata);
  162 
  163   imageMakerEvent->top = response->top;
  164   imageMakerEvent->left = response->left;
  165   imageMakerEvent->height = response->height;
  166   imageMakerEvent->width = response->width;
  167   strcpy(imageMakerEvent->filename, response->filename.c_str());
  168 
  169   if ( response->ok )
  170   {
  171     _sr_putevt(imageMakerEvent->dev_handle,
  172                APP_IMAGEMAKER_OK,
  173                sizeof(ImageMakerEvent),
  174                imageMakerEvent,
  175                0);
  176   }
  177   else
  178   {
  179     _sr_putevt(imageMakerEvent->dev_handle,
  180                APP_IMAGEMAKER_FAIL,
  181                sizeof(ImageMakerEvent),
  182                imageMakerEvent,
  183                0);
  184   }
  185   /* _sr_putevt() has made a copy of the data so the original can be deleted.
  186    */
  187   delete imageMakerEvent;
  188 }
  189 
  190 
  191 /*
  192  * Callback for RtspConnector events.
  193  * Forward the event to its target device (ipm) via the srl event api.
  194  */
  195 void rtspconnector_event_callback( RtspEvent* event )
  196 {
  197   int device_handle = reinterpret_cast<int>(event->userdata);
  198 
  199   _sr_putevt(device_handle,
  200              APP_RTSP_EVENT,
  201              sizeof(RtspEvent),
  202              event,
  203              0);
  204 }
  205 
  206 /////////////////////////////////////////////////////////////////////////////
  207 
  208 /*
  209  * This is the application's top level function, it has two modes of operation
  210  * which are selected by the 'probe' command line option. When this option is
  211  * specified the application performs hardware detection and outputs the results
  212  * in an 'ini' file format that may be used for subsequent sessions. If probing
  213  * has not been requested the application runs the woomera server.
  214  */
  215 bool AppDiaStar::run( const GetOptions& opts, int stop_fd, void(*stop_event_callback)(int) )
  216 {
  217   /*
  218    * Probe only.
  219    */
  220   if ( opts.isFound("probe") )
  221   {
  222     DialogicChannelManager* channelMgr = new DialogicChannelManager(*this, config_);
  223     if ( !channelMgr->init() )
  224     {
  225       delete channelMgr;
  226       return false;
  227     }
  228 
  229     bool isdn = false;
  230     bool ss7 = false;
  231     bool h324 = false;
  232 
  233     if ( opts.isFound("isdn") )
  234     {
  235       /* dti config will be set for isdn */
  236       isdn = true;
  237       ss7 = false;
  238     }
  239 
  240     if ( opts.isFound("ss7") )
  241     {
  242       /* dti config will be set for ss7 */
  243       isdn = false;
  244       ss7 = true;
  245       LOGNOTICE("AppDiaStar::run() dk:" << opts.getValue("ss7"));
  246     }
  247 
  248     if ( opts.isFound("h324") )
  249     {
  250       if ( isdn || ss7 )
  251       {
  252         h324 = true;
  253       }
  254       else
  255       {
  256         LOGERROR("AppDiaStar::run() option --h324 requires either option --isdn or option --ss7");
  257       }
  258     }
  259 
  260     bool res = config_.probe(opts.getValue("conf"),
  261                              isdn,
  262                              ss7,
  263                              opts.getValue("ss7"),
  264                              h324);
  265     delete channelMgr;
  266     return res;
  267   }
  268 
  269   /*
  270    * Normal operation.
  271    */
  272   LOGNOTICE("AppDiaStar::run() initialising...");
  273 
  274   std::string opt_conf = opts.getValue("conf");
  275 
  276   std::string opt_sdp_address = opts.getValue("sdp-address");
  277   if ( !opt_sdp_address.empty() )
  278   {
  279     config_.setSdpContactAddress(opt_sdp_address);
  280   }
  281 
  282   /*
  283    * Woomera address and port.
  284    */
  285   std::string opt_woomera_address = opts.getValue("woomera-address");
  286   if ( opt_woomera_address.empty() )
  287   {
  288     if ( !getInterfaceIpv4Addr("eth0", opt_woomera_address) )
  289     {
  290       opt_woomera_address = "127.0.0.1";
  291     }
  292   }
  293 
  294   std::string opt_woomera_port = opts.getValue("woomera-port");
  295   if ( opt_woomera_port.empty() )
  296   {
  297     opt_woomera_port = "42420";
  298   }
  299   int port = atoi(opt_woomera_port.c_str());
  300   if ( (port <= 0) || (port > 65535) )
  301   {
  302     port = 42420;
  303   }
  304 
  305   IpInfo woomera_ipinfo(opt_woomera_address, port);
  306 
  307   /* initialise woomera subsystem.
  308    */
  309   woomera_init();
  310   woomeraServer_ = woomera_server_new();
  311   woomeraCallCtlr_ = woomera_callctlr_new(woomera_server_send_event, woomeraServer_);
  312 
  313   woomera_server_set_contact_address(woomeraServer_, woomera_ipinfo.getAddressAndPort().c_str());
  314 
  315   /* setup exit hander
  316    */
  317   woomera_server_set_event(woomeraServer_, stop_fd, stop_event_callback);
  318 
  319   /* Initialise Dialogic and attach to Woomera's event mechanism.
  320    * When Woomera detects events on these fdS it will call the function
  321    * specified by the callback member of the attr struct that is passed to
  322    * woomera_server_run().
  323    */
  324   int nfds = sr_getfdcnt();
  325   int* fdarray = (int*) malloc(sizeof(int) * nfds);
  326   sr_getfdinfo(fdarray);
  327   for ( int i = 0; i < nfds; i++ )
  328   {
  329     woomera_server_set_event(woomeraServer_, fdarray[i], 0);
  330   }
  331   free(fdarray);
  332 
  333   channelMgr_ = new DialogicChannelManager(*this, config_);
  334   if ( !channelMgr_->start(opt_conf) )
  335   {
  336     LOGCRIT("AppDiaStar::run() failed to start DialogicChannelManager. Exiting...");
  337     delete channelMgr_;
  338     return false;
  339   }
  340 
  341   /*
  342    * Tell Woomera any extra commands that are available.
  343    */
  344   if ( config_.haveMm() )
  345   {
  346     woomera_callctlr_allow(woomeraCallCtlr_, WOOMERA_SERVER_PLAY);
  347     woomera_callctlr_allow(woomeraCallCtlr_, WOOMERA_SERVER_RECORD);
  348     woomera_callctlr_allow(woomeraCallCtlr_, WOOMERA_SERVER_STOP);
  349   }
  350 
  351   /*
  352    * Tell Woomera which protocols have been configured.
  353    */
  354   if ( config_.haveIsdn() )
  355   {
  356     woomera_callctlr_add_protocol(woomeraCallCtlr_, &protocol_def, "isdn", this);
  357   }
  358   if ( config_.haveSs7() )
  359   {
  360     woomera_callctlr_add_protocol(woomeraCallCtlr_, &protocol_def, "ss7", this);
  361   }
  362   if ( config_.haveSip() )
  363   {
  364     woomera_callctlr_add_protocol(woomeraCallCtlr_, &protocol_def, "sip", this);
  365   }
  366   if ( config_.haveConf() )
  367   {
  368     woomera_callctlr_add_protocol(woomeraCallCtlr_, &protocol_def, "conf", this);
  369   }
  370   if ( config_.haveH324() )
  371   {
  372     woomera_callctlr_add_protocol(woomeraCallCtlr_, &protocol_def, "h324", this);
  373   }
  374 
  375   /*
  376    * Set Woomera rtp media format.
  377    */
  378   std::string client_audio = config_.getClientAudioFormat();
  379   if ( client_audio == "pcma" )
  380   {
  381     woomera_callctlr_set_audio_format(woomeraCallCtlr_, woomera_key_pcma);
  382   }
  383   else if ( client_audio == "g722" )
  384   {
  385     woomera_callctlr_set_audio_format(woomeraCallCtlr_, woomera_key_g722);
  386   }
  387   else if ( client_audio == "g729" )
  388   {
  389     woomera_callctlr_set_audio_format(woomeraCallCtlr_, woomera_key_g729);
  390   }
  391   else /* pcmu */
  392   {
  393     woomera_callctlr_set_audio_format(woomeraCallCtlr_, woomera_key_pcmu);
  394   }
  395 
  396   std::string client_video = config_.getClientVideoFormat();
  397   if ( client_video == "h263-1998" )
  398   {
  399     woomera_callctlr_set_video_format(woomeraCallCtlr_, woomera_key_h263_1998);
  400   }
  401   else if ( client_video == "mpv4-es" )
  402   {
  403     woomera_callctlr_set_video_format(woomeraCallCtlr_, woomera_key_mp4ves);
  404   }
  405   else if ( client_video == "h264" )
  406   {
  407     woomera_callctlr_set_video_format(woomeraCallCtlr_, woomera_key_h264);
  408   }
  409   else /* h.263 */
  410   {
  411     woomera_callctlr_set_video_format(woomeraCallCtlr_, woomera_key_h263);
  412   }
  413 
  414   /*
  415    * run the woomera server.
  416    */
  417   attr_ = woomera_server_attr_new();
  418   attr_->server    = woomeraServer_;
  419   attr_->callctlr  = woomeraCallCtlr_;
  420   attr_->port      = woomera_ipinfo.getPort();
  421   attr_->timeout   = 1000;
  422   attr_->broadcast_port = 0;
  423   attr_->community[0] = '\0';
  424   attr_->callback  = &dialogic_event_callback;
  425   attr_->user_data = channelMgr_;        /* used by dialogic_event_callback */
  426 
  427   /* pass control to the woomera event loop, this will return following
  428    * a call to woomera_server_stop().
  429    */
  430   LOGNOTICE("AppDiaStar::run() starting Woomera server");
  431   woomera_server_run(attr_);
  432 
  433   /* exit
  434    */
  435   woomera_server_delete(woomeraServer_);
  436   woomera_callctlr_delete(woomeraCallCtlr_);
  437   delete channelMgr_;
  438   return true;
  439 }
  440 
  441 
  442 /*
  443  * forward to woomera, this will cause woomera_server_run() to return.
  444  */
  445 void AppDiaStar::stop()
  446 {
  447   woomera_server_stop(attr_);
  448 }
  449 
  450 
  451 /*
  452  * Parse a dial string into number and attribute parts.
  453  * Format: NUMBER / NAME = VALUE : NAME = VALUE
  454  * E.g. 1234567890/group=span1:cpa=yes
  455  */
  456 void AppDiaStar::parseDialString( const std::string& s,
  457                                   std::string& number,
  458                                   std::map<std::string, std::string>& attrs )
  459 {
  460   std::string::size_type seperator = s.find('/');
  461   if ( seperator == std::string::npos )
  462   {
  463     number = s;
  464   }
  465   else
  466   {
  467     number = s.substr(0, seperator);
  468     std::string attributes = s.substr(seperator + 1);
  469 
  470     std::vector<std::string> attr;
  471     tokenise(attributes, attr, ':');
  472     std::vector<std::string>::const_iterator i;
  473     for ( i = attr.begin(); i != attr.end(); ++i )
  474     {
  475       std::vector<std::string> kv;
  476       tokenise(*i, kv, '=');
  477       if ( kv.size() == 2 )
  478       {
  479         attrs.insert(std::map<std::string, std::string>::value_type(kv[0], kv[1]));
  480       }
  481       kv.clear();
  482     }
  483   }
  484 }
  485 
  486 
  487 /*
  488  * Create a channel to manage the call.
  489  */
  490 woomera_server_response* AppDiaStar::makeCall( woomera_callctlr_command* msg )
  491 {
  492   LOGINFO("AppDiaStar::makeCall() callid: " << msg->call_id);
  493 
  494   woomera_callctlr_command_make_call* callParms = &msg->m.make_call;
  495 
  496   woomera_server_response* response = woomera_server_response_new(msg->connection_id);
  497   response->mime = woomera_mime_new();
  498 
  499   const char* rtp_audio = woomera_mime_get_string(msg->incoming_mime,
  500                                                   woomera_key_rtp_audio);
  501   if ( !rtp_audio )
  502   {
  503     LOGERROR("AppDiaStar::makeCall() missing header: " << woomera_key_rtp_audio);
  504     response->response = 400;
  505     strcpy(response->args, "Missing RTP-Audio header");
  506     return response;
  507   }
  508   RtpIpInfo remote_rtp_audio(rtp_audio, RtpIpInfo::SENDRECV);
  509 
  510   const char* rtp_video = woomera_mime_get_string(msg->incoming_mime,
  511                                                   woomera_key_rtp_video);
  512   RtpIpInfo remote_rtp_video(rtp_video, RtpIpInfo::SENDRECV);
  513 
  514   /* local caller id */
  515   std::string local_number = callParms->calling_number;
  516 
  517   std::string local_name;
  518   const char* woomera_local_name = woomera_mime_get_string(msg->incoming_mime,
  519                                                            woomera_key_local_name);
  520   if ( woomera_local_name )
  521   {
  522     /* woomera passes this value as "name!number" */
  523     local_name = woomera_local_name;
  524     std::string::size_type pos = local_name.find('!');
  525     if ( pos != std::string::npos )
  526     {
  527       local_name = local_name.substr(0, pos);
  528     }
  529   }
  530   if ( local_name.empty() )
  531   {
  532     local_name = local_number;
  533   }
  534 
  535   /* dial string */
  536   std::string remote_url;
  537   if ( woomera_mime_includes(msg->common_mime, woomera_key_remote_url) != 0 )
  538   {
  539     remote_url = woomera_mime_get_string(msg->common_mime,
  540                                          woomera_key_remote_url);
  541   }
  542   else
  543   {
  544     remote_url = callParms->called_number;
  545   }
  546 
  547   std::string remote_number;
  548   std::map<std::string, std::string> attrs;
  549   parseDialString(remote_url, remote_number, attrs);
  550 
  551   std::map<std::string, std::string>::const_iterator i;  /* attribs */
  552 
  553   std::string group = "default";
  554   i = attrs.find("group");
  555   if ( i != attrs.end() )
  556   {
  557     group = (*i).second;
  558   }
  559 
  560   LOGDEBUG("AppDiaStar::makeCall() protocol: " << woomera_protocol_get_name(msg->protocol));
  561 
  562   DialogicChannel* channel = 0;
  563   if ( strcmp(woomera_protocol_get_name(msg->protocol), "isdn") == 0 )
  564   {
  565     channel = channelMgr_->createIsdnChannel(group, PROTOCOL_ISDN);
  566   }
  567   else if ( strcmp(woomera_protocol_get_name(msg->protocol), "ss7") == 0 )
  568   {
  569     channel = channelMgr_->createIsdnChannel(group, PROTOCOL_SS7);
  570   }
  571   else if ( strcmp(woomera_protocol_get_name(msg->protocol), "sip") == 0 )
  572   {
  573     channel = channelMgr_->createSipChannel(group);
  574   }
  575   else if ( strcmp(woomera_protocol_get_name(msg->protocol), "h324") == 0 )
  576   {
  577     channel = channelMgr_->createIsdnChannel(group, PROTOCOL_H324);
  578   }
  579   else if ( strcmp(woomera_protocol_get_name(msg->protocol), "conf") == 0 )
  580   {
  581     channel = channelMgr_->createConfChannel(remote_number);
  582   }
  583   else
  584   {
  585     ; /* unreachable */
  586   }
  587 
  588   if ( !channel )
  589   {
  590     LOGWARN("AppDiaStar::makeCall() No channel available");
  591     response->response = 503;
  592     strcpy(response->args, "No channel available");
  593     return response;
  594   }
  595 
  596   /* save client's media info.
  597    */
  598   channel->setRemoteRtpAudioInfo(remote_rtp_audio);
  599   channel->setRemoteRtpVideoInfo(remote_rtp_video);
  600 
  601   if ( channel->getProtocol() == PROTOCOL_CONF )
  602   {
  603     ConfPartyDevice* confParty = channel->getConfPartyDevice();
  604     confParty->setCaption(local_name);
  605 
  606     ConfPartyDevice::Role role = ConfPartyDevice::PRESENTER;
  607     i = attrs.find("role");
  608     if ( i != attrs.end() )
  609     {
  610       if ( (*i).second == "controller" )
  611       {
  612         role = ConfPartyDevice::CONTROLLER;
  613       }
  614       else if ( (*i).second == "presenter" )
  615       {
  616         role = ConfPartyDevice::PRESENTER;
  617       }
  618       else if ( (*i).second == "attendee" )
  619       {
  620         role = ConfPartyDevice::ATTENDEE;
  621       }
  622       else
  623       {
  624         channelMgr_->destroyChannel(channel);
  625         response->response = 400;
  626         strcpy(response->args, "invalid role");
  627         return response;
  628       }
  629     }
  630     confParty->setRole(role);
  631 
  632     i = attrs.find("position");
  633     if ( i != attrs.end() )
  634     {
  635       if ( (*i).second == "none" )
  636       {
  637         confParty->setVisible(false);;
  638       }
  639       else
  640       {
  641         unsigned int position = atoi((*i).second.c_str());
  642         confParty->setPosition(position);
  643       }
  644     }
  645 
  646     ConfDevice* confDevice = channel->getConfDevice();
  647     if ( !confDevice->addParty(confParty) )
  648     {
  649       channelMgr_->destroyChannel(channel);
  650       response->response = 500;
  651       strcpy(response->args, "Call failed");
  652       return response;
  653     }
  654 
  655     i = attrs.find("tiles");
  656     if ( i != attrs.end() )
  657     {
  658       confDevice->setLayout((*i).second);
  659     }
  660   }
  661   else /* isdn, ss7, sip, h324 */
  662   {
  663     bool cpa = false;
  664     i = attrs.find("cpa");
  665     if ( i != attrs.end() )
  666     {
  667       cpa = (*i).second == "yes";
  668     }
  669 
  670     if ( !channel->makeCall(local_number, local_name, remote_number, cpa) )
  671     {
  672       channelMgr_->destroyChannel(channel);
  673       response->response = 500;
  674       strcpy(response->args, "Call failed");
  675       return response;
  676     }
  677   }
  678 
  679   addCall(msg->call_id, channel);
  680 
  681   response->response = 200;
  682   strcpy(response->args, "Call started");
  683   return response;
  684 }
  685 
  686 
  687 /*
  688  * Forward the command to the channel object.
  689  */
  690 woomera_server_response* AppDiaStar::hangupCall( woomera_callctlr_command* msg )
  691 {
  692   LOGINFO("AppDiaStar::hangupCall() callid: " << msg->call_id);
  693 
  694   woomera_server_response* response = woomera_server_response_new(msg->connection_id);
  695 
  696   Call* call = findCall(msg->call_id);
  697   if ( call && call->getChannel() )
  698   {
  699     int cause = GC_NORMAL_CLEARING;
  700     const char* reason = woomera_mime_get_string(msg->incoming_mime,
  701                                                    woomera_key_reason);
  702     if ( reason )
  703     {
  704       cause = atoi(reason);
  705     }
  706 
  707     Channel* channel = call->getChannel();
  708 
  709     if ( channel->getProtocol() == PROTOCOL_CONF )
  710     {
  711       removeCall(msg->call_id);
  712       channelMgr_->destroyChannel((DialogicChannel*)channel);
  713       response->response = 200;
  714       strcpy(response->args, "Call cleared");
  715     }
  716     else /* isdn, ss7, h324, sip */
  717     {
  718       if ( channel->hangup(cause) )
  719       {
  720         removeCall(msg->call_id);
  721         response->response = 200;
  722         strcpy(response->args, "Call cleared");
  723       }
  724       else
  725       {
  726         response->response = 500;
  727         strcpy(response->args, "Unable to hangup call");
  728       }
  729     }
  730     return response;
  731   }
  732 
  733   response->response = 481;
  734   strcpy(response->args, "Call not found");
  735   return response;
  736 }
  737 
  738 
  739 /*
  740  * Forward the command to the channel object.
  741  */
  742 woomera_server_response* AppDiaStar::acceptCall( woomera_callctlr_command* msg )
  743 {
  744   LOGINFO("AppDiaStar::acceptCall() callid: " << msg->call_id);
  745 
  746   woomera_server_response* response = woomera_server_response_new(msg->connection_id);
  747 
  748   Call* call = findCall(msg->call_id);
  749   if ( call && call->getChannel() )
  750   {
  751     Channel* channel = call->getChannel();
  752     if ( channel->accept() )
  753     {
  754       /* save remote rtp ip-address and port. (video is optional)
  755        */
  756       const char* rtp_audio = woomera_mime_get_string(msg->incoming_mime,
  757                                                       woomera_key_rtp_audio);
  758       if ( !rtp_audio )
  759       {
  760         LOGERROR("AppDiaStar::acceptCall() missing header: " << woomera_key_rtp_audio);
  761         return 0;
  762       }
  763       RtpIpInfo remote_rtp_audio(rtp_audio, RtpIpInfo::SENDRECV);
  764 
  765       const char* rtp_video = woomera_mime_get_string(msg->incoming_mime,
  766                                                       woomera_key_rtp_video);
  767       RtpIpInfo* remote_rtp_video = 0;
  768       if ( rtp_video )
  769       {
  770         remote_rtp_video = new RtpIpInfo(rtp_video, RtpIpInfo::SENDRECV);
  771       }
  772 
  773       channel->setRemoteRtpAudioInfo(remote_rtp_audio);
  774 
  775       if ( remote_rtp_video )
  776       {
  777         channel->setRemoteRtpVideoInfo(*remote_rtp_video);
  778         delete remote_rtp_video;
  779       }
  780 
  781       /* save so that onAccept() can send the final response.
  782        */
  783       call->setConnectionId(msg->connection_id);
  784 
  785       response->response = 100;
  786       strcpy(response->args, "Call accepting");
  787     }
  788     else
  789     {
  790       response->response = 500;
  791       strcpy(response->args, "Unable to accept call");
  792     }
  793   }
  794   else
  795   {
  796     response->response = 481;
  797     strcpy(response->args, "Call not found");
  798   }
  799   return response;
  800 }
  801 
  802 
  803 /*
  804  * Forward the command to the channel object.
  805  */
  806 woomera_server_response* AppDiaStar::answerCall( woomera_callctlr_command* msg )
  807 {
  808   LOGINFO("AppDiaStar::answerCall() callid: " << msg->call_id);
  809 
  810   woomera_server_response* response = woomera_server_response_new(msg->connection_id);
  811 
  812   Call* call = findCall(msg->call_id);
  813   if ( call && call->getChannel() )
  814   {
  815     /* save so that onAnswer() can send the final response.
  816      */
  817     call->setConnectionId(msg->connection_id);
  818 
  819     Channel* channel = call->getChannel();
  820     if ( channel->answer() )
  821     {
  822       response->response = 100;
  823       strcpy(response->args, "Call answering");
  824     }
  825     else
  826     {
  827       response->response = 500;
  828       strcpy(response->args, "Unable to answer call");
  829     }
  830   }
  831   else
  832   {
  833     response->response = 481;
  834     strcpy(response->args, "Call not found");
  835   }
  836   return response;
  837 }
  838 
  839 
  840 /*
  841  * Forward the command to the channel object.
  842  */
  843 woomera_server_response* AppDiaStar::sendDtmf( woomera_callctlr_command* msg )
  844 {
  845   LOGINFO("AppDiaStar::sendDtmf() callid: " << msg->call_id);
  846 
  847   woomera_server_response* response = woomera_server_response_new(msg->connection_id);
  848 
  849   Call* call = findCall(msg->call_id);
  850   if ( call && call->getChannel() )
  851   {
  852     Channel* channel = call->getChannel();
  853     if ( channel->sendDtmf(msg->m.dtmf.digits) )
  854     {
  855       /* save so that onSendDtmfCompleted() can send the final response.
  856        */
  857       call->setConnectionId(msg->connection_id);
  858 
  859       response->response = 100;
  860       strcpy(response->args, "Sending dtmf");
  861     }
  862     else
  863     {
  864       response->response = 500;
  865       strcpy(response->args, "Unable to send dtmf");
  866     }
  867   }
  868   else
  869   {
  870     response->response = 481;
  871     strcpy(response->args, "Call not found");
  872   }
  873   return response;
  874 }
  875 
  876 
  877 /*
  878  * Handle a PLAY request.
  879  */
  880 woomera_server_response* AppDiaStar::play( woomera_callctlr_command* msg )
  881 {
  882   LOGINFO("AppDiaStar::play() callid: " << msg->call_id);
  883 
  884   woomera_server_response* response = woomera_server_response_new(msg->connection_id);
  885 
  886   Call* call = findCall(msg->call_id);
  887   if ( call && call->getChannel() )
  888   {
  889     const char* woomera_audio_uri = woomera_mime_get_string(msg->incoming_mime,
  890                                                             woomera_key_audio_uri);
  891 
  892     const char* woomera_video_uri = woomera_mime_get_string(msg->incoming_mime,
  893                                                             woomera_key_video_uri);
  894 
  895     const char* woomera_overlay = woomera_mime_get_string(msg->incoming_mime,
  896                                                           woomera_key_overlay);
  897 
  898     if ( !woomera_audio_uri && !woomera_video_uri && !woomera_overlay)
  899     {
  900       LOGERROR("AppDiaStar::play() no media specified");
  901       response->response = 400;
  902       strcpy(response->args, "No media");
  903       return response;
  904     }
  905 
  906     const char* woomera_stop_digits = woomera_mime_get_string(msg->incoming_mime,
  907                                                               woomera_key_stop_digits);
  908 
  909     const char* woomera_language = woomera_mime_get_string(msg->incoming_mime,
  910                                                            woomera_key_language);
  911 
  912     const char* woomera_repeat = woomera_mime_get_string(msg->incoming_mime,
  913                                                          woomera_key_repeat);
  914 
  915     std::string audio_uri, video_uri, overlay, stop_digits, lang;
  916 
  917     if ( woomera_audio_uri )
  918     {
  919       audio_uri = woomera_audio_uri;
  920     }
  921     if ( woomera_video_uri )
  922     {
  923       video_uri = woomera_video_uri;
  924     }
  925     if ( woomera_overlay )
  926     {
  927       overlay = woomera_overlay;
  928     }
  929     if ( woomera_stop_digits )
  930     {
  931       stop_digits = woomera_stop_digits;
  932     }
  933     if ( woomera_language )
  934     {
  935       lang = woomera_language;
  936     }
  937 
  938     int repeat = 1;
  939     if ( woomera_repeat )
  940     {
  941       if (strcmp("infinite", woomera_repeat) == 0 )
  942       {
  943         repeat = INT_MAX;
  944       }
  945       else
  946       {
  947         repeat = atoi(woomera_repeat);;
  948       }
  949     }
  950 
  951     Channel* channel = call->getChannel();
  952 
  953     if ( (channel->getProtocol() != PROTOCOL_SIP) &&
  954          (channel->getProtocol() != PROTOCOL_H324) &&
  955          (channel->getProtocol() != PROTOCOL_CONF) )
  956     {
  957       response->response = 503;
  958       strcpy(response->args, "Play not supported by call protocol");
  959     }
  960     else
  961     {
  962       if ( audio_uri.empty() && video_uri.empty() && overlay.empty() )
  963       {
  964         response->response = 400;
  965         strcpy(response->args, "No files specified");
  966       }
  967       else
  968       {
  969         if ( channel->play(audio_uri, video_uri, overlay, stop_digits, lang, repeat) )
  970         {
  971           call->setConnectionId(msg->connection_id);
  972 
  973           if ( !audio_uri.empty() || !video_uri.empty() )
  974           {
  975             response->response = 100;
  976             strcpy(response->args, "Starting play");
  977           }
  978           else /* overlay only */
  979           {
  980             response->response = 200;
  981             strcpy(response->args, "Play started");
  982           }
  983         }
  984         else
  985         {
  986           response->response = 500;
  987           strcpy(response->args, "Play request failed");
  988         }
  989       }
  990     }
  991   }
  992   else
  993   {
  994     response->response = 481;
  995     strcpy(response->args, "Call not found");
  996   }
  997   return response;
  998 }
  999 
 1000 
 1001 /*
 1002  * Handle a RECORD request.
 1003  */
 1004 woomera_server_response* AppDiaStar::record( woomera_callctlr_command* msg )
 1005 {
 1006   LOGINFO("AppDiaStar::record() callid: " << msg->call_id);
 1007 
 1008   woomera_server_response* response = woomera_server_response_new(msg->connection_id);
 1009 
 1010   Call* call = findCall(msg->call_id);
 1011   if ( call && call->getChannel() )
 1012   {
 1013     const char* woomera_audio_uri = woomera_mime_get_string(msg->incoming_mime,
 1014                                                             woomera_key_audio_uri);
 1015 
 1016     const char* woomera_video_uri = woomera_mime_get_string(msg->incoming_mime,
 1017                                                             woomera_key_video_uri);
 1018 
 1019     if ( !woomera_audio_uri && !woomera_video_uri )
 1020     {
 1021       LOGERROR("AppDiaStar::record() no media specified");
 1022       response->response = 400;
 1023       strcpy(response->args, "No media");
 1024       return response;
 1025     }
 1026 
 1027     const char* woomera_stop_digits = woomera_mime_get_string(msg->incoming_mime,
 1028                                                               woomera_key_stop_digits);
 1029 
 1030     const char* woomera_language = woomera_mime_get_string(msg->incoming_mime,
 1031                                                            woomera_key_language);
 1032 
 1033     const char* woomera_beep = woomera_mime_get_string(msg->incoming_mime,
 1034                                                        woomera_key_beep);
 1035 
 1036     const char* woomera_max_time = woomera_mime_get_string(msg->incoming_mime,
 1037                                                            woomera_key_max_time);
 1038 
 1039     std::string audio_uri, video_uri, stop_digits, lang;
 1040     bool beep = true;
 1041     unsigned int max_time = 0;  /* default to unlimited */
 1042 
 1043     if ( woomera_audio_uri )
 1044     {
 1045       audio_uri = woomera_audio_uri;
 1046     }
 1047     if ( woomera_video_uri )
 1048     {
 1049       video_uri = woomera_video_uri;
 1050     }
 1051     if ( woomera_stop_digits )
 1052     {
 1053       stop_digits = woomera_stop_digits;
 1054     }
 1055     if ( woomera_language )
 1056     {
 1057       lang = woomera_language;
 1058     }
 1059     if ( woomera_beep )
 1060     {
 1061       beep = (strcmp(woomera_beep, "yes") == 0);
 1062     }
 1063     if ( woomera_max_time )
 1064     {
 1065       max_time = (unsigned int) atoi(woomera_max_time);
 1066       max_time *= 1000;  /* scale to ms */
 1067     }
 1068     Channel* channel = call->getChannel();
 1069 
 1070     if ( (channel->getProtocol() != PROTOCOL_SIP) &&
 1071          (channel->getProtocol() != PROTOCOL_H324) &&
 1072          (channel->getProtocol() != PROTOCOL_CONF) )
 1073     {
 1074       response->response = 503;
 1075       strcpy(response->args, "Record not supported by call protocol");
 1076     }
 1077     else
 1078     {
 1079       if ( audio_uri.empty() && video_uri.empty() )
 1080       {
 1081         response->response = 400;
 1082         strcpy(response->args, "No files specified");
 1083       }
 1084       else
 1085       {
 1086         if ( channel->record(audio_uri, video_uri, stop_digits, lang, beep, max_time) )
 1087         {
 1088           call->setConnectionId(msg->connection_id);
 1089 
 1090           response->response = 100;
 1091           strcpy(response->args, "Starting record");
 1092         }
 1093         else
 1094         {
 1095           response->response = 500;
 1096           strcpy(response->args, "Record request failed");
 1097         }
 1098       }
 1099     }
 1100   }
 1101   else
 1102   {
 1103     response->response = 481;
 1104     strcpy(response->args, "Call not found");
 1105   }
 1106   return response;
 1107 }
 1108 
 1109 
 1110 /*
 1111  * Handle a STOP (play/record) request.
 1112  */
 1113 woomera_server_response* AppDiaStar::stop( woomera_callctlr_command* msg )
 1114 {
 1115   LOGINFO("AppDiaStar::stop() callid: " << msg->call_id);
 1116 
 1117   woomera_server_response* response = woomera_server_response_new(msg->connection_id);
 1118 
 1119   Call* call = findCall(msg->call_id);
 1120   if ( call && call->getChannel() )
 1121   {
 1122     Channel* channel = call->getChannel();
 1123 
 1124     if ( (channel->getProtocol() != PROTOCOL_SIP) &&
 1125          (channel->getProtocol() != PROTOCOL_CONF) )
 1126     {
 1127       response->response = 503;
 1128       strcpy(response->args, "Stop not supported by call protocol");
 1129     }
 1130     else
 1131     {
 1132       if ( channel->stop() )
 1133       {
 1134         response->response = 200;
 1135         strcpy(response->args, "Stopping");
 1136       }
 1137       else
 1138       {
 1139         response->response = 500;
 1140         strcpy(response->args, "Stop failed");
 1141       }
 1142     }
 1143   }
 1144   else
 1145   {
 1146     response->response = 481;
 1147     strcpy(response->args, "Call not found");
 1148   }
 1149   return response;
 1150 }
 1151 
 1152 
 1153 /*
 1154  * Handle an UPDATE request.
 1155  *
 1156  * For media updates:
 1157  *   If the new rtp parameters refer to a another channel, the connection is
 1158  *   done internally to avoid extra trancoding steps. Otherwise, streaming is
 1159  *   restarted using the new rtp values.
 1160  *   When MEDIA requests are used to optimise bridging between channels, each
 1161  *   channel will receive its own request so the connections referred to here
 1162  *   are half-duplex.
 1163  */
 1164 woomera_server_response* AppDiaStar::update( woomera_callctlr_command* msg )
 1165 {
 1166   LOGINFO("AppDiaStar::update() callid: " << msg->call_id);
 1167 
 1168   woomera_server_response* response = woomera_server_response_new(msg->connection_id);
 1169 
 1170   Call* call = findCall(msg->call_id);
 1171   if ( call && call->getChannel() )
 1172   {
 1173     Channel* channel = call->getChannel();
 1174 
 1175     /* Media */
 1176 
 1177     const char* rtp_audio = woomera_mime_get_string(msg->incoming_mime,
 1178                                                     woomera_key_rtp_audio);
 1179 
 1180     const char* rtp_video = woomera_mime_get_string(msg->incoming_mime,
 1181                                                     woomera_key_rtp_video);
 1182 
 1183     if ( rtp_audio || rtp_video)
 1184     {
 1185       call->setConnectionId(msg->connection_id); /* Async completion. */
 1186 
 1187       RtpIpInfo remote_rtp_audio(rtp_audio, RtpIpInfo::SENDRECV);
 1188       RtpIpInfo remote_rtp_video(rtp_video, RtpIpInfo::SENDRECV);
 1189 
 1190       /* If the new rtp values are local to this server, try to optimise
 1191        * the connection(s) internally.
 1192        */
 1193       Channel* other_channel = channelMgr_->findChannel(remote_rtp_audio, remote_rtp_video);
 1194       if ( other_channel && channel->isBridged() )
 1195       {
 1196         /* Already bridged internally. */
 1197         response->response = 409;
 1198         strcpy(response->args, "Conflict");
 1199       }
 1200       else
 1201       {
 1202         channel->stopMedia();
 1203 
 1204         if ( config_.isBridgeInternal() && other_channel && channel->bridge(other_channel) )
 1205         {
 1206           LOGDEBUG("AppDiaStar::update() optimised connection to channel: " << std::hex << other_channel);
 1207           response->response = 100;
 1208           strcpy(response->args, "Updating rtp");
 1209         }
 1210         else /* External. */
 1211         {
 1212           LOGDEBUG("AppDiaStar::update() remote rtp: a=" << remote_rtp_audio << ", v=" << remote_rtp_video);
 1213 
 1214           if ( rtp_audio )
 1215           {
 1216             channel->setRemoteRtpAudioInfo(remote_rtp_audio);
 1217           }
 1218           if ( rtp_video )
 1219           {
 1220             channel->setRemoteRtpVideoInfo(remote_rtp_video);
 1221           }
 1222 
 1223           if ( channel->startMedia() )
 1224           {
 1225             if ( channel->unbridge() )
 1226             {
 1227               response->response = 100;
 1228               strcpy(response->args, "Updating rtp");
 1229             }
 1230             else
 1231             {
 1232               response->response = 200;
 1233               strcpy(response->args, "Updated rtp");
 1234             }
 1235           }
 1236           else
 1237           {
 1238             response->response = 500;
 1239             strcpy(response->args, "Update request failed");
 1240           }
 1241         }
 1242       }
 1243     }
 1244 
 1245     /* Event notifications */
 1246 
 1247     const char* tone_events = woomera_mime_get_string(msg->incoming_mime,
 1248                                                       woomera_key_tone_events);
 1249     if ( tone_events )
 1250     {
 1251       if ( strcmp(tone_events, "enable") == 0 )
 1252       {
 1253         LOGDEBUG("AppDiaStar::update() enable tone events");
 1254         channel->enableToneEvents();
 1255       }
 1256       else
 1257       {
 1258         LOGDEBUG("AppDiaStar::update() disable tone events");
 1259         channel->disableToneEvents();
 1260       }
 1261       response->response = 200;
 1262       strcpy(response->args, "OK");
 1263     }
 1264 
 1265     const char* info_events = woomera_mime_get_string(msg->incoming_mime,
 1266                                                       woomera_key_info_events);
 1267     if ( info_events )
 1268     {
 1269       if ( strcmp(info_events, "enable") == 0 )
 1270       {
 1271         LOGDEBUG("AppDiaStar::update() enable info events");
 1272         channel->enableInfoEvents();
 1273       }
 1274       else
 1275       {
 1276         LOGDEBUG("AppDiaStar::update() disable info events");
 1277         channel->disableInfoEvents();
 1278       }
 1279       response->response = 200;
 1280       strcpy(response->args, "OK");
 1281     }
 1282   }
 1283   else
 1284   {
 1285     response->response = 481;
 1286     strcpy(response->args, "Call not found");
 1287   }
 1288   return response;
 1289 }
 1290 
 1291 
 1292 /*
 1293  * Forward the event to Woomera.
 1294  */
 1295 void AppDiaStar::onIncoming( Channel* channel,
 1296                              const std::string& local_number,
 1297                              const std::string& local_uri,
 1298                              const std::string& remote_number,
 1299                              const std::string& remote_name )
 1300 {
 1301   LOGDEBUG("AppDiaStar::onIncoming() " << std::hex << channel);
 1302 
 1303   woomera_callctlr_incoming_call_info* info = woomera_callctlr_incoming_call_info_new();
 1304 
 1305   if ( !info->common_mime )
 1306   {
 1307     info->common_mime = woomera_mime_new();
 1308   }
 1309 
 1310   copy_string_to_c_array(local_number, info->local_number, sizeof(info->local_number));
 1311   copy_string_to_c_array(local_uri, info->local_url, sizeof(info->local_url));   /* Woomera uses URL */
 1312   copy_string_to_c_array(remote_number, info->remote_number, sizeof(info->remote_number));
 1313   copy_string_to_c_array(remote_name, info->remote_name, sizeof(info->remote_name));
 1314 
 1315   if ( channel->getProtocol() == PROTOCOL_ISDN )
 1316   {
 1317     strcpy(info->scheme, "isdn");
 1318   }
 1319   else if ( channel->getProtocol() == PROTOCOL_SS7 )
 1320   {
 1321     strcpy(info->scheme, "ss7");
 1322   }
 1323   else if ( channel->getProtocol() == PROTOCOL_H324 )
 1324   {
 1325     strcpy(info->scheme, "h324");
 1326   }
 1327   else /* PROTOCOL_SIP */
 1328   {
 1329     strcpy(info->scheme, "sip");
 1330   }
 1331 
 1332   /* Tell Woomera, it will take ownership of 'info' and fill in the callid.
 1333    */
 1334   if ( woomera_callctlr_on_incoming_call(woomeraCallCtlr_, info) == 0 )
 1335   {
 1336     addCall(info->call_id, channel);
 1337     LOGINFO("AppDiaStar::onIncoming() callid: " << info->call_id);
 1338   }
 1339   else
 1340   {
 1341     LOGERROR("AppDiaStar::onIncoming() woomera_callctlr_on_incoming_call() failed");
 1342     channel->hangup(27);  /* O.O.O.*/
 1343   }
 1344 }
 1345 
 1346 
 1347 /*
 1348  * Accept completion, forward the event to Woomera.
 1349  */
 1350 void AppDiaStar::onAccepted( Channel* channel )
 1351 {
 1352   LOGDEBUG("AppDiaStar::onAccepted() " << std::hex << channel);
 1353 
 1354   Call* call = findCall(channel);
 1355   if ( call )
 1356   {
 1357     LOGINFO("AppDiaStar::onAccepted() callid: " << call->getId());
 1358 
 1359     woomera_server_response* response = woomera_server_response_new(call->getConnectionId());
 1360 
 1361     response->mime = woomera_mime_new();
 1362 
 1363     /* include the local media details in the response.
 1364      */
 1365     RtpIpInfo local_rtp_audio;
 1366     channel->getLocalRtpAudioInfo(local_rtp_audio);
 1367     woomera_mime_set_string(response->mime,
 1368                             woomera_key_rtp_audio,
 1369                             local_rtp_audio.getAddressAndPort().c_str());
 1370 
 1371     if ( channel->isVideo() )
 1372     {
 1373       RtpIpInfo local_rtp_video;
 1374       channel->getLocalRtpVideoInfo(local_rtp_video);
 1375       woomera_mime_set_string(response->mime,
 1376                               woomera_key_rtp_video,
 1377                               local_rtp_video.getAddressAndPort().c_str());
 1378     }
 1379 
 1380     woomera_mime_set_string(response->mime, woomera_key_dtmf, "OutofBand");
 1381 
 1382     response->response = 200;
 1383     strcpy(response->args, "Call accepted");
 1384 
 1385     woomera_server_send_response(woomeraServer_, response);
 1386   }
 1387 }
 1388 
 1389 
 1390 /*
 1391  * Answer completion, forward the event to Woomera.
 1392  */
 1393 void AppDiaStar::onAnswered( Channel* channel )
 1394 {
 1395   LOGDEBUG("AppDiaStar::onAnswered() " << std::hex << channel);
 1396 
 1397   Call* call = findCall(channel);
 1398   if ( call )
 1399   {
 1400     LOGINFO("AppDiaStar::onAnswered() callid: " << call->getId());
 1401 
 1402     woomera_server_response* response = woomera_server_response_new(call->getConnectionId());
 1403 
 1404     response->mime = woomera_mime_new();
 1405 
 1406     /* include the local media details in the response.
 1407      */
 1408     RtpIpInfo local_rtp_audio;
 1409     channel->getLocalRtpAudioInfo(local_rtp_audio);
 1410     woomera_mime_set_string(response->mime,
 1411                             woomera_key_rtp_audio,
 1412                             local_rtp_audio.getAddressAndPort().c_str());
 1413 
 1414     if ( channel->isVideo() )
 1415     {
 1416       RtpIpInfo local_rtp_video;
 1417       channel->getLocalRtpVideoInfo(local_rtp_video);
 1418       woomera_mime_set_string(response->mime,
 1419                               woomera_key_rtp_video,
 1420                               local_rtp_video.getAddressAndPort().c_str());
 1421     }
 1422 
 1423     woomera_mime_set_string(response->mime, woomera_key_dtmf, "OutofBand");
 1424 
 1425     response->response = 200;
 1426     strcpy(response->args, "Call answered");
 1427 
 1428     woomera_server_send_response(woomeraServer_, response);
 1429   }
 1430 }
 1431 
 1432 
 1433 /*
 1434  * Forward to Woomera as proceeding and media events.
 1435  */
 1436 void AppDiaStar::onProceeding( Channel* channel )
 1437 {
 1438   LOGDEBUG("AppDiaStar::onProceeding() " << std::hex << channel);
 1439 
 1440   Call* call = findCall(channel);
 1441   if ( call )
 1442   {
 1443     LOGINFO("AppDiaStar::onProceeding() callid: " << call->getId());
 1444 
 1445     woomera_callctlr_on_proceeding(woomeraCallCtlr_,
 1446                                    call->getId().c_str());
 1447 
 1448     if ( !call->sentMediaEvent() )
 1449     {
 1450       onMedia(channel);
 1451       call->setSentMediaEvent();
 1452     }
 1453   }
 1454 }
 1455 
 1456 
 1457 /*
 1458  * Forward the event to Woomera.
 1459  */
 1460 void AppDiaStar::onRinging( Channel* channel )
 1461 {
 1462   LOGDEBUG("AppDiaStar::onRinging() " << std::hex << channel);
 1463 
 1464   Call* call = findCall(channel);
 1465   if ( call )
 1466   {
 1467     LOGINFO("AppDiaStar::onRinging() callid: " << call->getId());
 1468 
 1469     woomera_callctlr_on_ringing(woomeraCallCtlr_,
 1470                                 call->getId().c_str(),
 1471                                 false);
 1472 
 1473     if ( !call->sentMediaEvent() )
 1474     {
 1475       onMedia(channel);
 1476       call->setSentMediaEvent();
 1477     }
 1478   }
 1479 }
 1480 
 1481 
 1482 /*
 1483  * Forward the event to Woomera.
 1484  */
 1485 void AppDiaStar::onHangup( Channel* channel,
 1486                            int cause,
 1487                            const std::string& cause_text,
 1488                            const std::string& conn_type )
 1489 {
 1490   LOGDEBUG("AppDiaStar::onHangup() " << std::hex << channel);
 1491 
 1492   Call* call = findCall(channel);
 1493   if ( call )
 1494   {
 1495     LOGINFO("AppDiaStar::onHangup() callid: " << call->getId() <<
 1496             ", cause: " << cause << " \"" << cause_text << "\"");
 1497 
 1498     woomera_callctlr_on_clear(woomeraCallCtlr_,
 1499                               call->getId().c_str(),
 1500                               cause,
 1501                               cause_text.c_str(),
 1502                               conn_type.empty() ? 0 : conn_type.c_str());
 1503     removeCall(call->getId());
 1504   }
 1505 }
 1506 
 1507 
 1508 /*
 1509  * Forward the event to Woomera.
 1510  */
 1511 void AppDiaStar::onConnect( Channel* channel, const std::string& conn_type )
 1512 {
 1513   LOGDEBUG("AppDiaStar::onConnect() " << std::hex << channel);
 1514 
 1515   Call* call = findCall(channel);
 1516   if ( call )
 1517   {
 1518     LOGINFO("AppDiaStar::onConnect() callid: " << call->getId());
 1519 
 1520     woomera_callctlr_on_connect(woomeraCallCtlr_,
 1521                                 call->getId().c_str(),
 1522                                 false,
 1523                                 conn_type.c_str());
 1524 
 1525     if ( !call->sentMediaEvent() )
 1526     {
 1527       onMedia(channel);
 1528       call->setSentMediaEvent();
 1529     }
 1530   }
 1531 }
 1532 
 1533 
 1534 /*
 1535  * Forward to Woomera.
 1536  */
 1537 void AppDiaStar::onMedia( Channel* channel )
 1538 {
 1539   LOGDEBUG("AppDiaStar::onMedia() " << std::hex << channel);
 1540 
 1541   Call* call = findCall(channel);
 1542   if ( call )
 1543   {
 1544     LOGINFO("AppDiaStar::onMedia() callid: " << call->getId());
 1545 
 1546     RtpIpInfo local_rtp_audio;
 1547     channel->getLocalRtpAudioInfo(local_rtp_audio);
 1548 
 1549     RtpIpInfo local_rtp_video;
 1550     channel->getLocalRtpVideoInfo(local_rtp_video);
 1551 
 1552     woomera_callctlr_on_media(woomeraCallCtlr_,
 1553                               call->getId().c_str(),
 1554                               local_rtp_audio.getAddressAndPort().c_str(),
 1555                               /* XXX
 1556                               channel->isVideo() ? local_rtp_video.getAddressAndPort().c_str() : NULL,
 1557                               */
 1558                               local_rtp_video.getAddressAndPort().c_str(),
 1559                               config_.isOutOfBandDtmf());
 1560   }
 1561 }
 1562 
 1563 
 1564 /*
 1565  * Forward the event to Woomera.
 1566  */
 1567 void AppDiaStar::onDtmf( Channel* channel, const std::string& digits )
 1568 {
 1569   Call* call = findCall(channel);
 1570   if ( call && !digits.empty() )
 1571   {
 1572     LOGINFO("AppDiaStar::onDtmf() callid: " << call->getId() <<
 1573             " digits: \"" << digits << "\"");
 1574 
 1575     woomera_callctlr_on_dtmf(woomeraCallCtlr_,
 1576                                call->getId().c_str(),
 1577                                digits.c_str());
 1578   }
 1579 }
 1580 
 1581 
 1582 /*
 1583  * Forward the event to Woomera.
 1584  */
 1585 void AppDiaStar::onTone( Channel* channel, const std::string& name )
 1586 {
 1587   Call* call = findCall(channel);
 1588   if ( call )
 1589   {
 1590     LOGINFO("AppDiaStar::onTone() callid: " << call->getId() <<
 1591             " tone: \"" << name << "\"");
 1592 
 1593     woomera_callctlr_on_tone(woomeraCallCtlr_,
 1594                                call->getId().c_str(),
 1595                                name.c_str());
 1596   }
 1597 }
 1598 
 1599 
 1600 /*
 1601  * Forward the event to Woomera.
 1602  */
 1603 void AppDiaStar::onInfo( Channel* channel,
 1604                        const std::string& mimetype,
 1605                        const std::string& content )
 1606 {
 1607   Call* call = findCall(channel);
 1608   if ( call )
 1609   {
 1610     LOGINFO("AppDiaStar::onInfo() callid: " << call->getId() <<
 1611             " mimetype: \"" << mimetype << "\"");
 1612 
 1613     woomera_callctlr_on_info(woomeraCallCtlr_,
 1614                                call->getId().c_str(),
 1615                                mimetype.c_str(),
 1616                                content.c_str());
 1617   }
 1618 }
 1619 
 1620 
 1621 /*
 1622  * Forward the event to Woomera.
 1623  */
 1624 void AppDiaStar::onSendDtmfCompleted( Channel* channel )
 1625 {
 1626   LOGINFO("AppDiaStar::onSendDtmfCompleted() " << std::hex << channel);
 1627 
 1628   Call* call = findCall(channel);
 1629   if ( call )
 1630   {
 1631     woomera_server_response* response = woomera_server_response_new(call->getConnectionId());
 1632 
 1633     response->mime = woomera_mime_new();
 1634 
 1635     response->response = 200;
 1636     strcpy(response->args, "SendDtmf completed");
 1637 
 1638     woomera_server_send_response(woomeraServer_, response);
 1639   }
 1640 }
 1641 
 1642 
 1643 /*
 1644  * Play started, forward the event to Woomera.
 1645  */
 1646 void AppDiaStar::onPlayOk( Channel* channel )
 1647 {
 1648   LOGDEBUG("AppDiaStar::onPlayOk() " << std::hex << channel);
 1649 
 1650   Call* call = findCall(channel);
 1651   if ( call )
 1652   {
 1653     LOGINFO("AppDiaStar::onPlayOk() callid: " << call->getId());
 1654 
 1655     woomera_server_response* response = woomera_server_response_new(call->getConnectionId());
 1656 
 1657     response->response = 200;
 1658     strcpy(response->args, "Play started");
 1659 
 1660     woomera_server_send_response(woomeraServer_, response);
 1661   }
 1662 }
 1663 
 1664 
 1665 /*
 1666  * Play request failed, forward the event to Woomera.
 1667  */
 1668 void AppDiaStar::onPlayFail( Channel* channel )
 1669 {
 1670   LOGDEBUG("AppDiaStar::onPlayFail() " << std::hex << channel);
 1671 
 1672   Call* call = findCall(channel);
 1673   if ( call )
 1674   {
 1675     LOGINFO("AppDiaStar::onPlayFail() callid: " << call->getId());
 1676 
 1677     woomera_server_response* response = woomera_server_response_new(call->getConnectionId());
 1678 
 1679     response->response = 400;
 1680     strcpy(response->args, "Play failed");
 1681 
 1682     woomera_server_send_response(woomeraServer_, response);
 1683   }
 1684 }
 1685 
 1686 
 1687 /*
 1688  * Forward the event to Woomera.
 1689  */
 1690 void AppDiaStar::onPlayCompleted( Channel* channel,
 1691                                   const std::string& reason,
 1692                                   unsigned int duration )
 1693 {
 1694   LOGINFO("AppDiaStar::onPlayCompleted() " << std::hex << channel);
 1695 
 1696   Call* call = findCall(channel);
 1697   if ( call )
 1698   {
 1699     std::stringstream ss;
 1700     ss << duration;
 1701     woomera_callctlr_on_play_completed(woomeraCallCtlr_,
 1702                                        call->getId().c_str(),
 1703                                        reason.c_str(),
 1704                                        ss.str().c_str());
 1705   }
 1706 }
 1707 
 1708 
 1709 /*
 1710  * Record started, forward the event to Woomera.
 1711  */
 1712 void AppDiaStar::onRecordOk( Channel* channel )
 1713 {
 1714   LOGDEBUG("AppDiaStar::onRecordOk() " << std::hex << channel);
 1715 
 1716   Call* call = findCall(channel);
 1717   if ( call )
 1718   {
 1719     LOGINFO("AppDiaStar::onRecordOk() callid: " << call->getId());
 1720 
 1721     woomera_server_response* response = woomera_server_response_new(call->getConnectionId());
 1722 
 1723     response->response = 200;
 1724     strcpy(response->args, "Record started");
 1725 
 1726     woomera_server_send_response(woomeraServer_, response);
 1727   }
 1728 }
 1729 
 1730 
 1731 /*
 1732  * Record request failed, forward the event to Woomera.
 1733  */
 1734 void AppDiaStar::onRecordFail( Channel* channel )
 1735 {
 1736   LOGDEBUG("AppDiaStar::onRecordFail() " << std::hex << channel);
 1737 
 1738   Call* call = findCall(channel);
 1739   if ( call )
 1740   {
 1741     LOGINFO("AppDiaStar::onRecordFail() callid: " << call->getId());
 1742 
 1743     woomera_server_response* response = woomera_server_response_new(call->getConnectionId());
 1744 
 1745     response->response = 400;
 1746     strcpy(response->args, "Record failed");
 1747 
 1748     woomera_server_send_response(woomeraServer_, response);
 1749   }
 1750 }
 1751 
 1752 
 1753 /*
 1754  * Forward the event to Woomera.
 1755  */
 1756 void AppDiaStar::onRecordCompleted( Channel* channel,
 1757                                     const std::string& reason,
 1758                                     unsigned int duration )
 1759 {
 1760   LOGINFO("AppDiaStar::onRecordCompleted() " << std::hex << channel);
 1761 
 1762   Call* call = findCall(channel);
 1763   if ( call )
 1764   {
 1765     std::stringstream ss;
 1766     ss << duration;
 1767     woomera_callctlr_on_record_completed(woomeraCallCtlr_,
 1768                                          call->getId().c_str(),
 1769                                          reason.c_str(),
 1770                                          ss.str().c_str());
 1771   }
 1772 }
 1773 
 1774 /*
 1775  * Forward the event to Woomera.
 1776  */
 1777 void AppDiaStar::onBridgeCompleted( Channel* channel )
 1778 {
 1779   LOGDEBUG("AppDiaStar::onBridgedCompleted() " << std::hex << channel);
 1780 
 1781   Call* call = findCall(channel);
 1782   if ( call )
 1783   {
 1784     LOGINFO("AppDiaStar::onBridgedCompleted() callid: " << call->getId());
 1785 
 1786     woomera_server_response* response = woomera_server_response_new(call->getConnectionId());
 1787 
 1788     response->response = 200;
 1789     strcpy(response->args, "Update rtp completed");
 1790 
 1791     woomera_server_send_response(woomeraServer_, response);
 1792   }
 1793 }
 1794 
 1795 /* vim:ts=4:set nu:
 1796  * EOF
 1797  */

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.8