📄 siptransactioninviteserver.cxx
字号:
/* Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*//* * Authors: Erik Eliasson <eliasson@it.kth.se> * Johan Bilien <jobi@via.ecp.fr>*//* Name * SipTransactionIntiveResponder.cxx * Author * Erik Eliasson, eliasson@it.kth.se * Purpose*//* o Start | |INVITE |a0:pass INV to TU INVITE V send 100 if TU won't in 200ms a1:send response+-----------+ +--------| |--------+101-199 from TU | | Proceeding| |a2:send response (if 100rel, set TimerRel1xx) +------->| |<-------+ a20:TimerRel1xx+--------| | Transport Err. resendRel1xx | | | a4:Inform TU +------->| |--------------->+ +-----------+ | 300-699 from TU | |2xx from TU | a3:send response | |a5:send response | | +------------------>+ | | INVITE V Timer G fires | a6:send response+-----------+a8:send response| +--------| |--------+ | | | Completed | | | +------->| |<-------+ | +-----------+ | | | | ACK | | | a7: - | +------------------>+ | Timer H fires | V or Transport Err.| +-----------+ a9:Inform TU | | | | | Confirmed | | | | | +-----------+ | | | |Timer I fires | |a10: - | | | V | +-----------+ | | | | | Terminated|<---------------+ | | +-----------+ Figure 7: INVITE server transaction*/#include<config.h>#include<libmsip/SipTransactionInviteServer.h>#include<libmsip/SipTransactionNonInviteServer.h>#include<libmsip/SipResponse.h>#include<libmsip/SipTransactionUtils.h>#include<libmsip/SipCommandDispatcher.h>#include<libmsip/SipCommandString.h>#include<libmsip/SipDialog.h>#include<libmsip/SipDialogConfig.h>#ifdef DEBUG_OUTPUT#include<libmutil/termmanip.h>#endifusing namespace std;/** * The first command a INVITE server transaction receives is an INVITE * packet. It forwards the packet to the TU/call. We send no 1xx since we * expect a response from the TU in less than 200 ms. */bool SipTransactionInviteServer::a0_start_proceeding_INVITE( const SipSMCommand &command){ if (transitionMatch("INVITE", command, SipSMCommand::transport_layer, SipSMCommand::transaction_layer)){ MRef<Socket*> sock = command.getCommandPacket()->getSocket(); if( sock ) setSocket( *sock ); else setSocket( NULL ); SipSMCommand cmd(command); cmd.setSource(SipSMCommand::transaction_layer); cmd.setDestination(SipSMCommand::dialog_layer);// cmd.setSource(SipSMCommand::transaction); dispatcher->enqueueCommand(cmd, HIGH_PRIO_QUEUE/*, PRIO_LAST_IN_QUEUE*/); //update dialogs route set ... needed to add route headers to the ACK we are going to send // TODO/XXX/FIXME: implement this in the TU instead!!! --EE //setDialogRouteSet( (SipRequest*)*command.getCommandPacket() ); return true; }else{ return false; }}/** * If we receive the INVITE packet _again_, our response was probably lost. * In that case we retransmit it. * Note: We expected that the TU/Call would answer before the remote side * retransmitted. If this failed, and if DEBUG_OUTPUT then we display an * error message. * TODO: Implement an option to send 100 trying in action "a0". */bool SipTransactionInviteServer::a1_proceeding_proceeding_INVITE( const SipSMCommand &command){ if (transitionMatch("INVITE", command, SipSMCommand::transport_layer, SipSMCommand::transaction_layer)){ MRef<SipResponse*> resp = lastResponse; if (resp.isNull()){#ifdef DEBUG_OUTPUT merr << FG_ERROR << "Invite server transaction failed to deliver response before remote side retransmitted. Bug?"<< PLAIN << end;#endif }else{ send(MRef<SipMessage*>(*resp), false); } return true; }else{ return false; }}/** * If a "1xx" response is received from the TU(/call), send it to the * remote side and save it in case we need to retransmit it. */bool SipTransactionInviteServer::a2_proceeding_proceeding_1xx( const SipSMCommand &command){ if (transitionMatch(SipResponse::type, command, SipSMCommand::dialog_layer, SipSMCommand::transaction_layer, "1**")){ MRef<SipResponse*> resp = (SipResponse*)*command.getCommandPacket(); lastResponse = resp; //no need for via header, it is copied from the request msg #if 0 if (resp->requires("100rel")){ lastReliableResponse=resp; //The order we want (no race): // 1. Create PRACK server transaction // 2. Request timeout // 3. send 1xx message MRef<SipTransaction*> pracktrans = new SipTransactionNonInviteServer(sipStack, /*MRef<SipDialog*>(this)*/ dialog, resp->getCSeq()+1, // The PRACK transaction MUST be the next in sequence "PRACK", /*bye->getLastViaBranch()*/ "", dialog->dialogState.callId); dialog->registerTransaction(pracktrans); timerRel1xxResend = sipStack->getTimers()->getT1(); requestTimeout(timerRel1xxResend,"timerRel1xxResend"); }#endif send(command.getCommandPacket(), false); return true; }else{ return false; }}/** * If a response (non 2xx/1xx) is received from the TU/Call, we send it to * the remote side. We save it in case we need to retransmit it later. * Set "timerH", wait time for an ACK. * Set "timerG", response re-tx interval */bool SipTransactionInviteServer::a3_proceeding_completed_resp36( const SipSMCommand &command){ if (transitionMatch(SipResponse::type, command, SipSMCommand::dialog_layer, SipSMCommand::transaction_layer, "3**\n4**\n5**\n6**")){ cancelTimeout("timerRel1xxResend"); lastResponse = MRef<SipResponse*>((SipResponse*)*command.getCommandPacket()); if( isUnreliable() ) { timerG = sipStack->getTimers()->getG(); requestTimeout(timerG, "timerG"); } requestTimeout(sipStack->getTimers()->getH(),"timerH"); //no need for via header, it is copied from the request msg send(command.getCommandPacket(), false); return true; }else return false;}/** * If we receive a "transport_error" indication, we inform the TU and go to * the terminated state. * FIXME: There is currently no one giving this command to the transaction * layer (EE, r241). */bool SipTransactionInviteServer::a4_proceeding_terminated_err( const SipSMCommand &command){ if (transitionMatch(command, SipCommandString::transport_error, SipSMCommand::transport_layer, SipSMCommand::transaction_layer)){ cancelTimeout("timerRel1xxResend"); SipSMCommand cmd( CommandString(callId, SipCommandString::transport_error), SipSMCommand::transaction_layer, SipSMCommand::dialog_layer); dispatcher->enqueueCommand( cmd, HIGH_PRIO_QUEUE/*, PRIO_LAST_IN_QUEUE*/ ); SipSMCommand cmdterminated( CommandString( callId, SipCommandString::transaction_terminated), SipSMCommand::transaction_layer, SipSMCommand::dispatcher); dispatcher->enqueueCommand( cmdterminated, HIGH_PRIO_QUEUE/*, PRIO_FIRST_IN_QUEUE*/ ); return true; }else{ return false; }}/** * If a 2xx response is received from the TU/Call it is sent to the remote * side and the transaction terminates. Note that the ACK is not yet * handled when a 2xx terminates the INVITE server transaction. */bool SipTransactionInviteServer::a5_proceeding_terminated_2xx( const SipSMCommand &command){ if (transitionMatch(SipResponse::type, command, SipSMCommand::dialog_layer, SipSMCommand::transaction_layer, "2**")){ cancelTimeout("timerRel1xxResend"); lastResponse = MRef<SipResponse*>((SipResponse*)*command.getCommandPacket()); //no need for via header, it is copied from the request msg send(command.getCommandPacket(), false); SipSMCommand cmd( CommandString( callId, SipCommandString::transaction_terminated), SipSMCommand::transaction_layer, SipSMCommand::dispatcher); dispatcher->enqueueCommand( cmd, HIGH_PRIO_QUEUE/*, PRIO_FIRST_IN_QUEUE*/ ); return true; }else{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -