📄 uabuilder.cxx
字号:
/* ==================================================================== * The Vovida Software License, Version 1.0 * * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The names "VOCAL", "Vovida Open Communication Application Library", * and "Vovida Open Communication Application Library (VOCAL)" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact vocal@vovida.org. * * 4. Products derived from this software may not be called "VOCAL", nor * may "VOCAL" appear in their name, without prior written * permission of Vovida Networks, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * ==================================================================== * * This software consists of voluntary contributions made by Vovida * Networks, Inc. and many individuals on behalf of Vovida Networks, * Inc. For more information on Vovida Networks, Inc., please see * <http://www.vovida.org/>. * */static const char* const UaBuilder_cxx_Version = "$Id: UaBuilder.cxx,v 1.37 2002/03/19 21:40:17 jason Exp $";#include "global.h"#include <SipEvent.hxx>#include <StatusMsg.hxx>#include "UaBuilder.hxx"#include "UaCallContainer.hxx"#include "UaStateMachine.hxx"#include "UaDeviceEvent.hxx"#include "UaDevice.hxx"#include "UaDigitTimerEvent.hxx"#include "UaTimerEvent.hxx"#include "UaConfiguration.hxx"using namespace Vocal;///UaBuilder::UaBuilder(){ Sptr < UaStateMachine > uaStateMachine = new UaStateMachine; addFeature( uaStateMachine );} // UaBuilder::UaBuilder///UaBuilder::~UaBuilder(){} // UaBuilder::~UaBuilder///voidUaBuilder::process( const Sptr < SipProxyEvent > nextEvent ){ assert ( nextEvent != 0 ); assert ( myCallContainer != 0 ); calls.dynamicCast( myCallContainer ); assert( calls != 0 ); stateMachine.dynamicCast( *( myFeatures.begin() ) ); assert( stateMachine != 0 ); /// Handle the 4 types of events: /// SipEvent Sptr < SipEvent > sipEvent; sipEvent.dynamicCast( nextEvent ); if ( sipEvent != 0 ) { /** Returning 'true' from a 'process' or 'handle' method causes * UaBuilder to exit without running sendEvent() */ if( processSipEvent( sipEvent ) ) { cpLog( LOG_DEBUG, "Returning from processSipEvent\n" ); return; } sendEvent( nextEvent ); return; } /// UaDeviceEvent Sptr < UaDeviceEvent > uaDeviceEvent; uaDeviceEvent.dynamicCast( nextEvent ); if ( uaDeviceEvent != 0 ) { if( processUaDeviceEvent( uaDeviceEvent ) ) { cpLog( LOG_DEBUG, "Returning from processUaDeviceEvent\n" ); return; } sendEvent( nextEvent ); return; } /// UaDigitEvent Sptr < UaDigitTimerEvent > uaDigitEvent; uaDigitEvent.dynamicCast( nextEvent ); if ( uaDigitEvent != 0 ) { if( processUaDigitEvent( uaDigitEvent ) ) { cpLog( LOG_DEBUG, "Returning from processUaDigitEvent\n" ); return; } sendEvent( nextEvent ); return; } /// UaTimerEvent Sptr < UaTimerEvent > uaTimerEvent; uaTimerEvent.dynamicCast( nextEvent ); if ( uaTimerEvent != 0 ) { if( processUaTimerEvent( uaTimerEvent ) ) { cpLog( LOG_DEBUG, "Returning from processSipEvent\n" ); return; } sendEvent( nextEvent ); return; } /// Event of unknown type // we shouldn't get to here. cpLog( LOG_ERR, "Unknown Event" ); assert( 0 );}/** * A parent 'process' method */boolUaBuilder::processSipEvent( const Sptr < SipEvent > sipEvent ){ cpLog( LOG_DEBUG, "SIP message event" ); cpLog( LOG_DEBUG, "In processSipEvent()" ); Sptr < StatusMsg > statusMsg; statusMsg.dynamicCast( sipEvent->getSipMsg() ); /// If we have a status msg, we handle it if ( statusMsg != 0 ) { if( handleStatusMsg( sipEvent ) ) { return true; } } /// If we get here, we have a SIP message event cpLog( LOG_DEBUG, "SIP message event" ); /// Let's check the call info, now callId = sipEvent->getSipCallLeg()->getCallId(); callInfo = calls->findCall( callId ); if ( callInfo == 0 ) { cpLog( LOG_DEBUG, "No CallInfo found" ); Sptr < InviteMsg > inviteMsg; inviteMsg.dynamicCast( sipEvent->getSipMsg() ); if ( inviteMsg == 0 ) { cpLog (LOG_DEBUG, "Not an INVITE - Discard event" ); return true; } else { cpLog( LOG_DEBUG, "New INVITE" ); callInfo = calls->newCall ( sipEvent->getSipCallLeg()->getCallId() ); assert( callInfo != 0 ); callInfo->setFeature( stateMachine ); if ( UaConfiguration::instance()->getLoadGenOn() ) { /// Assume this is a new call... /// Also assume that we are not in use. callInfo->setState ( stateMachine->findState( "StateAutoIdle" ) ); } else // LoadGen is off { /// We're not in loadgen mode /// Handle call waiting conditions if( handleCallWaiting( callInfo ) ) { cpLog( LOG_ERR, "Returned from handleCallWaiting\n" ); return true; } } } // lots of brackets! } return false;} /// UaBuilder::processSipEvent/** * A parent 'process' method */boolUaBuilder::processUaDeviceEvent( const Sptr < UaDeviceEvent > uaDeviceEvent ){ cpLog( LOG_DEBUG, "Device Event" ); /// The following situtation can occur: /// 1. user goes onhook /// 2. user goes offhook immediately /// 3. state machine processes the onhook and removes callid /// 4. state machine processes the offhook with original callid /// 5. the original callid no longer exists /// In this case, we will just change the callId in deviceEvent /// to the one in the device /// Short term fix only. bool exit = false; /// Tells us whether or not to exit UaBuilder if ( !(uaDeviceEvent->callId == UaDevice::instance()->getCallId()) ) { uaDeviceEvent->callId = UaDevice::instance()->getCallId(); } if ( uaDeviceEvent->callId == 0 ) { if ( ( uaDeviceEvent->type == DeviceEventHookUp ) ) { cpLog( LOG_DEBUG, "User Offhook" ); Sptr < SipCallId > newCallId = new SipCallId; if ( UaConfiguration::instance()->getCallIdOn() ) { // Use callId from config file Data newId( UaConfiguration::instance()->getCallId() ); newCallId->setLocalId( newId ); } callInfo = calls->newCall( *newCallId ); assert( callInfo != 0 ); callInfo->setFeature( stateMachine ); callInfo->setState( stateMachine->findState( "StateIdle" ) ); UaDevice::instance()->setCallId( newCallId ); uaDeviceEvent->setSipStack( sipStack ); } else // We have no callId & the event is NOT an offhook { cpLog( LOG_ERR, "Missing Call Id for hardware event" ); exit = true; return exit; } } // We must have a valid callId to enter this else statement else { callInfo = calls->findCall( *(uaDeviceEvent->callId) ); uaDeviceEvent->setSipStack( sipStack ); assert( callInfo != 0 ); } return exit;}/** * A parent 'process' method */boolUaBuilder::processUaDigitEvent( const Sptr < UaDigitTimerEvent > uaDigitEvent ){ cpLog( LOG_DEBUG, "ua Digit Event" ); if ( uaDigitEvent->callId == 0 ) { if ( UaConfiguration::instance()->getLoadGenOn() ) { if (uaDigitEvent->getLoadGenSigType() == LoadGenStartCall) { cpLog(LOG_DEBUG, ">>> New Call! <<<" ); Sptr < SipCallId > newCallId = new SipCallId; uaDigitEvent->callId = newCallId; callInfo = calls->newCall( *newCallId ); assert( callInfo != 0 ); callInfo->setFeature( stateMachine ); if (UaConfiguration::instance()->getRunMode() == "Calling" ) { callInfo->setState ( stateMachine->findState( "StateAutoIdle" ) ); } else if( UaConfiguration::instance()->getRunMode() == "RSTest") { callInfo->setState ( stateMachine->findState( "StateAutoRS" ) ); } uaDigitEvent->setSipStack( sipStack ); } } else // Loadgen is off { cpLog( LOG_DEBUG, "Discarded" ); return true; } } else // uaDigitEvent->callId != 0 { callInfo = calls->findCall( *(uaDigitEvent->callId) ); if ( callInfo == 0 ) { cpLog( LOG_DEBUG, "Discard late timer event" ); return true; } uaDigitEvent->setSipStack( sipStack ); } return false;}/** * A parent 'process' method */boolUaBuilder::processUaTimerEvent( const Sptr < UaTimerEvent > uaTimerEvent ){ Sptr < SipCallId > callId = uaTimerEvent->getCallId(); assert( callId != 0 ); callInfo = calls->findCall( *callId ); assert( callInfo != 0 ); uaTimerEvent->setSipStack( sipStack ); return false;}/** * A child 'handle' method */boolUaBuilder::handleStatusMsg( const Sptr < SipEvent > sipEvent ){ cpLog( LOG_DEBUG, "In handleStatusMsg()" ); /// Pull the StatusMsg out of the SipEvent Sptr < StatusMsg > statusMsg; statusMsg.dynamicCast( sipEvent->getSipMsg() ); /// Sanity check; this checked out ok in main process method assert( statusMsg != 0 ); /// Register if ( UaConfiguration::instance()->getRegisterOn() && statusMsg->getCSeq().getMethod() == "REGISTER" ) { if ( statusMsg->getStatusLine().getStatusCode() < 200 ) { /// just return, prevents re-registration loop cpLog( LOG_DEBUG, "REGISTER response: code %d", statusMsg->getStatusLine().getStatusCode() ); return true; } if ( registrationManager->handleRegistrationResponse( *statusMsg ) ) { cout << VTime::strftime("%y/%m/%d %H:%M:%S") << " Registration OK" << endl; cout << "Ready" << endl; } else { cpLog( LOG_WARNING, "Registration status code %d", statusMsg->getStatusLine().getStatusCode() ); } return true; } /// Subscribe if ( UaConfiguration::instance()->getSubscribeOn() && statusMsg->getCSeq().getMethod() == "SUBSCRIBE" ) { if ( subManager == 0 ) { cpLog( LOG_ERR, "SubscribeManager is not running" ); } else { if ( subManager->handleSubscribeResponse( *statusMsg ) ) cout << "Subscribe Ok" << endl; else cpLog( LOG_ERR, "Subscribe failed" ); } return true; } /// Notify if ( UaConfiguration::instance()->getSubscribeOn() ) { Sptr < NotifyMsg > notifyMsg; notifyMsg.dynamicCast( sipEvent->getSipMsg() ); if ( notifyMsg != 0 ) { subManager->handleNotify( *notifyMsg ); } } return false; // a return to the calling method} /// end handleStatusMsg()/** * A child 'handle' method */boolUaBuilder::handleCallWaiting( Sptr< CallInfo > callInfo ){ if ( UaConfiguration::instance()->getCallWaitingOn() ) { cpLog( LOG_DEBUG, "Call Waiting ON" ); /// if call waiting enabled, the new call will ring /// the set even when there is an active call HardwareStatusType hdwStatus = UaDevice::instance()->getHardwareStatus();#if 0 if ( hdwStatus == HARDWARE_UNAVAILABLE ) { cpLog( LOG_DEBUG, "Hardware Unavailabe" ); /// Device is in use callInfo->setState( stateMachine->findState( "StateBusyHere" ) ); } else {#endif string nextState = "StateIdle"; if ( hdwStatus == HARDWARE_AVAILABLE ) { cpLog( LOG_DEBUG, "Hardware Available" ); } else { cpLog( LOG_DEBUG, "Hardware available for call waiting only" ); } Sptr < SipCallId > activeId = UaDevice::instance()->getCallId(); /// allow call waiting only if the current call /// is talking to one party if ( activeId != 0 ) { Sptr < UaCallInfo > activeCall = calls->findCall( callId ); if ( activeCall != 0 ) { if ( activeCall->getContactList()->size() > 1 ) nextState = "StateBusyHere"; } } // New Call callInfo->setState( stateMachine->findState( nextState ) );// bug:// callInfo->setState( stateMachine->findState( "StateIdle" ) );#if 0 }#endif } /// Call Waiting is NOT turned on: else { cpLog( LOG_DEBUG, "Call Waiting Off" ); /// if call waiting is disabled, the new call will not ring /// the set when there is an active call if ( UaDevice::instance()->getHardwareStatus() == HARDWARE_AVAILABLE ) { cpLog( LOG_DEBUG, "Hardware Available" ); // New Call callInfo->setState( stateMachine->findState( "StateIdle" ) ); } else { cpLog( LOG_DEBUG, "Hardware Unavailable" ); // Device is in use callInfo->setState( stateMachine->findState( "StateBusyHere" ) ); } } return false;}/** */voidUaBuilder::sendEvent( const Sptr < SipProxyEvent > nextEvent ){ nextEvent->setCallInfo ( callInfo, calls ); stateMachine->process( nextEvent ); return;}///voidUaBuilder::setSipStack( const Sptr < SipTransceiver > sipstack ){ sipStack = sipstack;}///voidUaBuilder::setSubscribeManager( const Sptr < SubscribeManager > subscribeManager ){ subManager = subscribeManager;}///voidUaBuilder::startRegistration(){ if ( UaConfiguration::instance()->getRegisterOn() ) { registrationManager = new RegistrationManager( sipStack ); assert( registrationManager != 0 ); }} // UaBuilder::startRegistration
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -