Parent Directory
|
Revision Log
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 |