📄 uacallcontrol.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 UaCallControl_cxx_Version = "$Id: UaCallControl.cxx,v 1.28.2.11 2003/03/13 00:28:42 sprajpat Exp $";#include "SipEvent.hxx" #include "CallTimerEvent.hxx" #include "CallDB.hxx" #include "UaCallControl.hxx" #include "UaFacade.hxx" #include "CallAgent.hxx" #include "GuiEvent.hxx" #include "SdpHandler.hxx" #include "UaConfiguration.hxx" #include "SipUrl.hxx" #include "TelUrl.hxx" #include "CryptoRandom.hxx" #include "SipUserAgent.hxx" #include "SipTransactionId.hxx" #include "SipVia.hxx"#include "UaHardwareEvent.hxx"#include "DeviceEvent.hxx"#include "UaCommandLine.hxx"#include "MediaController.hxx"#include "NotifyMsg.hxx"#include "SubscribeMsg.hxx"#include "SipSubsNotifyEvent.hxx"#include "SipTextData.hxx"#include "RandomHex.hxx"#ifdef USE_MPEGLIB#include "VideoDevice.hxx"#endifusing namespace Vocal;using namespace UA;UaCallControl* UaCallControl::myInstance = 0;#define NUM_TAG_RANDOMNESS 4void UaCallControl::receivedRequest(UaBase& agent, const Sptr<SipMsg>& msg){}void UaCallControl::receivedStatus(UaBase& agent, const Sptr<SipMsg>& msg){ //Nothing to do here}bool UaCallControl::processEvent(const Sptr<SipProxyEvent>& event){ cpLog(LOG_DEBUG, "UaCallControl::processEvent"); if(CallControl::processEvent(event)) { cpLog(LOG_DEBUG, "Event handled by the base class"); //Already handled by the base class, so return return true; } //handle all-kinds of events, from GUI, CLI here Sptr<SipEvent> sipEvent; sipEvent.dynamicCast(event); if(sipEvent != 0) { cpLog(LOG_DEBUG, "Handling SIP event"); //Only Incoing INVITE is accepted, rest is an error Sptr<SipMsg> sipMsg = sipEvent->getSipMsg(); assert(sipMsg != 0); if(sipMsg->getType() != SIP_INVITE) { UaFacade::instance().postInfo(sipMsg); if(sipMsg->getType() == SIP_REGISTER) { Sptr<SipCommand> sCommand; sCommand.dynamicCast(sipMsg); Sptr<StatusMsg> sMsg = new StatusMsg(*sCommand, 501); UaFacade::instance().getSipTransceiver()->sendReply(sMsg); UaFacade::instance().postInfo(sMsg); cpLog(LOG_DEBUG, "Replying the Above msg (%s)\n", sMsg->encode().logData()); return true; } if((sipMsg->getType() == SIP_STATUS) ) { if(sipMsg->getCSeq().getMethod() == REGISTER_METHOD) { Sptr<StatusMsg> statusMsg; statusMsg.dynamicCast(sipMsg); if(statusMsg->getStatusLine().getStatusCode() == 200) { if((statusMsg->getExpires().getDelta().convertInt())) { UaFacade::instance().postMsg("REGISTERED "); } else { UaFacade::instance().postMsg("REGISTRATIONEXPIRED "); } } UaFacade::instance().getRegistrationManager()->handleRegistrationResponse(*statusMsg); } else if (sipMsg->getCSeq().getMethod() == CANCEL_METHOD) { UaFacade::instance().postMsg("L_HANGUP "); } } else if (sipMsg->getType() == SIP_SUBSCRIBE) { Sptr<SipCommand> sCommand; int _myPort = atoi((UaConfiguration::instance().getValue(LocalSipPortTag)).c_str()); sCommand.dynamicCast(sipMsg); Sptr<StatusMsg> sMsg = new StatusMsg(*sCommand, 200); UaFacade::instance().getSipTransceiver()->sendReply(sMsg); Sptr<SubscribeMsg> sbMsg; sbMsg.dynamicCast(sipMsg); SipSubsNotifyEvent ev("Notify"); Sptr<NotifyMsg> nMsg = new NotifyMsg(*sbMsg, ev); SipVia sipVia; sipVia.setprotoVersion("2.0"); sipVia.setHost(Data(theSystem.gethostAddress()) ); sipVia.setPort(_myPort); nMsg->flushViaList(); nMsg->setVia(sipVia); if (sbMsg->getNumContact() == 1) { SipRoute route; route.setUrl(sbMsg->getContact().getUrl()); nMsg->setRoute(route); //remove the contact header. nMsg->setNumContact(0); } SipContact myContact; Sptr< SipUrl > contactUrl = new SipUrl; contactUrl->setHost( Data( theSystem.gethostAddress() ) ); contactUrl->setPort(Data(_myPort)); myContact.setUrl( contactUrl ); nMsg->setContact(myContact); SipUserAgent uAgent("Vovida-SIP-SoftPhone/1.5.0 (www.vovida.org)"); nMsg->setUserAgent(uAgent); Sptr<SipUrl> tmpinetSipUrl; tmpinetSipUrl.dynamicCast(sbMsg->getContact().getUrl()); assert(tmpinetSipUrl != 0); // Create the XML blob as per IETF Draft "A Data format for // Presense using XML" Data buf; buf += "<?xml version=\"1.0\"?>"; buf += "\r\n"; buf +="<!DOCTYPE presence"; buf += "\r\n"; buf += "PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">"; buf += "\r\n"; buf += "<presence>"; buf += "\r\n"; buf += "<presentity uri=\""; buf += tmpinetSipUrl->getNameAddr(); buf += "\" />"; buf += "\r\n"; buf +="<atom id=\""; buf += RandomHex::get(4); buf += "\">"; buf += "\r\n"; buf += "<address uri=\""; buf += contactUrl->getNameAddr(); buf += ";user=ip\" priority=\"0.800000\">"; buf += "\r\n"; buf += "<status status=\"open\" />"; buf += "\r\n"; buf += "<duplex duplex=\"full\" />"; buf += "\r\n"; buf += "</address>"; buf += "\r\n"; buf += "</atom>"; buf += "\r\n"; buf += "</presence>"; SipTextData Txt(buf,"xpidf+xml"); nMsg->setContentData(&Txt); // Send Notify Message to whoever SUBSCRIBED UaFacade::instance().getSipTransceiver()->sendAsync(nMsg); } else if (sipMsg->getType() == SIP_BYE) { Sptr<SipCommand> sCommand; sCommand.dynamicCast(sipMsg); Sptr<StatusMsg> sMsg = new StatusMsg(*sCommand, 200); UaFacade::instance().getSipTransceiver()->sendReply(sMsg); cpLog(LOG_ERR, "Out of dialog message (%s)", sipMsg->encode().logData()); cpLog(LOG_DEBUG, "Replying the Above msg to stop flodding (%s)\n", sMsg->encode().logData()); } else if ((sipMsg->getType() != SIP_ACK) && (sipMsg->getType() != SIP_SUBSCRIBE)) { Sptr<SipCommand> sCommand; sCommand.dynamicCast(sipMsg); Sptr<StatusMsg> sMsg = new StatusMsg(*sCommand, 501); UaFacade::instance().getSipTransceiver()->sendReply(sMsg); cpLog(LOG_ERR, "Not Implemented message (%s)", sipMsg->encode().logData()); cpLog(LOG_DEBUG, "Replying the Above msg (%s)\n", sMsg->encode().logData()); } return true; } //Send 4xx if busy Sptr<SipCommand> sCmd; sCmd.dynamicCast(sipMsg); if(busy(sCmd)) { cpLog(LOG_INFO, "Agent is busy, ignoring the call\n"); return true; } Sptr<InviteMsg> inMg; inMg.dynamicCast(sipMsg); Sptr<SipSdp> remoteSdp; remoteSdp.dynamicCast(inMg->getContentData(0)); if(remoteSdp == 0) { // no SDP, so abort Sptr<SipCommand> Cmd; Cmd.dynamicCast(sipMsg); Sptr<StatusMsg> sMsg = new StatusMsg(*Cmd, 606); UaFacade::instance().getSipTransceiver()->sendReply(sMsg); cpLog(LOG_ERR, "No SDP in INVITE message (%s)", sipMsg->encode().logData()); cpLog(LOG_DEBUG, "Replying the Above msg (%s)\n", sMsg->encode().logData()); return true; } if(!(inMg->getContentLength().getLength().convertInt() == 0) && (remoteSdp->getRtpPort() == 0)){ Sptr<SipCommand> Cmd; Cmd.dynamicCast(sipMsg); Sptr<StatusMsg> sMsg = new StatusMsg(*Cmd, 606); UaFacade::instance().getSipTransceiver()->sendReply(sMsg); cpLog(LOG_ERR, "No Port in the m line of SDP in INVITE message (%s)", sipMsg->encode().logData()); cpLog(LOG_DEBUG, "Replying the Above msg (%s)\n", sMsg->encode().logData()); return true; } //Create the CallAgent to control UaServer Sptr<CallAgent> cAgent = new CallAgent(sipMsg, Vocal::UA::A_SERVER); //Persist the agent for the duration of the call myMutex.lock(); myCallMap[cAgent->getId()] = cAgent; myMutex.unlock(); //Post message to the GUI strstream s; s << "RINGING " << sipMsg->getFrom().getUser().logData() << endl << ends; UaFacade::instance().postMsg(s.str()); s.freeze(false); //Send the 180 back to the caller Sptr<SipCommand> sCommand; sCommand.dynamicCast(sipMsg); Sptr<StatusMsg> sMsg = new StatusMsg(*sCommand, 180); cAgent->getInvokee()->sendMsg(sMsg); //UaFacade::instance().getSipTransceiver()->sendReply(sMsg); if((UaFacade::instance().getMode() == CALL_MODE_ANNON) || (UaFacade::instance().getMode() == CALL_MODE_VMAIL)) { cAgent->acceptCall(); } //UaServer state-machine will take the call from here return true; } Sptr<GuiEvent> gEvent; gEvent.dynamicCast(event); if(gEvent != 0) { handleGuiEvents(gEvent); return true; } Sptr<UaHardwareEvent> hEvent; hEvent.dynamicCast(event); if(hEvent != 0) { //Get the event id int id = hEvent->myId; Sptr<CallAgent> cAgent; myMutex.lock(); if(myCallMap.count(id)) { cAgent.dynamicCast(myCallMap[id]); if(hEvent->type == HardwareAudioType) { if(hEvent->request.type == AudioStop) { cAgent->doBye(); } } } else { cpLog(LOG_DEBUG, "Did not find agent for id:%d" ,id); } myMutex.unlock(); return true; }#if 1 Sptr<DeviceEvent> dEvent; dEvent.dynamicCast(event); if(dEvent != 0) { //Get the event id int id = dEvent->id; Sptr<CallAgent> cAgent; myMutex.lock(); if(myCallMap.count(id)) { cAgent.dynamicCast(myCallMap[id]); if(dEvent->type == DeviceEventHookDown) { //VMCP server sent an event, cleanup cAgent->doBye(); } } else { cpLog(LOG_DEBUG, "Did not find agent for id:%d" ,id); } myMutex.unlock(); return true; }#endif return true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -