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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1218 - (download) (annotate)
Wed Jun 6 13:16:07 2012 UTC (11 months, 1 week ago) by jtarlton
File size: 35656 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        dialogicchannelmanager.cxx
   30  * \brief       Manager for Dialogic channels.
   31  * \author      Antony Martin <antony.martin@dialogic.com>
   32  * \author      John Tarlton <john.tarlton@dialogic.com>
   33  * \version     30-MAR-2009
   34  */
   35 
   36 /*-------------------------------- Dependencies ------------------------------*/
   37 
   38 #include <arpa/inet.h>     // inet_pton
   39 
   40 #include <iostream>
   41 #include <fstream>
   42 #include <algorithm>
   43 #include <string.h>        // memset
   44 
   45 #include <gclib.h>
   46 #include <srllib.h>
   47 
   48 
   49 #ifndef lint               // suppress warning about ‘_hsw_1_devmapr4_h’
   50 # define lint
   51 #  include <devmapr4.h>
   52 #  include <gcip.h>
   53 # undef  lint
   54 #else
   55 # include <devmapr4.h>
   56 # include <gcip.h>
   57 #endif
   58 
   59 #include "net-util.h"
   60 #include "logger.h"
   61 #include "inifile.h"
   62 #include "string-util.h"
   63 #include "appevent.h"
   64 
   65 #include "mediastatemachine.h"
   66 #include "dialogicchannelmanager.h"
   67 
   68 /*----------------------------------------------------------------------------*/
   69 
   70 /*
   71  * ctor, store the application's callback client.
   72  */
   73 DialogicChannelManager::DialogicChannelManager( ChannelManagerClient& client,
   74                                                 Config& config )
   75   : client_ (client),
   76     config_ (config),
   77     imageMakerThread_ (imagemaker_event_callback),
   78     rtspConnector_ ("DiaStarServer", rtspconnector_event_callback),
   79     total_ (0)
   80 {
   81   LOGDEBUG("DialogicChannelManager::DialogicChannelManager()");
   82 
   83   buildMediaStateMachine(mediaStateMachine_);
   84 }
   85 
   86 
   87 /*
   88  * Cleanup channels and call shutdown() to cleanup the devices.
   89  */
   90 DialogicChannelManager::~DialogicChannelManager()
   91 {
   92   LOGDEBUG("DialogicChannelManager::~DialogicChannelManager()");
   93 
   94   for ( channel_t::iterator i = channels_.begin(); i != channels_.end(); ++i )
   95   {
   96     delete *i;
   97   }
   98 
   99   shutdown();
  100 }
  101 
  102 
  103 /*
  104  * Start global call, load device configuration and create devices.
  105  * If the conf file is undefined, probe the devices and create a default
  106  * dti group (test mode).
  107  */
  108 bool DialogicChannelManager::start( const std::string& conf )
  109 {
  110   if ( conf.empty() && init() )
  111   {
  112     LOGDEBUG("DialogicChannelManager::start() no conf file specified, using defaults.");
  113     if ( !config_.detectDevices(true) )
  114     {
  115       return false;
  116     }
  117 
  118     /* create a 'default' group for all dti devices.
  119      */
  120     GroupManager<GcIsdnDevice>::Group* grp = config_.gcGroups.add("default");
  121     int pos = 1;
  122 
  123     std::vector<Config::DtiBoardConfig>::iterator i = config_.dtiBoards.begin();
  124     for ( ; i != config_.dtiBoards.end(); ++i )
  125     {
  126       std::vector<Config::DtiConfig>::iterator j;
  127       for ( j = (*i).dti.begin(); j != (*i).dti.end(); ++j )
  128       {
  129         (*j).groups.push_back(Config::DtiConfig::group_membership_t(grp, pos++));
  130       }
  131     }
  132 
  133     return openDevices();
  134   }
  135 
  136   if ( config_.loadConf(conf) && init() )
  137   {
  138     if ( !toneDetector_.load(config_.getToneTemplatePath()) )
  139     {
  140       return false;
  141     }
  142 
  143     if ( !imageMakerThread_.init("/etc/diastar/imagemaker.d",
  144                                  "/var/lib/diastar/imagemaker/images") )
  145     {
  146       return false;
  147     }
  148 
  149     if ( !openDevices() )
  150     {
  151       return false;
  152     }
  153 
  154     mediaFinder_.setMediaDir(config_.getMediaDir());
  155     mediaFinder_.setLanguage(config_.getLanguage());
  156 
  157     rtspConnector_.start();
  158 
  159     return true;
  160   }
  161 
  162   return false;
  163 }
  164 
  165 
  166 /*
  167  * Close devices, delete device objects and stop global call.
  168  */
  169 void DialogicChannelManager::shutdown()
  170 {
  171   closeDevices();
  172 
  173   for ( device_map_t::iterator i = deviceMap_.begin(); i != deviceMap_.end(); ++i )
  174   {
  175     delete (*i).second;
  176   }
  177 
  178   for ( board_map_t::iterator j = boardMap_.begin(); j != boardMap_.end(); ++j )
  179   {
  180     delete (*j).second;
  181   }
  182 
  183   LOGDEBUG("DialogicChannelManager::shutdown() Stopping Global Call");
  184   gc_Stop();
  185 }
  186 
  187 
  188 /*
  189  * Configure dialogic libs.
  190  */
  191 bool DialogicChannelManager::init()
  192 {
  193   /* Init Dialogic's standard runtime lib.
  194    */
  195 #ifdef _WIN32
  196   int mode = SR_STASYNC | SR_POLLMODE;
  197   if ( sr_setparm(SRL_DEVICE, SR_MODELTYPE, &mode) == -1 )
  198   {
  199     LOGCRIT("DialogicChannelManager::init() sr_setparm(SR_STASYNC | SR_POLLMODE) failed.");
  200     return false;
  201   }
  202 #else
  203   int mode = SR_POLLMODE;
  204   if ( sr_setparm(SRL_DEVICE, SR_MODEID, &mode) == -1 )
  205   {
  206     LOGCRIT("DialogicChannelManager::init() sr_setparm(SR_POLLMODE) failed.");
  207     return false;
  208   }
  209 #endif
  210 
  211   /*
  212    * IP configuration (SIP only).
  213    */
  214   IP_VIRTBOARD* ipVirtBoards = 0;
  215   if ( config_.iptBoards.size() > 0 )
  216   {
  217     ipVirtBoards = new IP_VIRTBOARD[config_.iptBoards.size()];
  218 
  219     int n = 0;
  220     std::vector<Config::IptBoardConfig>::const_iterator i = config_.iptBoards.begin();
  221     for ( ; i != config_.iptBoards.end(); ++i )
  222     {
  223       IP_VIRTBOARD* ipVirtBoard = &ipVirtBoards[n];
  224       INIT_IP_VIRTBOARD(ipVirtBoard);
  225 
  226       unsigned long local_ip = 0L;
  227       inet_pton(AF_INET, (*i).localAddrInfo.getAddress().c_str(), &local_ip);
  228       int sip_signaling_port = (*i).localAddrInfo.getPort();
  229 
  230       LOGINFO("DialogicChannelManager::init() binding board: " << (*i).name <<
  231               " to: " << (*i).localAddrInfo.getAddress() << ", port: " << sip_signaling_port);
  232 
  233       ipVirtBoard->total_max_calls     = (*i).maxCalls;
  234       ipVirtBoard->localIP.ip_ver      = IPVER4;
  235       ipVirtBoard->localIP.u_ipaddr.ipv4 = local_ip;
  236       ipVirtBoard->sip_max_calls       = (*i).maxCalls;
  237       ipVirtBoard->h323_max_calls      = IP_CFG_NO_CALLS;
  238       ipVirtBoard->sip_signaling_port  = sip_signaling_port;
  239       ipVirtBoard->sip_msginfo_mask    = IP_SIP_MSGINFO_ENABLE | IP_SIP_MIME_ENABLE;
  240 
  241       /* Optional outbound proxy.
  242        */
  243       if ( (*i).proxyAddrInfo.isValid() )
  244       {
  245         LOGINFO("DialogicChannelManager::init() setting outbound proxy for board: " <<
  246                 (*i).name << " to: " << (*i).proxyAddrInfo);
  247         unsigned long  proxy_ip = 0L;
  248         inet_pton(AF_INET, (*i).proxyAddrInfo.getAddress().c_str(), &proxy_ip);
  249         int proxy_port = (*i).proxyAddrInfo.getPort();
  250 
  251         ipVirtBoard->outbound_proxy_IP.ip_ver = IPVER4;
  252         ipVirtBoard->outbound_proxy_IP.u_ipaddr.ipv4 = proxy_ip;
  253         ipVirtBoard->outbound_proxy_hostname = NULL;
  254         ipVirtBoard->outbound_proxy_port = proxy_port;
  255       }
  256 
  257       n++;
  258     }
  259   }
  260 
  261   IPCCLIB_START_DATA ipData;
  262   INIT_IPCCLIB_START_DATA(&ipData, config_.iptBoards.size(), ipVirtBoards);
  263   ipData.max_parm_data_size = IP_CFG_PARM_DATA_MAXLEN;
  264 
  265   /* 3PCC is required to get access to the Session Description (SDP) of
  266    * the SIP message, and then to control the media (RTP) streaming.
  267    */
  268   ipData.media_operational_mode = MEDIA_OPERATIONAL_MODE_3PCC;
  269 
  270   /*
  271    * Start GlobalCall using DM3 and IPM etc.
  272    */
  273 
  274   CCLIB_START_STRUCT dm3cc_lib = { (char*)"GC_DM3CC_LIB", NULL };
  275   CCLIB_START_STRUCT ss7_lib = { (char*)"GC_SS7_LIB",   NULL };
  276   CCLIB_START_STRUCT ipm_lib = { (char*)"GC_IPM_LIB",   NULL };
  277   CCLIB_START_STRUCT h3r_lib = { (char*)"GC_H3R_LIB",   &ipData };
  278 
  279   std::vector<CCLIB_START_STRUCT> cclibs;
  280 
  281   cclibs.push_back(dm3cc_lib);
  282 
  283   if ( config_.haveSs7() )
  284   {
  285     cclibs.push_back(ss7_lib);
  286   }
  287 
  288   cclibs.push_back(ipm_lib);
  289 
  290   if ( config_.iptBoards.size() > 0 )
  291   {
  292     cclibs.push_back(h3r_lib);
  293   }
  294 
  295   GC_START_STRUCT gcLibStart;
  296   memset(&gcLibStart, 0, sizeof(GC_START_STRUCT));
  297   gcLibStart.cclib_list = &cclibs[0];
  298   gcLibStart.num_cclibs = cclibs.size();
  299 
  300   if ( gc_Start(&gcLibStart) != GC_SUCCESS )
  301   {
  302     GC_INFO gc_info;
  303     gc_ErrorInfo(&gc_info);
  304     LOGCRIT("DialogicChannelManager::init() gc_Start failed. " << gc_info);
  305     delete[] ipVirtBoards;
  306     return false;
  307   }
  308 
  309   delete[] ipVirtBoards;
  310 
  311   if ( config_.haveH324() )
  312   {
  313     LOGINFO("DialogicChannelManager::init() starting m3g");
  314 
  315     M3G_START_STRUCT m3gstart;
  316     INIT_M3G_START_STRUCT(&m3gstart);
  317 
  318     m3gstart.numEndpoints = config_.m3gDevices.size();
  319 
  320     if ( m3g_Start(&m3gstart) == M3G_ERROR )
  321     {
  322       LOGERROR("DialogicChannelManager::init() m3g_Start() failed");
  323       return false;
  324     }
  325   }
  326   return true;
  327 }
  328 
  329 
  330 /*
  331  * Create device objects and open their devices.
  332  * Abort immediately if a device fails to open.
  333  */
  334 bool DialogicChannelManager::openDevices()
  335 {
  336   /* Do vox first as the are needed by the dti and ipt devices */
  337   if ( !openVoxDevices() )
  338   {
  339     return false;
  340   }
  341   if ( !openDtiDevices() )
  342   {
  343     return false;
  344   }
  345   if ( !openIpmDevices() )
  346   {
  347     return false;
  348   }
  349   if ( !openIptDevices() )
  350   {
  351     return false;
  352   }
  353   if ( !openMmDevices() )
  354   {
  355     return false;
  356   }
  357   if ( !openM3gDevices() )
  358   {
  359     return false;
  360   }
  361 
  362   if ( config_.confBoards.size() > 0 )
  363   {
  364     std::vector<Config::ConfBoardConfig>::const_iterator i = config_.confBoards.begin();
  365     for ( ; i != config_.confBoards.end(); ++i )
  366     {
  367       ConfBoard* confBoard  = new ConfBoard((*i).name, *this);
  368       if ( confBoard->open() )
  369       {
  370         boardMap_.insert(board_map_t::value_type((*i).name, confBoard));
  371       }
  372       else
  373       {
  374         delete confBoard;
  375         return false;;
  376       }
  377     }
  378   }
  379   return true;
  380 }
  381 
  382 
  383 /*
  384  * Create dti device objects and open their devices.
  385  * Dti boards are used for configuration only; there is no board device to open.
  386  * Abort immediately if a device fails to open.
  387  */
  388 bool DialogicChannelManager::openDtiDevices()
  389 {
  390   std::vector<Config::DtiBoardConfig>::const_iterator i = config_.dtiBoards.begin();
  391   for ( ; i != config_.dtiBoards.end(); ++i )
  392   {
  393     std::vector<Config::DtiConfig>::const_iterator j;
  394     for ( j = (*i).dti.begin(); j != (*i).dti.end(); ++j )
  395     {
  396       /* Each dti device is allocated a dedicated vox device.
  397        */
  398       if ( voxDevices_.empty() )
  399       {
  400         LOGERROR("DialogicChannelManager::openDtiDevice() Unable to create dti device, no free vox device available");
  401         return false;
  402       }
  403       VoxDevice* vox = voxDevices_.front();
  404       voxDevices_.pop();
  405 
  406       GcIsdnDevice* gcdev = new GcIsdnDevice((*j).name, (*i).protocol, (*i).ss7, *this, vox);
  407       if ( gcdev->open() )
  408       {
  409         vox->bindGcDevice(gcdev);
  410 
  411         deviceMap_.insert(device_map_t::value_type((*j).name, gcdev));
  412 
  413         /* add the device to each of its groups.
  414          */
  415         std::vector<Config::DtiConfig::group_membership_t>::const_iterator k;
  416         for ( k = (*j).groups.begin(); k != (*j).groups.end(); ++k )
  417         {
  418           (*k).first->add(gcdev, (*k).second);
  419         }
  420       }
  421       else
  422       {
  423         delete gcdev;
  424         voxDevices_.push(vox);
  425         return false;
  426       }
  427     }
  428   }
  429   return true;
  430 }
  431 
  432 
  433 /*
  434  * Create and open each IPM device, if the open fails delete the device object.
  435  */
  436 bool DialogicChannelManager::openIpmDevices()
  437 {
  438   std::vector<std::string>::const_iterator i;
  439   for ( i = config_.ipmDevices.begin(); i != config_.ipmDevices.end(); ++i )
  440   {
  441     IpmDevice* ipmdev = new IpmDevice(*i, *this);
  442     if ( ipmdev->open() )
  443     {
  444       deviceMap_.insert(device_map_t::value_type(*i, ipmdev));
  445       ipmDevices_.push(ipmdev);
  446       ipmdev->setSdpContactAddress(config_.getSdpContactAddress());
  447     }
  448     else
  449     {
  450       delete ipmdev;
  451       return false;
  452     }
  453   }
  454   return true;
  455 }
  456 
  457 
  458 /*
  459  * Create and open each vox device, if the open fails delete the device object.
  460  */
  461 bool DialogicChannelManager::openVoxDevices()
  462 {
  463   std::vector<int> vox_handles; /* for tone detector */
  464 
  465   std::vector<std::string>::const_iterator i;
  466   for ( i = config_.voxDevices.begin(); i != config_.voxDevices.end(); ++i )
  467   {
  468     VoxDevice* voxdev = new VoxDevice(*i, *this);
  469     if ( voxdev->open() )
  470     {
  471       deviceMap_.insert(device_map_t::value_type(*i, voxdev));
  472       voxDevices_.push(voxdev);
  473       vox_handles.push_back(voxdev->getDeviceHandle());
  474     }
  475     else
  476     {
  477       delete voxdev;
  478       return false;
  479     }
  480   }
  481 
  482   if ( !toneDetector_.addTonesToDevices(vox_handles) )
  483   {
  484     return false;
  485   }
  486   return true;
  487 }
  488 
  489 
  490 /*
  491  * Ipt devices are determined by the configuration only, i.e. not probed.
  492  * In addition to opening the devices their parent boards are opened for
  493  * the purpose of sending sip registration requests.
  494  * These devices are dependent on ipm devices
  495  */
  496 bool DialogicChannelManager::openIptDevices()
  497 {
  498   std::vector<Config::IptBoardConfig>::const_iterator i = config_.iptBoards.begin();
  499   for ( ; i != config_.iptBoards.end(); ++i )
  500   {
  501     GcIptBoard* iptBoard = new GcIptBoard((*i).name, *this);
  502     if ( iptBoard->open() )
  503     {
  504       Coders::audio_coders_t preferred_audio_coders;
  505       const Coders::audio_coders_t& all_audio_coders = coders_.getAudioCoders();
  506 
  507       std::vector<std::string>::const_iterator j;
  508       for ( j = (*i).audio_codecs.begin(); j != (*i).audio_codecs.end(); ++j )
  509       {
  510         Coders::audio_coders_t::const_iterator k;
  511         for ( k = all_audio_coders.begin(); k != all_audio_coders.end(); ++k )
  512         {
  513           if ( *j == (*k).encoding )
  514           {
  515             preferred_audio_coders.push_back(*k);
  516             break;
  517           }
  518         }
  519       }
  520       iptBoard->setAudioCoders(preferred_audio_coders);
  521 
  522       Coders::video_coders_t preferred_video_coders;
  523       const Coders::video_coders_t& all_video_coders = coders_.getVideoCoders();
  524 
  525       for ( j = (*i).video_codecs.begin(); j != (*i).video_codecs.end(); ++j )
  526       {
  527         Coders::video_coders_t::const_iterator k;
  528         for ( k = all_video_coders.begin(); k != all_video_coders.end(); ++k )
  529         {
  530           if ( *j == (*k).encoding )
  531           {
  532             /* If vga is not licensed, remove its levels from the
  533              * available formats and replace the default (active) format.
  534              */
  535             if ( ((*k).encoding == "h264") && !((*i).have_vga) )
  536             {
  537               VideoCoderInfo h264 = *k;
  538               std::vector<VideoCoderInfo::Fmt>::iterator l = h264.available_fmts.begin();
  539               while ( l != h264.available_fmts.end() )
  540               {
  541                 if ( (*l).imageWidth == VIDEO_IMAGE_WIDTH_VGA )
  542                 {
  543                   h264.available_fmts.erase(l++);
  544                 }
  545                 else
  546                 {
  547                   if ( (*l).level == VIDEO_LEVEL_1_3_H264 )
  548                   {
  549                     h264.active_fmt = *l;
  550                   }
  551                   l++;
  552                 }
  553               }
  554               preferred_video_coders.push_back(h264);
  555             }
  556             else
  557             {
  558               preferred_video_coders.push_back(*k);
  559             }
  560             break;
  561           }
  562         }
  563       }
  564       iptBoard->setVideoCoders(preferred_video_coders);
  565 
  566       iptBoard->setLocalAddr((*i).localAddrInfo);
  567       iptBoard->setRegistrar((*i).registrarAddrInfo);
  568       iptBoard->setTtl((*i).ttl);
  569 
  570       Config::IptBoardConfig::user_map_t::const_iterator m;
  571       for ( m = (*i).users.begin(); m != (*i).users.end(); ++m )
  572       {
  573         iptBoard->registerEntity((*m).first,
  574                                  (*m).second.identity,
  575                                  (*m).second.password,
  576                                  (*m).second.realm);
  577       }
  578 
  579       boardMap_.insert(board_map_t::value_type((*i).name, iptBoard));
  580     }
  581     else
  582     {
  583       delete iptBoard;
  584       LOGERROR("DialogicChannelManager::openIptDevice() Failed to open IPT board: " << (*i).name);
  585       return false;
  586     }
  587 
  588     for ( int n = 1; n <= (*i).maxCalls; n++ )
  589     {
  590       std::stringstream dev_name;
  591       dev_name << (*i).name << "T" << n;
  592 
  593       /* Each ipt device is allocated a dedicated vox device.
  594        */
  595       if ( voxDevices_.empty() )
  596       {
  597         LOGERROR("DialogicChannelManager::openIptDevice() Unable to create IPT device, insufficient VOX devices, you may need to regenerate your Diastar config file");
  598         return false;
  599       }
  600       /* Each ipt device is allocated a dedicated ipm device.
  601        */
  602       if ( ipmDevices_.empty() )
  603       {
  604         LOGERROR("DialogicChannelManager::openIptDevice() Unable to create IPT device, insufficient IPM devices, you may need to regenerate your Diastar config file");
  605         return false;
  606       }
  607 
  608       VoxDevice* vox = voxDevices_.front();
  609       voxDevices_.pop();
  610 
  611       IpmDevice* ipm = ipmDevices_.front();
  612       ipmDevices_.pop();
  613 
  614       GcIptDevice* iptdev = new GcIptDevice(dev_name.str(), *this, vox, *iptBoard, ipm);
  615       if ( iptdev->open() )
  616       {
  617         vox->bindGcDevice(iptdev);
  618         ipm->bindIptDevice(iptdev);
  619 
  620         deviceMap_.insert(device_map_t::value_type(dev_name.str(), iptdev));
  621         iptDevices_.push_back(iptdev);
  622       }
  623       else
  624       {
  625         delete iptdev;
  626         voxDevices_.push(vox);
  627         ipmDevices_.push(ipm);
  628         return false;
  629       }
  630       dev_name.str("");
  631     }
  632   }
  633   return true;
  634 }
  635 
  636 
  637 /*
  638  * Create and open each MM device, if the open fails delete the device object.
  639  */
  640 bool DialogicChannelManager::openMmDevices()
  641 {
  642   std::vector<std::string>::const_iterator i;
  643   for ( i = config_.mmDevices.begin(); i != config_.mmDevices.end(); ++i )
  644   {
  645     MmDevice* mmdev = new MmDevice(*i, *this);
  646     if ( mmdev->open() )
  647     {
  648       deviceMap_.insert(device_map_t::value_type(*i, mmdev));
  649       mmDevices_.push(mmdev);
  650     }
  651     else
  652     {
  653       delete mmdev;
  654       return false;
  655     }
  656   }
  657   return true;
  658 }
  659 
  660 
  661 /*
  662  * Open the M3g board and create and open each M3g device, if the open fails
  663  * delete the device object.
  664  */
  665 bool DialogicChannelManager::openM3gDevices()
  666 {
  667   if ( !config_.haveH324() )
  668   {
  669     return true;
  670   }
  671 
  672   M3gBoard* m3gBoard = new M3gBoard(config_.m3gBoard->name, *this);
  673   if ( m3gBoard->open() )
  674   {
  675     boardMap_.insert(board_map_t::value_type(config_.m3gBoard->name, m3gBoard));
  676 
  677     bool trace;
  678 
  679     std::vector<std::string>::const_iterator i;
  680     for ( i = config_.m3gDevices.begin(); i != config_.m3gDevices.end(); ++i )
  681     {
  682       /* Check if this device should have tracing enabled.
  683        */
  684       trace = false;
  685       std::vector<std::string>::const_iterator j;
  686       for ( j = config_.m3gTraceDevices.begin(); j != config_.m3gTraceDevices.end(); ++j )
  687       {
  688         if ( *j == *i )
  689         {
  690           trace = true;
  691           break;
  692         }
  693       }
  694       /* Create and open device.
  695        */
  696       M3gDevice* m3gdev = new M3gDevice(*i, *this, trace);
  697       if ( m3gdev->open() )
  698       {
  699         deviceMap_.insert(device_map_t::value_type(*i, m3gdev));
  700         m3gDevices_.push(m3gdev);
  701       }
  702       else
  703       {
  704         delete m3gdev;
  705         return false;
  706       }
  707     }
  708   }
  709   else
  710   {
  711     delete m3gBoard;
  712     LOGERROR("DialogicChannelManager::openM3gDevices() Failed to open m3g board: " << config_.m3gBoard->name);
  713     return false;
  714   }
  715   return true;
  716 }
  717 
  718 
  719 /*
  720  * Close all devices and boards.
  721  */
  722 void DialogicChannelManager::closeDevices()
  723 {
  724   device_map_t::iterator i;
  725   for ( i = deviceMap_.begin(); i != deviceMap_.end(); ++i )
  726   {
  727     LOGDEBUG("DialogicChannelManager::closeDevices() Closing device: " << (*i).first);
  728     (*i).second->close();
  729   }
  730 
  731   board_map_t::iterator j;
  732   for ( j = boardMap_.begin(); j != boardMap_.end(); ++j )
  733   {
  734     LOGDEBUG("DialogicChannelManager::closeDevices() Closing board: " << (*j).first);
  735     (*j).second->close();
  736   }
  737 }
  738 
  739 
  740 /*
  741  * Allocate an ipm device.
  742  */
  743 IpmDevice* DialogicChannelManager::allocIpmDevice()
  744 {
  745   IpmDevice* ipm = 0;
  746   if ( !ipmDevices_.empty() )
  747   {
  748     ipm = ipmDevices_.front();
  749     ipmDevices_.pop();
  750     LOGDEBUG("DialogicChannelManager::allocIpmDevice() device: " << ipm->getDeviceName());
  751   }
  752   else
  753   {
  754     LOGWARN("DialogicChannelManager::allocIpmDevice() No device available");
  755   }
  756   return ipm;
  757 }
  758 
  759 
  760 /*
  761  * Release an ipm device.
  762  */
  763 void DialogicChannelManager::freeIpmDevice( IpmDevice* ipm )
  764 {
  765   if ( ipm )
  766   {
  767     ipm->disconnect();
  768     ipmDevices_.push(ipm);
  769     LOGDEBUG("DialogicChannelManager::freeIpmDevice() device: " << ipm->getDeviceName());
  770   }
  771 }
  772 
  773 
  774 /*
  775  * Allocate a Multi-Media device.
  776  */
  777 MmDevice* DialogicChannelManager::allocMmDevice()
  778 {
  779   MmDevice* mm = 0;
  780   if ( !mmDevices_.empty() )
  781   {
  782     mm = mmDevices_.front();
  783     mmDevices_.pop();
  784     LOGDEBUG("DialogicChannelManager::allocMmDevice() device: " << mm->getDeviceName());
  785   }
  786   else
  787   {
  788     LOGWARN("DialogicChannelManager::allocMmDevice() No device available");
  789   }
  790   return mm;
  791 }
  792 
  793 
  794 /*
  795  * Release a Multi-Media device.
  796  */
  797 void DialogicChannelManager::freeMmDevice( MmDevice* mm )
  798 {
  799   if ( mm )
  800   {
  801     if ( mm->isPlaying() )
  802     {
  803       mm->stopPlay(PLAY_STOPPED);
  804     }
  805     if ( mm->isRecording() )
  806     {
  807       mm->stopPlay(RECORD_STOPPED);
  808     }
  809     mm->disconnect();
  810     mmDevices_.push(mm);
  811     LOGDEBUG("DialogicChannelManager::freeMmDevice() device: " << mm->getDeviceName());
  812   }
  813 }
  814 
  815 
  816 /*
  817  * Lookup the device or board and pass it the event.
  818  */
  819 int DialogicChannelManager::dispatchEvent( METAEVENT& metaevent )
  820 {
  821   char* atdv_name = ATDV_NAMEP(metaevent.evtdev);
  822   if ( atdv_name )
  823   {
  824     /* use the device's base name to route the event */
  825     std::string dev_name(atdv_name);
  826     std::string::size_type pos = dev_name.find(':');
  827     std::string base_name = dev_name.substr(0, pos);
  828 
  829     device_map_t::const_iterator i = deviceMap_.find(base_name);
  830     if ( i != deviceMap_.end() )
  831     {
  832       DialogicDevice* device = (*i).second;
  833       if ( device )
  834       {
  835         return device->processEvent(metaevent);
  836       }
  837     }
  838 
  839     board_map_t::const_iterator j = boardMap_.find(base_name);
  840     if ( j != boardMap_.end() )
  841     {
  842       DialogicBoard* board = (*j).second;
  843       if ( board )
  844       {
  845         return board->processEvent(metaevent);
  846       }
  847     }
  848     LOGERROR("DialogicChannelManager::dispatchEvent() Unknown device: \"" <<
  849              atdv_name << "\"" << " event: 0x" << std::hex << metaevent.evttype);
  850   }
  851   return 0;
  852 }
  853 
  854 
  855 /*
  856  * Use the encodings set by configuration to set the coders for the ipm device
  857  * that handles the client (Woomera) media streams.
  858  */
  859 void DialogicChannelManager::setClientCoders( IpmDevice* ipm )
  860 {
  861   const Coders::audio_coders_t&  audioCoders = getAudioCoders();
  862   Coders::audio_coders_t::const_iterator i;
  863   for ( i = audioCoders.begin(); i != audioCoders.end(); ++i )
  864   {
  865     if ( (*i).encoding == config_.getClientAudioFormat() )
  866     {
  867       ipm->setLocalAudioCoder(*i);
  868       ipm->setRemoteAudioCoder(*i);
  869       break;
  870     }
  871   }
  872 
  873   const Coders::video_coders_t&  videoCoders = getVideoCoders();
  874   Coders::video_coders_t::const_iterator j;
  875   for ( j = videoCoders.begin(); j != videoCoders.end(); ++j )
  876   {
  877     if ( (*j).encoding == config_.getClientVideoFormat() )
  878     {
  879       if ( (*j).encoding == "h264" )
  880       {
  881         VideoCoderInfo clientVideoCoder = *j;
  882 
  883         eVIDEO_LEVEL level = VIDEO_LEVEL_1_3_H264;
  884 
  885         if ( config_.getClientH264Level() == "1.0" )
  886         {
  887           clientVideoCoder.active_fmt.level = VIDEO_LEVEL_1_H264;
  888         }
  889         else if ( config_.getClientH264Level() == "1.B" )
  890         {
  891           level = VIDEO_LEVEL_1_B_H264;
  892         }
  893         else if ( config_.getClientH264Level() == "1.1" )
  894         {
  895           level = VIDEO_LEVEL_1_1_H264;
  896         }
  897         else if ( config_.getClientH264Level() == "1.2" )
  898         {
  899           level = VIDEO_LEVEL_1_2_H264;
  900         }
  901         else if ( config_.getClientH264Level() == "1.3" )
  902         {
  903           level = VIDEO_LEVEL_1_3_H264;
  904         }
  905         else if ( config_.getClientH264Level() == "2.0" )
  906         {
  907           level = VIDEO_LEVEL_2_0_H264;
  908         }
  909         else if ( config_.getClientH264Level() == "2.1" )
  910         {
  911           level = VIDEO_LEVEL_2_1_H264;
  912         }
  913         else if ( config_.getClientH264Level() == "2.2" )
  914         {
  915           level = VIDEO_LEVEL_2_2_H264;
  916         }
  917         else if ( config_.getClientH264Level() == "3.0" )
  918         {
  919           level = VIDEO_LEVEL_3_0_H264;
  920         }
  921         else if ( config_.getClientH264Level() == "3.1" )
  922         {
  923           level = VIDEO_LEVEL_3_1_H264;
  924         }
  925 
  926         std::vector<VideoCoderInfo::Fmt>::const_iterator k = clientVideoCoder.available_fmts.begin();
  927         for ( ; k != clientVideoCoder.available_fmts.end(); ++k )
  928         {
  929           if ( (*k).level == level )
  930           {
  931             clientVideoCoder.active_fmt.profile = (*k).profile;
  932             clientVideoCoder.active_fmt.level = (*k).level;
  933             clientVideoCoder.active_fmt.imageWidth = (*k).imageWidth;
  934             clientVideoCoder.active_fmt.imageHeight = (*k).imageHeight;
  935             clientVideoCoder.active_fmt.framesPerSec = (*k).framesPerSec;
  936             clientVideoCoder.active_fmt.bitRate = (*k).bitRate;
  937             break;
  938           }
  939         }
  940         ipm->setLocalVideoCoder(clientVideoCoder);
  941         ipm->setRemoteVideoCoder(clientVideoCoder);
  942       }
  943       else
  944       {
  945         ipm->setLocalVideoCoder(*j);
  946         ipm->setRemoteVideoCoder(*j);
  947       }
  948       break;
  949     }
  950   }
  951 }
  952 
  953 
  954 /*
  955  * Create the channel using a dti device allocated from a specific group.
  956  */
  957 DialogicChannel* DialogicChannelManager::createIsdnChannel( const std::string& group,
  958                                                             Protocol protocol )
  959 {
  960   LOGDEBUG("DialogicChannelManager::createIsdnChannel() using group: " << group);
  961 
  962   GroupManager<GcIsdnDevice>::Group* grp = config_.gcGroups.find(group);
  963   if ( !grp )
  964   {
  965     LOGERROR("Unknown group: \"" << group << "\"");
  966     return 0;
  967   }
  968 
  969   if ( grp->empty() )
  970   {
  971     LOGWARN("Unable to create channel, no free GC device available");
  972     return 0;
  973   }
  974 
  975   GcIsdnDevice* gc = grp->get();
  976   DialogicChannel* channel = 0;
  977   if ( gc->getProtocol() != protocol )
  978   {
  979     LOGERROR("Dti device: " << gc->getDeviceName() << " protocol mismatch - check configuration");
  980   }
  981   else
  982   {
  983     channel = createIsdnChannel(gc);
  984   }
  985 
  986   if ( !channel ) /* failed, put back in group */
  987   {
  988     std::vector<Config::DtiBoardConfig>::const_iterator i = config_.dtiBoards.begin();
  989     for ( ; i != config_.dtiBoards.end(); ++i )
  990     {
  991       std::vector<Config::DtiConfig>::const_iterator j;
  992       for ( j = (*i).dti.begin(); j != (*i).dti.end(); ++j )
  993       {
  994         if ( (*j).name == gc->getDeviceName() )
  995         {
  996           std::vector<Config::DtiConfig::group_membership_t>::const_iterator k;
  997           for ( k = (*j).groups.begin(); k != (*j).groups.end(); ++k )
  998           {
  999             if ( (*k).first == grp )
 1000             {
 1001               grp->add(gc, (*k).second);
 1002               break;
 1003             }
 1004           }
 1005           return 0;
 1006         }
 1007       }
 1008     }
 1009   }
 1010 
 1011   return channel;
 1012 }
 1013 
 1014 
 1015 /*
 1016  * Create a channel using a specific dti device.
 1017  */
 1018 DialogicChannel* DialogicChannelManager::createIsdnChannel( GcIsdnDevice* gc )
 1019 {
 1020   LOGDEBUG("DialogicChannelManager::createIsdnChannel() using device: " << gc->getDeviceName());
 1021 
 1022   if ( ipmDevices_.empty() )
 1023   {
 1024     LOGERROR("Unable to create channel, no free IPM device available");
 1025     return 0;
 1026   }
 1027 
 1028   M3gDevice* m3g = 0;
 1029   if ( gc->getProtocol() == PROTOCOL_H324 )
 1030   {
 1031     if ( m3gDevices_.empty() )
 1032     {
 1033       LOGERROR("Unable to create channel, no free M3g device available");
 1034       return 0;
 1035     }
 1036     m3g = m3gDevices_.front();
 1037     m3gDevices_.pop();
 1038   }
 1039 
 1040   /* Client rtp. */
 1041   IpmDevice* ipm = ipmDevices_.front();
 1042   ipmDevices_.pop();
 1043   setClientCoders(ipm);
 1044 
 1045   /* remove gc from all groups */
 1046   std::vector<Config::DtiBoardConfig>::const_iterator i = config_.dtiBoards.begin();
 1047   for ( ; i != config_.dtiBoards.end(); ++i )
 1048   {
 1049     std::vector<Config::DtiConfig>::const_iterator j;
 1050     for ( j = (*i).dti.begin(); j != (*i).dti.end(); ++j )
 1051     {
 1052       if ( (*j).name == gc->getDeviceName() )
 1053       {
 1054         std::vector<Config::DtiConfig::group_membership_t>::const_iterator k;
 1055         for ( k = (*j).groups.begin(); k != (*j).groups.end(); ++k )
 1056         {
 1057           (*k).first->remove(gc);
 1058         }
 1059       }
 1060       break;
 1061     }
 1062     if ( j != (*i).dti.end() )
 1063     {
 1064       break;
 1065     }
 1066   }
 1067 
 1068   DialogicChannel* channel = 0;
 1069 
 1070   if ( (gc->getProtocol() == PROTOCOL_ISDN) || (gc->getProtocol() == PROTOCOL_SS7) )
 1071   {
 1072     gc->attachVox();
 1073 
 1074     /* tone monitoring */
 1075     VoxDevice* vox = gc->getVox();
 1076     vox->clearToneDetector();
 1077     vox->listen(gc);
 1078     vox->disableToneNotifications();
 1079     if ( config_.isOutOfBandDtmf() )
 1080     {
 1081       vox->startDtmfMonitoring();
 1082     }
 1083 
 1084     channel = new DialogicChannel(*this, gc, ipm);
 1085     channels_.push_back(channel);
 1086 
 1087     LOGINFO("DialogicChannelManager::createIsdnChannel() " <<
 1088             std::hex << channel <<
 1089             ", dti: " << gc->getDeviceName() <<
 1090             ", ipm: " << ipm->getDeviceName() <<
 1091             ", vox: " << vox->getDeviceName());
 1092   }
 1093   else /* PROTOCOL_H324 */
 1094   {
 1095     channel = new DialogicChannel(*this, mediaStateMachine_, gc, m3g, ipm);
 1096     channels_.push_back(channel);
 1097 
 1098     m3g->startSession();
 1099 
 1100     if ( dev_Connect(m3g->getDeviceHandle(),
 1101                      gc->getNetworkHandle(),
 1102                      DM_FULLDUP,
 1103                      EV_SYNC) != DEV_SUCCESS )
 1104     {
 1105       DEV_ERRINFO error_info;
 1106       if ( dev_ErrorInfo(&error_info) != -1 )
 1107       {
 1108         LOGERROR("DialogicChannelManager::createIsdnChannel() dev_Connect(0x" <<
 1109                  std::hex << m3g->getDeviceHandle() <<
 1110                  ", 0x" << gc->getNetworkHandle() <<
 1111                  ") failed: " << std::dec << error_info);
 1112       }
 1113       else
 1114       {
 1115         LOGERROR("DialogicChannelManager::createIsdnChannel() dev_Connect() failed, unable to retrieve error info");
 1116       }
 1117     }
 1118 
 1119     LOGINFO("DialogicChannelManager::createIsdnChannel() " <<
 1120             std::hex << channel <<
 1121             ", dti: " << gc->getDeviceName() <<
 1122             ", ipm: " << ipm->getDeviceName() <<
 1123             ", m3g: " << m3g->getDeviceName());
 1124   }
 1125 
 1126   total_++;
 1127   LOGINFO("Active channels: " << channels_.size() << ", total: " << total_);
 1128 
 1129   return channel;
 1130 }
 1131 
 1132 
 1133 /*
 1134  * Create the channel using a free ipt device.
 1135  * Note, group is reserved for future use.
 1136  */
 1137 DialogicChannel* DialogicChannelManager::createSipChannel( const std::string& group )
 1138 {
 1139   LOGDEBUG("DialogicChannelManager::createSipChannel() using group: " << group);
 1140 
 1141   if ( iptDevices_.empty() )
 1142   {
 1143     LOGERROR("Unable to create channel, no free IPT device available");
 1144     return 0;
 1145   }
 1146 
 1147   GcIptDevice* gc = iptDevices_.front();
 1148   iptDevices_.pop_front();
 1149 
 1150   DialogicChannel* channel = createSipChannel(gc);
 1151 
 1152   if ( !channel ) /* failed, put back */
 1153   {
 1154     iptDevices_.push_front(gc);
 1155   }
 1156 
 1157   return channel;
 1158 }
 1159 
 1160 
 1161 /*
 1162  * Create a channel using a specific ipt device.
 1163  */
 1164 DialogicChannel* DialogicChannelManager::createSipChannel( GcIptDevice* gc )
 1165 {
 1166   LOGDEBUG("DialogicChannelManager::createSipChannel() using device: " << gc->getDeviceName() <<
 1167            " (" << gc->getIpmDevice()->getDeviceName() << ")");
 1168 
 1169   if ( ipmDevices_.empty() )
 1170   {
 1171     LOGERROR("Unable to create channel, no free IPM device available");
 1172     return 0;
 1173   }
 1174 
 1175   /* Client rtp. */
 1176   IpmDevice* ipm = ipmDevices_.front();
 1177   ipmDevices_.pop();
 1178   setClientCoders(ipm);
 1179 
 1180   iptDevices_.remove(gc);
 1181 
 1182   /* tone monitoring */
 1183   VoxDevice* vox = gc->getVox();
 1184   vox->clearToneDetector();
 1185   vox->listen(gc->getIpmDevice());
 1186   vox->disableToneNotifications();
 1187 
 1188 #if 0
 1189   /* XXX dtmf mode needs config option, e.g. rfc2833, info or inband
 1190    * can get double digits if this is enabled unconditionally
 1191    */
 1192   if ( isOutOfBandDtmf() )
 1193   {
 1194     vox->startDtmfMonitoring();
 1195   }
 1196 #endif
 1197 
 1198   DialogicChannel* channel = new DialogicChannel(*this,
 1199                                                  mediaStateMachine_,
 1200                                                  gc,
 1201                                                  ipm);
 1202   channels_.push_back(channel);
 1203 
 1204   LOGINFO("DialogicChannelManager::createSipChannel() " <<
 1205           std::hex << channel <<
 1206           ", ipt: " << gc->getDeviceName() <<
 1207           ", ipm: " << ipm->getDeviceName() <<
 1208           ", vox: " << vox->getDeviceName());
 1209 
 1210   total_++;
 1211   LOGINFO("Active channels: " << channels_.size() << ", total: " << total_);
 1212   return channel;
 1213 }
 1214 
 1215 
 1216 /*
 1217  * Create a conference channel.
 1218  */
 1219 DialogicChannel* DialogicChannelManager::createConfChannel( const std::string& conf_id )
 1220 {
 1221   LOGDEBUG("DialogicChannelManager::createConfChannel() using conf: " << conf_id);
 1222 
 1223   if ( ipmDevices_.empty() )
 1224   {
 1225     LOGERROR("Unable to create channel, no free IPM device available");
 1226     return 0;
 1227   }
 1228 
 1229   conf_map_t::const_iterator i = confs_.find(conf_id);
 1230   if ( i == confs_.end() )
 1231   {
 1232     LOGERROR("Unable to create channel, can't find conf: " << conf_id);
 1233     return 0;
 1234   }
 1235 
 1236   ConfBoard& confBoard = (*i).second->getConfBoard();
 1237 
 1238   ConfPartyDevice* confParty = confBoard.allocPartyDevice();
 1239   if ( !confParty )
 1240   {
 1241     LOGERROR("Unable to create channel, no free party device available");
 1242     return 0;
 1243   }
 1244 
 1245   /* Client rtp. */
 1246   IpmDevice* ipm = ipmDevices_.front();
 1247   ipmDevices_.pop();
 1248   setClientCoders(ipm);
 1249 
 1250   DialogicChannel* channel = new DialogicChannel(*this,
 1251                                                  mediaStateMachine_,
 1252                                                  (*i).second,
 1253                                                  confParty,
 1254                                                  ipm);
 1255   channels_.push_back(channel);
 1256 
 1257   LOGINFO("DialogicChannelManager::createConfChannel() " <<
 1258           std::hex << channel <<
 1259           ", conf: " << conf_id <<
 1260           ", ipm: " << ipm->getDeviceName());
 1261 
 1262   total_++;
 1263   LOGINFO("Active channels: " << channels_.size() << ", total: " << total_);
 1264   return channel;
 1265 }
 1266 
 1267 
 1268 /*
 1269  * Release the channel's devices and delete the channel object.
 1270  */
 1271 void DialogicChannelManager::destroyChannel( DialogicChannel* channel )
 1272 {
 1273   LOGINFO("DialogicChannelManager::destroyChannel() " << std::hex << channel);
 1274 
 1275   if ( !channel )
 1276   {
 1277     return;
 1278   }
 1279 
 1280   if ( (channel->getProtocol() == PROTOCOL_ISDN) ||
 1281        (channel->getProtocol() == PROTOCOL_SS7) ||
 1282        (channel->getProtocol() == PROTOCOL_H324) )
 1283   {
 1284     GcIsdnDevice* gc = static_cast<GcIsdnDevice*>(channel->getGcDevice());
 1285     if ( gc )
 1286     {
 1287       if ( (gc->getProtocol() == PROTOCOL_ISDN) || (gc->getProtocol() == PROTOCOL_ISDN) )
 1288       {
 1289         gc->unListen();
 1290         gc->detachVox();
 1291       }
 1292       else /* PROTOCOL_H324 */
 1293       {
 1294         M3gDevice* m3g = channel->getM3gDevice();
 1295 
 1296         dev_Disconnect(m3g->getDeviceHandle(), EV_SYNC);
 1297             dev_Disconnect(gc->getNetworkHandle(), EV_SYNC);
 1298 
 1299         m3gDevices_.push(m3g);
 1300       }
 1301       /* return the gc device to its groups
 1302        */
 1303       std::vector<Config::DtiBoardConfig>::const_iterator i = config_.dtiBoards.begin();
 1304       for ( ; i != config_.dtiBoards.end(); ++i )
 1305       {
 1306         std::vector<Config::DtiConfig>::const_iterator j;
 1307         for ( j = (*i).dti.begin(); j != (*i).dti.end(); ++j )
 1308         {
 1309           if ( (*j).name == gc->getDeviceName() )
 1310           {
 1311             std::vector<Config::DtiConfig::group_membership_t>::const_iterator k;
 1312             for ( k = (*j).groups.begin(); k != (*j).groups.end(); ++k )
 1313             {
 1314               /* group->add(device, position) */
 1315               (*k).first->add(gc, (*k).second);
 1316             }
 1317             break;
 1318           }
 1319         }
 1320         if ( j != (*i).dti.end() )
 1321         {
 1322           break;
 1323         }
 1324       }
 1325     }
 1326   }
 1327   else if ( channel->getProtocol() == PROTOCOL_SIP )
 1328   {
 1329     GcIptDevice* gc = static_cast<GcIptDevice*>(channel->getGcDevice());
 1330     if ( gc )
 1331     {
 1332       IpmDevice* ipt_ipm = gc->getIpmDevice();
 1333       ipt_ipm->disconnect();
 1334       ipt_ipm->stopMedia();
 1335       ipt_ipm->removeOverlay();
 1336       iptDevices_.push_back(gc);
 1337     }
 1338   }
 1339   else /* PROTOCOL_CONF */
 1340   {
 1341     ConfPartyDevice* confParty = channel->getConfPartyDevice();
 1342     ConfDevice* confDevice = channel->getConfDevice();
 1343     if ( confDevice && confParty )
 1344     {
 1345       confParty->disconnect();
 1346       confDevice->removeParty(confParty);
 1347     }
 1348   }
 1349 
 1350   IpmDevice* ipm = channel->getIpmDevice();
 1351   if ( ipm )
 1352   {
 1353     if ( (channel->getProtocol() == PROTOCOL_SIP) ||
 1354          (channel->getProtocol() == PROTOCOL_CONF) ||
 1355          (channel->getProtocol() == PROTOCOL_H324) )
 1356     {
 1357       ipm->disconnect();
 1358       ipm->stopMedia();
 1359       ipm->removeOverlay();
 1360     }
 1361     else /* ISDN, SS7 */
 1362     {
 1363       ipm->unListen();
 1364     }
 1365     ipmDevices_.push(ipm);
 1366   }
 1367 
 1368   for ( channel_t::iterator i = channels_.begin(); i != channels_.end(); ++i )
 1369   {
 1370     if ( *i == channel )
 1371     {
 1372       channels_.erase(i);
 1373       break;
 1374     }
 1375   }
 1376   delete channel;
 1377 
 1378   LOGINFO("Active channels: " << channels_.size() << ", total: " << total_);
 1379 }
 1380 
 1381 
 1382 /*
 1383  * Does a linear search of the channels_ array.
 1384  */
 1385 DialogicChannel* DialogicChannelManager::findChannel( const ConfPartyDevice* party ) const
 1386 {
 1387   channel_t::const_iterator i;
 1388   for ( i = channels_.begin(); i != channels_.end(); ++i )
 1389   {
 1390     DialogicChannel* channel = *i;
 1391     if ( channel && (channel->getConfPartyDevice() == party) )
 1392     {
 1393       return channel;
 1394     }
 1395   }
 1396   return 0;
 1397 }
 1398 
 1399 
 1400 /*
 1401  * Does a linear search of the channels_ array.
 1402  */
 1403 DialogicChannel* DialogicChannelManager::findChannel( const RtpIpInfo& rtp_audio,
 1404                                                       const RtpIpInfo& rtp_video ) const
 1405 {
 1406   channel_t::const_iterator i;
 1407   for ( i = channels_.begin(); i != channels_.end(); ++i )
 1408   {
 1409     DialogicChannel* channel = *i;
 1410 
 1411     RtpIpInfo local_rtp_audio;
 1412     channel->getLocalRtpAudioInfo(local_rtp_audio);
 1413 
 1414     RtpIpInfo local_rtp_video;
 1415     channel->getLocalRtpVideoInfo(local_rtp_video);
 1416 
 1417     if ( (local_rtp_audio == rtp_audio) && (local_rtp_video == rtp_video) )
 1418     {
 1419       return channel;
 1420     }
 1421   }
 1422   return 0;
 1423 }
 1424 
 1425 
 1426 /* vim:ts=4:set nu:
 1427  * EOF
 1428  */

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