public void Initialize(IInternalSoftPhone softPhone) { Check.Require(softPhone.EndWaitForAckTimer, "softPhone.EndWaitForAckTimer"); softPhone.EndWaitForAckTimer.Start(); _logger.Debug("Initialized."); }
protected override void AfterPhoneProcessedRequest(IInternalSoftPhone softPhone, SipRequestEvent requestEvent) { if (requestEvent.Request.CSeq.Command == SipMethods.Invite) { _waitingforInviteReceived.Set(); } }
public void AfterInitialize(IInternalSoftPhone softPhone) { Check.Require(softPhone, "softPhone"); Check.Require(softPhone.PendingCall, "softPhone.PendingCall"); softPhone.PendingCall.RaiseCallStateChanged(CallState.Setup); }
protected override void AfterPhoneProcessedResponse(IInternalSoftPhone softPhone, Hallo.Sip.Stack.SipResponseEvent responseEvent) { if (responseEvent.Response.StatusLine.StatusCode == 180) { _waitingforRingingProcessed.Set(); } }
protected override void AfterPhoneProcessedResponse(IInternalSoftPhone softPhone, SipResponseEvent responseEvent) { if (responseEvent.Response.StatusLine.StatusCode == 200 && responseEvent.Response.CSeq.Command == SipMethods.Bye) { _waitForOkByeProcessed.Set(); } }
public void ProcessResponse(IInternalSoftPhone softPhone, Sip.Stack.SipResponseEvent responseEvent) { SipStatusLine statusLine = responseEvent.Response.StatusLine; _logger.Debug("processing response: {0} ...", statusLine.ResponseCode); int statusCodeDiv100 = statusLine.StatusCode / 100; if (responseEvent.ClientTransaction == null) { if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. In this state, the ResponseEvent is expected to have a 'NOT NULL' ClientTx. DebugInfo: TxId created from RESPONSE: '{1}'. This Id could not be matched to a clienttransaction in the provider's clienttransactiontable.", statusCodeDiv100, SipProvider.GetClientTransactionId(responseEvent.Response)); return; } /*wait for ok on bye*/ if (_logger.IsInfoEnabled) _logger.Info("'{0}XX' response. Begin processing...", statusCodeDiv100); if (statusCodeDiv100 != 2) { if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. Only 'x200-299' responses are processed in this state."); return; } if (responseEvent.ClientTransaction.Request.CSeq.Command == SipMethods.Bye) { if (_logger.IsInfoEnabled) _logger.Info("Received final response on 'BYE' request.Transitioning to Idle..."); softPhone.ChangeState(softPhone.StateProvider.GetIdle()); } else { if (_logger.IsDebugEnabled) _logger.Debug("Response ignored. This is not the response to the 'BYE' request."); } }
public void Initialize(IInternalSoftPhone softPhone) { Check.Require(softPhone, "softPhone"); Check.Require(softPhone.PendingInvite, "softPhone.PendingInvite"); _logger.Debug("Initialized."); }
protected override void AfterPhoneProcessedResponse(IInternalSoftPhone softPhone, Hallo.Sip.Stack.SipResponseEvent responseEvent) { if (responseEvent.Response.StatusLine.StatusCode == 180) { _ringingProcessed.Set(); } }
public void AfterInitialize(IInternalSoftPhone softPhone) { Check.Require(softPhone, "softPhone"); Check.Require(softPhone.PendingCall, "softPhone.PendingCall"); softPhone.PendingCall.RaiseCallStateChanged(CallState.Ringing); }
public void ProcessResponse(IInternalSoftPhone softPhone, SipResponseEvent responseEvent) { ProcessResponseCounter++; _state.ProcessResponse(softPhone, responseEvent); _afterProcessResponse(softPhone, responseEvent); }
public void Initialize(IInternalSoftPhone softPhone) { Check.Require(softPhone.PendingInvite, "softPhone.PendingInvite"); Check.Require(softPhone.PendingInvite.CancelTransaction, "softPhone.PendingInvite.CancelTransaction"); Check.Require(softPhone.PendingInvite.InviteClientTransaction, "softPhone.PendingInvite.InviteClientTransaction"); _logger.Debug("Initialized."); }
public void ProcessRequest(IInternalSoftPhone softPhone, SipRequestEvent requestEvent) { ProcessRequestCounter++; _state.ProcessRequest(softPhone, requestEvent); _afterProcessRequest(softPhone, requestEvent); }
public void ProcessResponse(IInternalSoftPhone softPhone, Sip.Stack.SipResponseEvent responseEvent) { SipStatusLine statusLine = responseEvent.Response.StatusLine; _logger.Debug("processing response: {0} ...", statusLine.ResponseCode); int statusCodeDiv100 = statusLine.StatusCode / 100; if (responseEvent.ClientTransaction == null) { if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. In this state, the ResponseEvent is expected to have a 'NOT NULL' ClientTx. DebugInfo: TxId created from RESPONSE: '{1}'. This Id could not be matched to a clienttransaction in the provider's clienttransactiontable.", statusCodeDiv100, SipProvider.GetClientTransactionId(responseEvent.Response)); return; } /*wait for ok on cancel + 487 for invite*/ if (_logger.IsInfoEnabled) _logger.Info("'{0}XX' response. Begin processing...", statusCodeDiv100); if (statusCodeDiv100 < 2) { if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. Only FINAL (x200-x500) responses are processed in this state."); return; } if (responseEvent.ClientTransaction.GetId() == softPhone.PendingInvite.CancelTransaction.GetId()) { _receivedFinalCancelStatusCode = responseEvent.Response.StatusLine.StatusCode; if (_logger.IsInfoEnabled) _logger.Info("Received final response on 'CANCEL' request. StatusCode: {0}", _receivedFinalCancelStatusCode); } if (responseEvent.ClientTransaction.GetId() == softPhone.PendingInvite.InviteClientTransaction.GetId()) { if (_logger.IsInfoEnabled) _logger.Info("Received final response on 'INVITE' request."); _receivedFinalInviteResponse = true; if (_logger.IsDebugEnabled) _logger.Debug("Terminating the Dialog..."); softPhone.PendingInvite.Dialog.Terminate(); if (_logger.IsDebugEnabled) _logger.Debug("Dialog terminated."); } //TODO: use locks. if (_receivedFinalCancelStatusCode == 481 || /*when cancel-tx x481 is received, the invite will NOT receive a final response. => go to idle immediately*/ (_receivedFinalCancelStatusCode == 200 && _receivedFinalInviteResponse)) /*when cancel-tx x200 is received, the invite will receive a final response. => wait for x487 before going to idle*/ { if (_logger.IsDebugEnabled) _logger.Debug("Changing CallState to 'Cancelled'"); softPhone.PendingCall.RaiseCallStateChanged(CallState.Cancelled); /*go to idle*/ if (_logger.IsDebugEnabled) _logger.Debug("Both 'CANCEL' & 'INVITE' Tx have received a final response. Transitioning to Idle..."); softPhone.ChangeState(softPhone.StateProvider.GetIdle()); } }
protected override void AfterPhoneProcessedResponse(IInternalSoftPhone softPhone, Hallo.Sip.Stack.SipResponseEvent responseEvent) { if (responseEvent.Response.StatusLine.StatusCode == 180) { _ringingProcessed.Set(); } if (responseEvent.Response.StatusLine.StatusCode == 200 && responseEvent.Response.CSeq.Command == SipMethods.Cancel) { _waitforOkProcessed.Set(); } }
public void Initialize(IInternalSoftPhone softPhone) { Check.Require(softPhone, "softPhone"); Check.Require(softPhone.PendingInvite, "softPhone.PendingInvite"); if (softPhone.PendingInvite.IsIncomingCall) { softPhone.RetransmitRingingTimer.Start(); } _logger.Debug("Initialized."); }
protected override void AfterPhoneProcessedResponse(IInternalSoftPhone softPhone, Hallo.Sip.Stack.SipResponseEvent responseEvent) { if (responseEvent.Response.StatusLine.StatusCode == 180) { _ringingProcessed.Set(); } if (responseEvent.Response.StatusLine.StatusCode == 481 && responseEvent.Response.CSeq.Command == SipMethods.Cancel) { _waitforProcessed.Set(); } }
public void ProcessRequest(IInternalSoftPhone softPhone, Sip.Stack.SipRequestEvent requestEvent) { string method = requestEvent.Request.RequestLine.Method; _logger.Debug("processing request: {0} ...", method); if (method != SipMethods.Bye) { if (_logger.IsDebugEnabled) _logger.Debug("Received request: '{0}'. Request ignored.", method); return; } if (_logger.IsInfoEnabled) { _logger.Info("'BYE' received. Begin processing..."); } if (requestEvent.Dialog == null) { if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. A 'BYE' RequestEvent is expected to have a 'NOT NULL' dialog. DebugInfo: DialogId created from BYE: '{0}'. This Id could not be matched to a dialog in the provider's dialogtable.", SipProvider.GetDialogId(requestEvent.Request, true)); return; } if (requestEvent.Dialog.GetId() != softPhone.PendingInvite.Dialog.GetId()) { if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. The 'BYE' RequestEvent.Dialog, is expected to match only to the Dialog of the PendingInvite. DebugInfo: DialogId created from BYE: '{0}'. This case is not supposed to occur, since the phone can only process ONE dialog at a time. Check what's going on !!", SipProvider.GetDialogId(requestEvent.Request, true)); return; } if (_logger.IsDebugEnabled) _logger.Debug("Sending OK response to BYE.."); var okResponse = requestEvent.Request.CreateResponse(SipResponseCodes.x200_Ok); var tx = softPhone.SipProvider.CreateServerTransaction(requestEvent.Request); tx.SendResponse(okResponse); requestEvent.IsSent = true; softPhone.PendingInvite.Dialog.Terminate(); softPhone.PendingCall.RaiseCallStateChanged(CallState.Completed); if (_logger.IsDebugEnabled) _logger.Debug("OK Send."); if (_logger.IsInfoEnabled) { _logger.Info("Transitioning to 'IDLE'..."); } softPhone.ChangeState(softPhone.StateProvider.GetIdle()); }
public void AfterInitialize(IInternalSoftPhone softPhone) { Check.Require(softPhone, "softPhone"); Check.Require(softPhone.PendingCall, "softPhone.PendingCall"); softPhone.PendingCall.RaiseCallStateChanged(CallState.Ringback); if (softPhone.PendingInvite.CancelOnWaitFinal) { softPhone.SendCancel(); softPhone.PendingInvite.CancelOnWaitFinal = false; } }
public void ProcessResponse(IInternalSoftPhone softPhone, Sip.Stack.SipResponseEvent responseEvent) { SipStatusLine statusLine = responseEvent.Response.StatusLine; _logger.Debug("processing response: {0} ...", statusLine.ResponseCode); int statusCodeDiv100 = statusLine.StatusCode / 100; if (responseEvent.ClientTransaction == null) { if (_logger.IsInfoEnabled) { _logger.Info("Processing ABORTED. In this state, the ResponseEvent is expected to have a 'NOT NULL' ClientTx. DebugInfo: TxId created from RESPONSE: '{1}'. This Id could not be matched to a clienttransaction in the provider's clienttransactiontable.", statusCodeDiv100, SipProvider.GetClientTransactionId(responseEvent.Response)); } return; } /*wait for ok on bye*/ if (_logger.IsInfoEnabled) { _logger.Info("'{0}XX' response. Begin processing...", statusCodeDiv100); } if (statusCodeDiv100 != 2) { if (_logger.IsInfoEnabled) { _logger.Info("Processing ABORTED. Only 'x200-299' responses are processed in this state."); } return; } if (responseEvent.ClientTransaction.Request.CSeq.Command == SipMethods.Bye) { if (_logger.IsInfoEnabled) { _logger.Info("Received final response on 'BYE' request.Transitioning to Idle..."); } softPhone.ChangeState(softPhone.StateProvider.GetIdle()); } else { if (_logger.IsDebugEnabled) { _logger.Debug("Response ignored. This is not the response to the 'BYE' request."); } } }
public void AfterInitialize(IInternalSoftPhone softPhone) { Check.Require(softPhone, "softPhone"); Check.Require(softPhone.PendingCall, "softPhone.PendingCall"); Check.Require(softPhone.PendingInvite, "softPhone.PendingInvite"); Check.Require(softPhone.PendingInvite.Dialog, "softPhone.PendingInvite.Dialog"); softPhone.PendingCall.RaiseCallStateChanged(CallState.Completed); if (_logger.IsInfoEnabled) _logger.Info("CallState changed to 'Completed'."); softPhone.PendingInvite.Dialog.Terminate(); if (_logger.IsDebugEnabled) _logger.Debug("Dialog terminated."); }
public void ProcessRequest(IInternalSoftPhone softPhone, Sip.Stack.SipRequestEvent requestEvent) { string method = requestEvent.Request.RequestLine.Method; _logger.Debug("processing request: {0} ...", method); if (method != SipMethods.Invite) { if (_logger.IsDebugEnabled) _logger.Debug("Received request: '{0}'. Request ignored.", method); return; } if(_logger.IsInfoEnabled) _logger.Info("'INVITE' received. Creating 'RINGING' response..."); var ringingResponse = requestEvent.Request.CreateResponse(SipResponseCodes.x180_Ringing); ringingResponse.To.Tag = SipUtil.CreateTag(); var contactUri = softPhone.AddressFactory.CreateUri("", softPhone.ListeningPoint.ToString()); ringingResponse.Contacts.Add(softPhone.HeaderFactory.CreateContactHeader(contactUri)); if (_logger.IsDebugEnabled) _logger.Debug("Sending response ... "); var serverTransaction = softPhone.SipProvider.CreateServerTransaction(requestEvent.Request); var dialog = softPhone.SipProvider.CreateServerDialog(serverTransaction as SipInviteServerTransaction); serverTransaction.SendResponse(ringingResponse); requestEvent.IsSent = true; if (_logger.IsInfoEnabled) _logger.Info("Response send. Transitioning to 'RINGING' state."); softPhone.PendingInvite = new InviteInfo() { OriginalRequest = requestEvent.Request, RingingResponse = ringingResponse, From = requestEvent.Request.From.SipUri, To = requestEvent.Request.To.SipUri, InviteServerTransaction = (SipInviteServerTransaction) serverTransaction, IsIncomingCall = true, Dialog = dialog }; softPhone.RaiseIncomingCall();/* !! the incoming call event is raised, before any callstate events can occur*/ softPhone.ChangeState(softPhone.StateProvider.GetRinging()); if (_logger.IsDebugEnabled) _logger.Debug("'RINGING' response created. Raising Incoming PhoneCall..."); if (_logger.IsDebugEnabled) _logger.Debug("Raised."); }
public void ProcessRequest(IInternalSoftPhone softPhone, Sip.Stack.SipRequestEvent requestEvent) { string method = requestEvent.Request.RequestLine.Method; _logger.Debug("processing request: {0} ...", method); if (method != SipMethods.Ack) { if (_logger.IsDebugEnabled) { _logger.Debug("Received request: '{0}'. Request ignored.", method); } return; } if (_logger.IsInfoEnabled) { _logger.Info("'ACK' received. Begin processing..."); } if (requestEvent.Dialog == null) { if (_logger.IsInfoEnabled) { _logger.Info("Processing ABORTED. An 'ACK' RequestEvent is expected to have a 'NOT NULL' dialog. DebugInfo: DialogId created from ACK: '{0}'. This Id could not be matched to a dialog in the provider's dialogtable.", SipProvider.GetDialogId(requestEvent.Request, true)); } return; } if (requestEvent.Dialog.GetId() != softPhone.PendingInvite.Dialog.GetId()) { if (_logger.IsInfoEnabled) { _logger.Info("Processing ABORTED. The 'ACK' RequestEvent it's Dialog, is expected to match only to the Dialog of the PendingInvite. DebugInfo: DialogId created from ACK: '{0}'. This case is not supposed to occur, since the phone can only process ONE dialog at a time. Check what's going on !!", SipProvider.GetDialogId(requestEvent.Request, true)); } return; } if (_logger.IsInfoEnabled) { _logger.Info("Transitioning to 'ESTABLISHED'..."); } softPhone.ChangeState(softPhone.StateProvider.GetEstablished()); }
protected override void Given() { //create invite that is addresses to the phone's sipuri _invite = CreateInviteRequest(_testClientUaUri, _phoneUaUri); //create phone that is located at IpEndPoint2 var phoneCs = new FakeSipContextSource(_phoneUaEndPoint); _network = new FakeNetwork(); _sipProvider1 = new SipProvider(new SipStack(), phoneCs); _phone = new SoftPhone(_sipProvider1, new SipMessageFactory(), new SipHeaderFactory(), new SipAddressFactory(), _stateProvider, _timerFactory, new SipListeningPoint(_phoneUaEndPoint)); phoneCs.AddToNetwork(_network); _network.AddReceiver(_testClientUaEndPoint, OnTestClientUaReceive); _phone.InternalStateChanged += new EventHandler <EventArgs>(_calleePhone_InternalStateChanged); _phone.IncomingCall += new EventHandler <VoipEventArgs <IPhoneCall> >(_calleePhone_IncomingCall); _phone.Start(); GivenOverride(); }
public void AfterInitialize(IInternalSoftPhone softPhone) { Check.Require(softPhone, "softPhone"); Check.Require(softPhone.PendingCall, "softPhone.PendingCall"); Check.Require(softPhone.PendingInvite, "softPhone.PendingInvite"); Check.Require(softPhone.PendingInvite.Dialog, "softPhone.PendingInvite.Dialog"); softPhone.PendingCall.RaiseCallStateChanged(CallState.Completed); if (_logger.IsInfoEnabled) { _logger.Info("CallState changed to 'Completed'."); } softPhone.PendingInvite.Dialog.Terminate(); if (_logger.IsDebugEnabled) { _logger.Debug("Dialog terminated."); } }
public void ProcessRequest(IInternalSoftPhone softPhone, Sip.Stack.SipRequestEvent requestEvent) { string method = requestEvent.Request.RequestLine.Method; _logger.Debug("processing request: {0} ...", method); if (method != SipMethods.Ack) { if (_logger.IsDebugEnabled) _logger.Debug("Received request: '{0}'. Request ignored.", method); return; } if (_logger.IsInfoEnabled) { _logger.Info("'ACK' received. Begin processing..."); } if (requestEvent.Dialog == null) { if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. An 'ACK' RequestEvent is expected to have a 'NOT NULL' dialog. DebugInfo: DialogId created from ACK: '{0}'. This Id could not be matched to a dialog in the provider's dialogtable.", SipProvider.GetDialogId(requestEvent.Request, true)); return; } if (requestEvent.Dialog.GetId() != softPhone.PendingInvite.Dialog.GetId()) { if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. The 'ACK' RequestEvent it's Dialog, is expected to match only to the Dialog of the PendingInvite. DebugInfo: DialogId created from ACK: '{0}'. This case is not supposed to occur, since the phone can only process ONE dialog at a time. Check what's going on !!", SipProvider.GetDialogId(requestEvent.Request, true)); return; } if (_logger.IsInfoEnabled) { _logger.Info("Transitioning to 'ESTABLISHED'..."); } softPhone.ChangeState(softPhone.StateProvider.GetEstablished()); }
public void AfterInitialize(IInternalSoftPhone softPhone) { _state.AfterInitialize(softPhone); }
public void ProcessResponse(IInternalSoftPhone softPhone, SipResponseEvent responseEvent) { }
public void ProcessRequest(IInternalSoftPhone softPhone, Sip.Stack.SipRequestEvent requestEvent) { }
protected override void AfterPhoneProcessedResponse(IInternalSoftPhone softPhone, Hallo.Sip.Stack.SipResponseEvent responseEvent) { }
public void AfterInitialize(IInternalSoftPhone softPhone) { }
public void Terminate(IInternalSoftPhone softPhone) { _state.Terminate(softPhone); }
public void Terminate(IInternalSoftPhone softPhone) { }
protected virtual void AfterPhoneProcessedResponse(IInternalSoftPhone softPhone, SipResponseEvent responseEvent) { }
public void ProcessRequest(IInternalSoftPhone softPhone, SipRequestEvent requestEvent) { string method = requestEvent.Request.RequestLine.Method; if (method != SipMethods.Cancel) { if (_logger.IsDebugEnabled) { _logger.Debug("Received request: '{0}'. Request ignored.", method); } return; } if (_logger.IsInfoEnabled) { _logger.Info("'CANCEL' received. Start processing..."); } #region attempt to match transaction /*terminate pending invite with 487 (assumption: PendingInvite.OriginalRequest= requestEvent.ServerTransaction.Request)*/ if (_logger.IsDebugEnabled) { _logger.Debug("Attempting to match 'CANCEL' target-tx against a tx in the ServerTransactionTable..."); } var txIdAttempts = CreateTxIdAttempts(requestEvent.Request); ISipServerTransaction serverTransaction = null; foreach (var txIdAttempt in txIdAttempts) { serverTransaction = softPhone.SipProvider.FindServerTransactionById(txIdAttempt); if (serverTransaction != null) { break; } } #endregion if (serverTransaction == null) { #region no match if (_logger.IsDebugEnabled) { _logger.Debug("Could not match 'CANCEL' to an existing transaction. Sending x487 response..."); } var cancelResponse = requestEvent.Request.CreateResponse(SipResponseCodes.x481_Call_Transaction_Does_Not_Exist); var cancelTx = softPhone.SipProvider.CreateServerTransaction(requestEvent.Request); cancelTx.SendResponse(cancelResponse); requestEvent.IsSent = true; if (_logger.IsDebugEnabled) { _logger.Debug("x487 response send."); } #endregion } else { #region matched #region respond to cancel with ok if (_logger.IsDebugEnabled) { _logger.Debug("'CANCEL' target-tx matched. Answering to cancel with ok..."); } var cancelOkResponse = requestEvent.Request.CreateResponse(SipResponseCodes.x200_Ok); var cancelOkTx = softPhone.SipProvider.CreateServerTransaction(requestEvent.Request); cancelOkTx.SendResponse(cancelOkResponse); requestEvent.IsSent = true; if (_logger.IsDebugEnabled) { _logger.Debug("Answered."); } #endregion #region respond to matched tx with x487 if (serverTransaction.GetId() != softPhone.PendingInvite.InviteServerTransaction.GetId()) { if (_logger.IsInfoEnabled) { _logger.Info("'CANCEL' target-tx does NOT match 'INVITE.' Processing ABORTED. The 'CANCEL' target-tx is expected, to match only to the pending 'INVITE' servertransaction."); } } else { if (_logger.IsDebugEnabled) { _logger.Debug("Creating '487-Request terminated' response and sending..."); } var requestToCancel = serverTransaction.Request; var terminateResponse = requestToCancel.CreateResponse(SipResponseCodes.x487_Request_Terminated); /*terminate pending invite.*/ softPhone.PendingInvite.InviteServerTransaction.SendResponse(terminateResponse); if (_logger.IsDebugEnabled) { _logger.Debug("Response send."); } if (_logger.IsDebugEnabled) { _logger.Debug("Changing callstate to 'CANCELLED'."); } softPhone.PendingCall.RaiseCallStateChanged(CallState.Cancelled); if (_logger.IsInfoEnabled) { _logger.Info("'CANCEL' Processed. Transitioning (back) to 'Idle'"); } softPhone.ChangeState(softPhone.StateProvider.GetIdle()); } #endregion #endregion } }
public void Terminate(IInternalSoftPhone softPhone) { softPhone.RetransmitRingingTimer.Stop(); }
public void Initialize(IInternalSoftPhone softPhone) { _logger.Debug("Initialized."); }
public void ProcessResponse(IInternalSoftPhone softPhone, Sip.Stack.SipResponseEvent responseEvent) { SipStatusLine statusLine = responseEvent.Response.StatusLine; _logger.Debug("processing response: {0} ...", statusLine.ResponseCode); int statusCodeDiv100 = statusLine.StatusCode / 100; if (_logger.IsInfoEnabled) { _logger.Info("'{0}XX' response. Begin processing...", statusCodeDiv100); } if (responseEvent.ClientTransaction == null) { if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. A '{0}XX' ResponseEvent is expected to have a 'NOT NULL' ClientTx. DebugInfo: TxId created from RESPONSE: '{1}'. This Id could not be matched to a clienttransaction in the provider's clienttransactiontable.", statusCodeDiv100, SipProvider.GetClientTransactionId(responseEvent.Response)); return; } if (responseEvent.ClientTransaction.GetId() != softPhone.PendingInvite.InviteClientTransaction.GetId()) { if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. The '{0}XX' ResponseEvent.ClientTransaction, is expected to match only to the InviteSendTransaction of the PendingInvite. DebugInfo: TxId created from RESPONSE: '{1}'. This case is not supposed to occur, since the phone can only process ONE PendingInvite at a time. Check what's going on !!", statusCodeDiv100, SipProvider.GetClientTransactionId(responseEvent.Response)); return; } if (responseEvent.Dialog == null) { if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. In this state the 'ResponseEvent' is expected to have a 'NOT NULL' dialog. DebugInfo: DialogId created from Response: '{0}'. This Id could not be matched to a dialog in the provider's dialogtable.", SipProvider.GetDialogId(responseEvent.Response, false)); return; } if (responseEvent.Dialog.GetId() != softPhone.PendingInvite.Dialog.GetId()) { if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. In this state the 'ResponseEvent' it's Dialog, is expected to match only to the Dialog of the PendingInvite. DebugInfo: DialogId created from response: '{0}'. This case is not supposed to occur, since the phone can only process ONE dialog at a time. Check what's going on !!", SipProvider.GetDialogId(responseEvent.Response, false)); return; } if (statusCodeDiv100 == 1) { if (_logger.IsInfoEnabled) _logger.Info("Do nothing"); } else if (statusCodeDiv100 == 2) { if (_logger.IsInfoEnabled) _logger.Info("Transitioning to 'ESTABLISHED'..."); Check.IsTrue(responseEvent.Dialog is SipInviteClientDialog, "Failed to respond to '200' response with ACK request. The 'ACK' can not be created. The responseEvent.Dialog is expected to be of type SipInviteClientDialog."); var clientDialog = (SipInviteClientDialog) softPhone.PendingInvite.Dialog; var ack = clientDialog.CreateAck(); clientDialog.SendAck(ack); softPhone.ChangeState(softPhone.StateProvider.GetEstablished()); } else { //change callstate. Don't go automatically to 'IDLE' state, but wait for the api user to invoke Call.Stop() if (statusLine.ResponseCode == SipResponseCodes.x486_Busy_Here) { if (_logger.IsDebugEnabled) _logger.Debug("Changing CallState to 'BusyHere'"); softPhone.PendingCall.RaiseCallStateChanged(CallState.BusyHere); } else { if (_logger.IsDebugEnabled) _logger.Debug("Changing CallState to 'Error'"); softPhone.PendingCall.RaiseCallStateChanged(CallState.Error); } softPhone.PendingInvite.Dialog.Terminate(); } }
protected virtual void AfterInitialized(IInternalSoftPhone softPhone) { }
public void Terminate(IInternalSoftPhone softPhone) { Check.Require(softPhone.EndWaitForAckTimer, "softPhone.EndWaitForAckTimer"); softPhone.EndWaitForAckTimer.Stop(); }
protected virtual void AfterPhoneProcessedRequest(IInternalSoftPhone softPhone, SipRequestEvent requestEvent) { }
public void ProcessRequest(IInternalSoftPhone softPhone, SipRequestEvent requestEvent) { string method = requestEvent.Request.RequestLine.Method; if (method != SipMethods.Cancel) { if (_logger.IsDebugEnabled) _logger.Debug("Received request: '{0}'. Request ignored.", method); return; } if (_logger.IsInfoEnabled) _logger.Info("'CANCEL' received. Start processing..."); #region attempt to match transaction /*terminate pending invite with 487 (assumption: PendingInvite.OriginalRequest= requestEvent.ServerTransaction.Request)*/ if (_logger.IsDebugEnabled) _logger.Debug("Attempting to match 'CANCEL' target-tx against a tx in the ServerTransactionTable..."); var txIdAttempts = CreateTxIdAttempts(requestEvent.Request); ISipServerTransaction serverTransaction = null; foreach (var txIdAttempt in txIdAttempts) { serverTransaction = softPhone.SipProvider.FindServerTransactionById(txIdAttempt); if(serverTransaction !=null) break; } #endregion if (serverTransaction == null) { #region no match if (_logger.IsDebugEnabled) _logger.Debug("Could not match 'CANCEL' to an existing transaction. Sending x487 response..."); var cancelResponse = requestEvent.Request.CreateResponse(SipResponseCodes.x481_Call_Transaction_Does_Not_Exist); var cancelTx = softPhone.SipProvider.CreateServerTransaction(requestEvent.Request); cancelTx.SendResponse(cancelResponse); requestEvent.IsSent = true; if (_logger.IsDebugEnabled) _logger.Debug("x487 response send."); #endregion } else { #region matched #region respond to cancel with ok if (_logger.IsDebugEnabled) _logger.Debug("'CANCEL' target-tx matched. Answering to cancel with ok..."); var cancelOkResponse = requestEvent.Request.CreateResponse(SipResponseCodes.x200_Ok); var cancelOkTx = softPhone.SipProvider.CreateServerTransaction(requestEvent.Request); cancelOkTx.SendResponse(cancelOkResponse); requestEvent.IsSent = true; if (_logger.IsDebugEnabled) _logger.Debug("Answered."); #endregion #region respond to matched tx with x487 if (serverTransaction.GetId() != softPhone.PendingInvite.InviteServerTransaction.GetId()) { if (_logger.IsInfoEnabled) _logger.Info("'CANCEL' target-tx does NOT match 'INVITE.' Processing ABORTED. The 'CANCEL' target-tx is expected, to match only to the pending 'INVITE' servertransaction."); } else { if (_logger.IsDebugEnabled) _logger.Debug("Creating '487-Request terminated' response and sending..."); var requestToCancel = serverTransaction.Request; var terminateResponse = requestToCancel.CreateResponse(SipResponseCodes.x487_Request_Terminated); /*terminate pending invite.*/ softPhone.PendingInvite.InviteServerTransaction.SendResponse(terminateResponse); if (_logger.IsDebugEnabled) _logger.Debug("Response send."); if (_logger.IsDebugEnabled) _logger.Debug("Changing callstate to 'CANCELLED'."); softPhone.PendingCall.RaiseCallStateChanged(CallState.Cancelled); if (_logger.IsInfoEnabled) _logger.Info("'CANCEL' Processed. Transitioning (back) to 'Idle'"); softPhone.ChangeState(softPhone.StateProvider.GetIdle()); } #endregion #endregion } }
public void ProcessRequest(IInternalSoftPhone softPhone, Sip.Stack.SipRequestEvent requestEvent) { string method = requestEvent.Request.RequestLine.Method; _logger.Debug("processing request: {0} ...", method); if (method != SipMethods.Bye) { if (_logger.IsDebugEnabled) { _logger.Debug("Received request: '{0}'. Request ignored.", method); } return; } if (_logger.IsInfoEnabled) { _logger.Info("'BYE' received. Begin processing..."); } if (requestEvent.Dialog == null) { if (_logger.IsInfoEnabled) { _logger.Info("Processing ABORTED. A 'BYE' RequestEvent is expected to have a 'NOT NULL' dialog. DebugInfo: DialogId created from BYE: '{0}'. This Id could not be matched to a dialog in the provider's dialogtable.", SipProvider.GetDialogId(requestEvent.Request, true)); } return; } if (requestEvent.Dialog.GetId() != softPhone.PendingInvite.Dialog.GetId()) { if (_logger.IsInfoEnabled) { _logger.Info("Processing ABORTED. The 'BYE' RequestEvent.Dialog, is expected to match only to the Dialog of the PendingInvite. DebugInfo: DialogId created from BYE: '{0}'. This case is not supposed to occur, since the phone can only process ONE dialog at a time. Check what's going on !!", SipProvider.GetDialogId(requestEvent.Request, true)); } return; } if (_logger.IsDebugEnabled) { _logger.Debug("Sending OK response to BYE.."); } var okResponse = requestEvent.Request.CreateResponse(SipResponseCodes.x200_Ok); var tx = softPhone.SipProvider.CreateServerTransaction(requestEvent.Request); tx.SendResponse(okResponse); requestEvent.IsSent = true; softPhone.PendingInvite.Dialog.Terminate(); softPhone.PendingCall.RaiseCallStateChanged(CallState.Completed); if (_logger.IsDebugEnabled) { _logger.Debug("OK Send."); } if (_logger.IsInfoEnabled) { _logger.Info("Transitioning to 'IDLE'..."); } softPhone.ChangeState(softPhone.StateProvider.GetIdle()); }
public void ProcessResponse(IInternalSoftPhone softPhone, Sip.Stack.SipResponseEvent responseEvent) { SipStatusLine statusLine = responseEvent.Response.StatusLine; _logger.Debug("processing response: {0} ...", statusLine.ResponseCode); if (statusLine.ResponseCode == SipResponseCodes.x100_Trying) { if (_logger.IsDebugEnabled) { _logger.Debug("'Trying' response received. Ignored"); } return; } int statusCodeDiv100 = statusLine.StatusCode / 100; if (_logger.IsInfoEnabled) { _logger.Info("'{0}XX' response. Begin processing...", statusCodeDiv100); } if (responseEvent.ClientTransaction == null) { if (_logger.IsInfoEnabled) { _logger.Info("Processing ABORTED. A '{0}XX' ResponseEvent is expected to have a 'NOT NULL' ClientTx. DebugInfo: TxId created from RESPONSE: '{1}'. This Id could not be matched to a clienttransaction in the provider's clienttransactiontable.", statusCodeDiv100, SipProvider.GetClientTransactionId(responseEvent.Response)); } return; } if (responseEvent.ClientTransaction.GetId() != softPhone.PendingInvite.InviteClientTransaction.GetId()) { if (_logger.IsInfoEnabled) { _logger.Info("Processing ABORTED. The '{0}XX' ResponseEvent.ClientTransaction, is expected to match only to the InviteSendTransaction of the PendingInvite. DebugInfo: TxId created from RESPONSE: '{1}'. This case is not supposed to occur, since the phone can only process ONE PendingInvite at a time. Check what's going on !!", statusCodeDiv100, SipProvider.GetClientTransactionId(responseEvent.Response)); } return; } if (responseEvent.Dialog == null) { if (_logger.IsInfoEnabled) { _logger.Info("Processing ABORTED. In this state the 'ResponseEvent' is expected to have a 'NOT NULL' dialog. DebugInfo: DialogId created from Response: '{0}'. This Id could not be matched to a dialog in the provider's dialogtable.", SipProvider.GetDialogId(responseEvent.Response, false)); } return; } if (responseEvent.Dialog.GetId() != softPhone.PendingInvite.Dialog.GetId()) { if (_logger.IsInfoEnabled) { _logger.Info("Processing ABORTED. In this state the 'ResponseEvent' it's Dialog, is expected to match only to the Dialog of the PendingInvite. DebugInfo: DialogId created from response: '{0}'. This case is not supposed to occur, since the phone can only process ONE dialog at a time. Check what's going on !!", SipProvider.GetDialogId(responseEvent.Response, false)); } return; } if (statusCodeDiv100 == 1) { /*go to wait for final*/ if (_logger.IsInfoEnabled) { _logger.Info("Transitioning to 'WAITFINAL'..."); } softPhone.ChangeState(softPhone.StateProvider.GetWaitFinal()); } else if (statusCodeDiv100 == 2) { if (_logger.IsInfoEnabled) { _logger.Info("Transitioning to 'ESTABLISHED'..."); } Check.IsTrue(responseEvent.Dialog is SipInviteClientDialog, "Failed to respond to '200' response with ACK request. The 'ACK' can not be created. The responseEvent.Dialog is expected to be of type SipInviteClientDialog."); var clientDialog = (SipInviteClientDialog)softPhone.PendingInvite.Dialog; var ack = clientDialog.CreateAck(); clientDialog.SendAck(ack); softPhone.ChangeState(softPhone.StateProvider.GetEstablished()); } else { //change callstate. don't go automatically to 'IDLE' state, but wait for the api user to invoke Call.Stop() if (statusLine.ResponseCode == SipResponseCodes.x486_Busy_Here) { if (_logger.IsDebugEnabled) { _logger.Debug("Changing CallState to 'BusyHere'"); } softPhone.PendingCall.RaiseCallStateChanged(CallState.BusyHere); } else { if (_logger.IsDebugEnabled) { _logger.Debug("Changing CallState to 'Error'"); } softPhone.PendingCall.RaiseCallErrorOccured(CallError.SipResponse, statusLine.ResponseCode); softPhone.PendingCall.RaiseCallStateChanged(CallState.Error); } softPhone.PendingInvite.Dialog.Terminate(); softPhone.ChangeState(softPhone.StateProvider.GetIdle()); } }
public void ProcessResponse(IInternalSoftPhone softPhone, Sip.Stack.SipResponseEvent responseEvent) { SipStatusLine statusLine = responseEvent.Response.StatusLine; _logger.Debug("processing response: {0} ...", statusLine.ResponseCode); int statusCodeDiv100 = statusLine.StatusCode / 100; if (responseEvent.ClientTransaction == null) { if (_logger.IsInfoEnabled) { _logger.Info("Processing ABORTED. In this state, the ResponseEvent is expected to have a 'NOT NULL' ClientTx. DebugInfo: TxId created from RESPONSE: '{1}'. This Id could not be matched to a clienttransaction in the provider's clienttransactiontable.", statusCodeDiv100, SipProvider.GetClientTransactionId(responseEvent.Response)); } return; } /*wait for ok on cancel + 487 for invite*/ if (_logger.IsInfoEnabled) { _logger.Info("'{0}XX' response. Begin processing...", statusCodeDiv100); } if (statusCodeDiv100 < 2) { if (_logger.IsInfoEnabled) { _logger.Info("Processing ABORTED. Only FINAL (x200-x500) responses are processed in this state."); } return; } if (responseEvent.ClientTransaction.GetId() == softPhone.PendingInvite.CancelTransaction.GetId()) { _receivedFinalCancelStatusCode = responseEvent.Response.StatusLine.StatusCode; if (_logger.IsInfoEnabled) { _logger.Info("Received final response on 'CANCEL' request. StatusCode: {0}", _receivedFinalCancelStatusCode); } } if (responseEvent.ClientTransaction.GetId() == softPhone.PendingInvite.InviteClientTransaction.GetId()) { if (_logger.IsInfoEnabled) { _logger.Info("Received final response on 'INVITE' request."); } _receivedFinalInviteResponse = true; if (_logger.IsDebugEnabled) { _logger.Debug("Terminating the Dialog..."); } softPhone.PendingInvite.Dialog.Terminate(); if (_logger.IsDebugEnabled) { _logger.Debug("Dialog terminated."); } } //TODO: use locks. if (_receivedFinalCancelStatusCode == 481 || /*when cancel-tx x481 is received, the invite will NOT receive a final response. => go to idle immediately*/ (_receivedFinalCancelStatusCode == 200 && _receivedFinalInviteResponse)) /*when cancel-tx x200 is received, the invite will receive a final response. => wait for x487 before going to idle*/ { if (_logger.IsDebugEnabled) { _logger.Debug("Changing CallState to 'Cancelled'"); } softPhone.PendingCall.RaiseCallStateChanged(CallState.Cancelled); /*go to idle*/ if (_logger.IsDebugEnabled) { _logger.Debug("Both 'CANCEL' & 'INVITE' Tx have received a final response. Transitioning to Idle..."); } softPhone.ChangeState(softPhone.StateProvider.GetIdle()); } }
public void Initialize(IInternalSoftPhone softPhone) { _state.Initialize(softPhone); _afterInitialized(softPhone);//TODO: rename }