/// <summary> /// Sends a response based on this transaction. /// </summary> /// <param name="response">The response.</param> public override void SendResponse(Message response) { LastResponse = response; if (response.Is1XX()) { if (State == "proceeding") { Stack.Send(response, Remote, Transport); } } else if (response.Is2XX()) { if (State == "proceeding") { State = "terminated"; Stack.Send(response, Remote, Transport); } } else { if (State == "proceeding") { State = "completed"; if (!Transport.Reliable) { StartTimer("G", Timer.G()); } StartTimer("H", Timer.H()); Stack.Send(response, Remote, Transport); } } }
/// <summary> /// Triggered on receipt of a SIP response. /// </summary> /// <param name="transaction">The transaction.</param> /// <param name="response">The response.</param> public override void ReceivedResponse(Transaction transaction, Message response) { if (response.Is2XX() && response.Headers.ContainsKey("Contact") && transaction != null && transaction.Request.Method == "INVITE") { RemoteTarget = new SIPURI(((Address)(Request.First("Contact").Value)).Uri.ToString()); } if (!response.Is1XX()) { Clients.RemoveAll(x => x == transaction); } if (response.ResponseCode == 408 || response.ResponseCode == 481) { Close(); } if (response.ResponseCode == 401 || response.ResponseCode == 407) { if (Authenticate(response, transaction)) { Stack.ReceivedResponse(this, response); } } else if (transaction != null) { Stack.ReceivedResponse(this, response); } if (Autoack && response.Is2XX() && (transaction != null && transaction.Request.Method == "INVITE" || response.First("CSeq").Method == "INVITE")) { Message ack = CreateRequest("ACK"); SendRequest(ack); } }
/// <summary> /// Triggered on receipt of any responses. Updates state of transaction. /// </summary> /// <param name="response">The response.</param> public override void ReceivedResponse(Message response) { if (response.Is1XX()) { if (State == "calling") { State = "proceeding"; App.ReceivedResponse(this, response); } else if (State == "proceeding") { App.ReceivedResponse(this, response); } } else if (response.Is2XX()) { if (State == "calling" || State == "proceeding") { State = "terminated"; App.ReceivedResponse(this, response); } } else { if (State == "calling" || State == "proceeding") { State = "completed"; Stack.Send(CreateAck(response), Remote, Transport); App.ReceivedResponse(this, response); if (!Transport.Reliable) { StartTimer("D", Timer.D()); } else { Timeout("D", 0); } } else if (State == "completed") { Stack.Send(CreateAck(response), Remote, Transport); } } }
/// <summary> /// Handles the received response and passes it to the appropriate transaction or dialog for further handling. /// </summary> /// <param name="r">The received response.</param> /// <param name="uri">The SIP URI.</param> private void ReceivedResponse(Message r, SIPURI uri) { if (r.Headers.ContainsKey("Service-Route") && r.Is2XX() && r.First("CSeq").Method.Contains("REGISTER")) { ServiceRoute = r.Headers["Service-Route"]; foreach (Header h in ServiceRoute) { h.Name = "Route"; } } else if (r.Headers.ContainsKey("Record-Route") && r.Is2XX()) { // TODO: FIX This ? don't need to keep building record-route ? //InviteRecordRoute = r.Headers["Record-Route"]; //foreach (Header h in InviteRecordRoute) //{ // h.Name = "Route"; //} } if (!r.Headers.ContainsKey("Via")) { Debug.Assert(false, String.Format("No Via header in received response \n{0}\n", r)); return; } string branch = r.Headers["Via"][0].Attributes["branch"]; string method = r.Headers["CSeq"][0].Method; Transaction t = FindTransaction(Transaction.CreateId(branch, method)); if (t == null) { if ((method == "INVITE") && (r.Is2XX())) { _log.Debug("Looking for dialog with ID " + Dialog.ExtractID(r)); foreach (KeyValuePair<string, Dialog> keyValuePair in Dialogs) { _log.Debug("Current Dialogs " + keyValuePair.Key); } Dialog d = FindDialog(r); if (d == null) { Debug.Assert(false, String.Format("No transaction or dialog for 2xx of INVITE \n{0}\n", r)); return; } else { d.ReceivedResponse(null, r); } } else { Console.WriteLine("No Transaction for response...ignoring...."); //Debug.Assert(false, String.Format("No Transaction for response \n{0}\n", r.ToString())); return; } } else { t.ReceivedResponse(r); return; } }
/// <summary> /// Handles the received response and passes it to the appropriate transaction or dialog for further handling. /// </summary> /// <param name="r">The received response.</param> /// <param name="uri">The SIP URI.</param> private void ReceivedResponse(Message r, SIPURI uri) { if (r.Headers.ContainsKey("Service-Route") && r.Is2XX() && r.First("CSeq").Method.Contains("REGISTER")) { ServiceRoute = r.Headers["Service-Route"]; foreach (Header h in ServiceRoute) { h.Name = "Route"; } } else if (r.Headers.ContainsKey("Record-Route") && r.Is2XX()) { // TODO: FIX This ? don't need to keep building record-route ? //InviteRecordRoute = r.Headers["Record-Route"]; //foreach (Header h in InviteRecordRoute) //{ // h.Name = "Route"; //} } if (!r.Headers.ContainsKey("Via")) { Debug.Assert(false, String.Format("No Via header in received response \n{0}\n", r)); return; } string branch = r.Headers["Via"][0].Attributes["branch"]; string method = r.Headers["CSeq"][0].Method; Transaction t = FindTransaction(Transaction.CreateId(branch, method)); if (t == null) { if ((method == "INVITE") && (r.Is2XX())) { _log.Debug("Looking for dialog with ID " + Dialog.ExtractID(r)); foreach (KeyValuePair <string, Dialog> keyValuePair in Dialogs) { _log.Debug("Current Dialogs " + keyValuePair.Key); } Dialog d = FindDialog(r); if (d == null) { Debug.Assert(false, String.Format("No transaction or dialog for 2xx of INVITE \n{0}\n", r)); return; } else { d.ReceivedResponse(null, r); } } else { Console.WriteLine("No Transaction for response...ignoring...."); //Debug.Assert(false, String.Format("No Transaction for response \n{0}\n", r.ToString())); return; } } else { t.ReceivedResponse(r); return; } }
/// <summary> /// Determines whether this instance [can create a dialog] for the specified request. /// </summary> /// <param name="request">The request.</param> /// <param name="response">The response.</param> /// <returns><c>true</c> if this instance [can create a dialog] for the specified request; otherwise, <c>false</c>.</returns> public static bool CanCreateDialog(Message request, Message response) { return((response.Is2XX()) && ((request.Method == "INVITE") || (request.Method == "SUBSCRIBE"))); }
/// <summary> /// Determines whether this instance [can create a dialog] for the specified request. /// </summary> /// <param name="request">The request.</param> /// <param name="response">The response.</param> /// <returns><c>true</c> if this instance [can create a dialog] for the specified request; otherwise, <c>false</c>.</returns> public static bool CanCreateDialog(Message request, Message response) { return ((response.Is2XX()) && ((request.Method == "INVITE") || (request.Method == "SUBSCRIBE"))); }