📄 authagent.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 AuthAgent_cxx_Version = "$Id: AuthAgent.cxx,v 1.23.2.1 2003/02/05 02:56:53 sprajpat Exp $";#include "ByeMsg.hxx"#include "InfoMsg.hxx"#include "SipTextData.hxx"#include "SipProxyAuthorization.hxx"#include "SystemInfo.hxx"#include "SipRoute.hxx"#include "ControlStateFactory.hxx"#include "CallDB.hxx"#include "B2bFacade.hxx"#include "MultiLegCallControl.hxx"#include "UaServer.hxx"#include "UaClient.hxx"#include "AuthAgent.hxx"#include "B2bConfig.hxx"#include "CallTimerEvent.hxx"#include "AAAEvent.hxx"#include "AuthData.hxx"#include "BillingData.hxx"#include "SipVia.hxx"using namespace Vocal;using namespace Vocal::UA;AuthAgent::AuthAgent(unsigned long authId, const Sptr<SipMsg>& sipMsg) : BasicAgent(authId) { myState = ControlStateFactory::instance().getState(C_STATE_INIT); ///Create new UserAgent myInvokee = new UaServer(sipMsg, B2bFacade::instance().getSipTransceiver(), this); myInvokee->receivedMsg(sipMsg); //Extract the PUID if out there, or else use FROM header Sptr<SipCommand> sipCmd; sipCmd.dynamicCast(sipMsg); const SipProxyAuthorization& pAuth = sipCmd->getProxyAuthorization(); string puid; string encryptedPassword; LocalScopeAllocator lo; if(pAuth.encode().length()) { if(pAuth.getAuthScheme() == AUTH_BASIC) { puid = sipMsg->getFrom().getUser().getData(lo); encryptedPassword = pAuth.getBasicCookie().getData(lo); } else { puid = pAuth.getTokenValue(USERNAME).getData(lo); encryptedPassword = pAuth.getTokenValue("response").getData(lo); } cpLog(LOG_DEBUG, "Setting UID (%s), password (%s) from Proxy-Authorization header", puid.c_str(), encryptedPassword.c_str()); } else { //No Authentication scheme, set the dummy password puid = sipMsg->getFrom().getUser().getData(lo); encryptedPassword = "."; cpLog(LOG_DEBUG, "No Authentication info available, setting UID (%s) from FROM header", puid.c_str()); } //Extracted PUID //Add the callleg in CallDb CallDB::instance().addCallLeg(myInvokee); //Set the authData myAAAData = new AuthData(puid, encryptedPassword, theSystem.gethostAddress(), sipMsg->getFrom().getUser().getData(lo), sipMsg->getTo().getUser().getData(lo));};void AuthAgent::doAuth() { myState->auth(*this); Sptr<AAAEvent> authEvent = new AAAEvent(this); if(B2bConfig::instance().getStr(B2bConfig::PP_OPTIONS) == B2bConfig::PP_FREE) { //Since call is free, no need to authenticate and no //Need to timeout either Sptr<AuthData> authData; authData.dynamicCast(myAAAData); assert(myAAAData != 0); //This should be done by the stack, to check the mandator FROM and TO field //If radius server is used, this situation would result in a REJECTION any ways if(myInvokee->getRequest()->getFrom().getUser().length() && myInvokee->getRequest()->getTo().getUser().length()) { authData->setStatus(A_ACCEPT); } else { authData->setStatus(A_REJECT); } //Set the callout time to infinite authData->setSessionTimeOut(-1); authDone(authEvent); } else { ///Queue the request for authorization const SipCallLeg& cLeg = myInvokee->getCallLeg(); cpLog(LOG_DEBUG, "Sending AAA request for id: %ld, callleg(%s)", getId(), cLeg.encode().logData()); B2bFacade::instance().getAAATransceiver()->sendAuthRequest(authEvent); }}void AuthAgent::authDone(const Sptr<AAAEvent>& aEvent) { Sptr<AuthData> authData; authData.dynamicCast(myAAAData); assert(myAAAData != 0); if(authData->getStatus() == A_ACCEPT) { const SipCallLeg& cLeg = myInvokee->getCallLeg(); cpLog(LOG_DEBUG, "Authorization accepted for id(%ld), callleg(%s)", getId(), cLeg.encode().logData()); Sptr<AccountingData> aData = new AccountingData(myAuthId); CallDB::instance().setAccountingData(cLeg, myAuthId, aData); Sptr<AuthData> authData; authData.dynamicCast(myAAAData); int duration = authData->getSessionTimeOut(); cpLog(LOG_DEBUG, "Call duration is (%d)", duration); aData->setUnusedSeconds(duration); myState->authDone(*this); } else { const SipCallLeg& cLeg = myInvokee->getCallLeg(); cpLog(LOG_DEBUG, "Authorization failed for id(%ld), callleg(%s)", getId(), cLeg.encode().logData()); //Auth failed //Send 404 to the caller Sptr<SipMsg> sipMsg = myInvokee->getRequest(); //Send 404 first Sptr<SipCommand> sCmd; sCmd.dynamicCast(sipMsg); Sptr<StatusMsg> statusMsg = new StatusMsg(*sCmd, 404); myInvokee->sendMsg(statusMsg); myState->fail(*this); }}void AuthAgent::placeCall(){ cpLog(LOG_DEBUG, "AuthAgent::placeCall()"); //Create a client side user agent //Create Invite from the source invite Sptr<SipMsg> sipMsg = myInvokee->getRequest(); Sptr<InviteMsg> iMsg; iMsg.dynamicCast(sipMsg); Sptr<InviteMsg> inviteMsg = UaBase::createInvite(iMsg); if(B2bConfig::instance().getStr(B2bConfig::PP_OPTIONS) != B2bConfig::PP_FREE) { ///Send the start account data event //Get the saved user name string uName = myAAAData->getUserName(); LocalScopeAllocator lo; myAAAData = new BillingData(myInvokee->getRequest()->getCallId().getData().getData(lo), uName, theSystem.gethostAddress(), sipMsg->getFrom().getUser().getData(lo), sipMsg->getTo().getUser().getData(lo)); Sptr<AAAEvent> aEvent = new AAAEvent(this); cpLog(LOG_DEBUG, "Sending Start account data"); B2bFacade::instance().getAAATransceiver()->sendAcctStart(aEvent); } Sptr<MultiLegCallData> mData = CallDB::instance().getMultiLegCallData(myInvokee->getCallLeg()); assert(mData != 0); Sptr<AccountingData> accData = mData->getAccountingData(); time_t t; t = time(&t); accData->setStartTime(t); Sptr<UaBase> userAgent = new UaClient(inviteMsg, B2bFacade::instance().getSipTransceiver(), this); CallDB::instance().addPeer(myInvokee, userAgent); userAgent->sendMsg(inviteMsg); cpLog(LOG_DEBUG, "%s, sending %s", userAgent->className().c_str(), inviteMsg->encode().logData());}void AuthAgent::doBye(){ cpLog(LOG_DEBUG, "AuthAgent::doBye()"); myInvokee->sendBye(); //Send bye to the caller and its peers //Find the agent's peer and send bye to all peers Sptr<UserAgentPeerList> pList = CallDB::instance().findAllPeers(*myInvokee); for(UserAgentPeerList::iterator itr = pList->begin(); itr != pList->end(); itr++) { (*itr)->sendBye(); } Sptr<BillingData> bData; bData.dynamicCast(myAAAData); assert(bData != 0); bData->setTermCause(BT_SESSION_TIMEOUT); endCall();}void AuthAgent::endCall(){ //Cancel timer B2bFacade::instance().getEventFifo()->cancel(myTimerId); cpLog(LOG_DEBUG, "AuthAgent::endCall()"); Sptr<MultiLegCallData> mData = CallDB::instance().getMultiLegCallData(myInvokee->getCallLeg()); assert(mData != 0); Sptr<AccountingData> accData = mData->getAccountingData(); time_t t; t = time(&t); accData->setEndTime(t); if(B2bConfig::instance().getStr(B2bConfig::PP_OPTIONS) != B2bConfig::PP_FREE) { ///Send Stop records to billing int duration = t - accData->getStartTime(); Sptr<BillingData> bData; bData.dynamicCast(myAAAData); assert(bData != 0); bData->setDuration(duration); Sptr<AAAEvent> aEvent = new AAAEvent(this); cpLog(LOG_DEBUG, "AuthAgent::Sending Acct Stop"); B2bFacade::instance().getAAATransceiver()->sendAcctStop(aEvent); } ///Transit the controller state myState->bye(*this);}void AuthAgent::doCancel(){ cpLog(LOG_DEBUG, "AuthAgent::doCancel()"); myState->cancel(*this);}voidAuthAgent::timerExpired(){ cpLog(LOG_DEBUG, "AuthAgent::timerExpired()"); myState->timerExpired(*this);}voidAuthAgent::inCall(){ cpLog(LOG_DEBUG, "AuthAgent::inCall()"); assert(myInvokee->isAServer()); cpLog(LOG_DEBUG, "AuthAgent::inCall" ); //Transit the controller state machine to be inCall myState->inCall(*this); if(B2bConfig::instance().getStr(B2bConfig::PP_OPTIONS) != B2bConfig::PP_FREE) { ///Send the interim Account Record Sptr<MultiLegCallData> mData = CallDB::instance().getMultiLegCallData(myInvokee->getCallLeg()); assert(mData != 0); Sptr<AccountingData> accData = mData->getAccountingData(); ///Calculate the setup delay, which is the time difference between // the first ///invite sent to the callee and a final response wwas received time_t t; t = time(&t); int delay = t - accData->getStartTime(); cpLog(LOG_DEBUG, "Sending interim account data with delay (%ld)", delay); Sptr<AAAEvent> aEvent = new AAAEvent(this); Sptr<BillingData> bData; bData.dynamicCast(myAAAData); assert(bData != 0); bData->setSetupDelay(delay); B2bFacade::instance().getAAATransceiver()->sendAcctInterim(aEvent); //Disable it for now //sendInfoMsg(accData->getUnusedSeconds()); //Start the timer cpLog(LOG_DEBUG, "In Call, setting timer to (%d) seconds", accData->getUnusedSeconds()); Sptr<CallTimerEvent> tEvent = new CallTimerEvent(this); myTimerId = B2bFacade::instance().getEventFifo()->addDelayMs(tEvent,accData->getUnusedSeconds()*1000); }}voidAuthAgent::callFailed(){ cpLog(LOG_DEBUG, "AuthAgent::callFailed()"); myState->fail(*this);}voidAuthAgent::setDeleted(){ myDelFlag = true; cpLog(LOG_DEBUG, "Deleting AuthAgent::setDeleted:%d", getId()) ; CallDB::instance().removePeer(*myInvokee); CallDB::instance().removeAccountingData(getId()); MultiLegCallControl::instance().removeAgent(getId(), 30000);}voidAuthAgent::sendInfoMsg(int secs){ //Create Info message Sptr<InfoMsg> infoMsg = new InfoMsg(); infoMsg->setNumRecordRoute(0); infoMsg->setNumRoute(0); infoMsg->flushViaList(); SipVia via2; via2.setHost(theSystem.gethostAddress()); via2.setPort(B2bConfig::instance().getLocalSipPort()); infoMsg->setVia(via2); infoMsg->setRouteList(myInvokee->getRouteList()); SipRoute siproute = infoMsg->getRoute(0); infoMsg->removeRoute(0); SipRequestLine rLine(SIP_INFO, siproute.getUrl()); infoMsg->setRequestLine(rLine); infoMsg->setCallId(myInvokee->getRequest()->getCallId()); //Get local CSeq number, increment it and set it in the Info Message SipCSeq lSeq = myInvokee->getLocalCSeq(); lSeq.incrCSeq(); myInvokee->setLocalCSeq(lSeq); SipCSeq cSeq(SIP_INFO, lSeq.getCSeqData()); infoMsg->setCSeq(cSeq); char buf[256]; sprintf(buf, "You have (%d) seconds for the call\n", secs); Data ltData(buf); ltData += CRLF; SipTextData tData(ltData); infoMsg->setContentData(&tData); cpLog(LOG_DEBUG, "%s" , infoMsg->encode().logData()); B2bFacade::instance().getSipTransceiver()->sendAsync(infoMsg);}///void AuthAgent::receivedRequest(UaBase& agent, const Sptr<SipMsg>& msg){ MultiLegCallControl::instance().receivedRequest(agent,msg);}///void AuthAgent::receivedStatus(UaBase& agent, const Sptr<SipMsg>& msg){ MultiLegCallControl::instance().receivedStatus(agent,msg);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -