public First ( string name ) : SIPLib.SIP.Header | ||
name | string | The name. |
return | SIPLib.SIP.Header |
/// <summary> /// Creates the transaction branch ID. /// </summary> /// <param name="request">The request (can be a SIP message or a Dictionary with the necessary headers).</param> /// <param name="server">if set to <c>true</c> [server].</param> /// <returns>System.String.</returns> public static string CreateBranch(object request, bool server) { string to = "", from = "", callId = "", cSeq = ""; if (request is Message) { Message requestMessage = (Message)(request); to = requestMessage.First("To").Value.ToString(); from = requestMessage.First("From").Value.ToString(); callId = requestMessage.First("Call-ID").Value.ToString(); cSeq = requestMessage.First("CSeq").Number.ToString(); } else if (request is Dictionary <string, object> ) { Dictionary <string, object> dict = (Dictionary <string, object>)request; object[] headers = dict.Values.ToArray(); to = headers[0].ToString(); from = headers[1].ToString(); callId = headers[2].ToString(); cSeq = headers[3].ToString(); } string data = to.ToLower() + "|" + from.ToLower() + "|" + callId.ToLower() + "|" + cSeq.ToLower() + "|" + server.ToString(); using (MD5 md5Hash = MD5.Create()) { string hash = Helpers.GetMd5Hash(md5Hash, data); } //TODO fix this ? replace data with hash ? data = Helpers.Base64Encode(data).Replace('=', '.'); return("z9hG4bK" + data); }
public void ProcessMessage(Message request) { if (request.First("Content-Type").ToString().ToUpper().Contains("TEXT/PLAIN")) { try { if (MessageRecievedEvent != null) { MessageRecievedEvent(this, new MessageReceivedArgs(request.First("From").Value.ToString(), request.Body)); } } catch (Exception exception) { MessageBox.Show("Error in handling IM Message : " + exception.Message); } } else if (request.First("Content-Type").ToString().ToUpper().Equals("APPLICATION/IM-ISCOMPOSING+XML")) { try { if (TypingMessageRecievedEvent != null) { TypingMessageRecievedEvent(this, new TypingMessageRecievedArgs(request.First("From").Value.ToString(), request.Body)); } } catch (Exception exception) { MessageBox.Show("Error in handling IM Message : " + exception.Message); } } }
/// <summary> /// Creates the server side dialog. /// </summary> /// <param name="stack">The stack.</param> /// <param name="request">The request.</param> /// <param name="response">The response.</param> /// <param name="transaction">The transaction.</param> /// <returns>Dialog.</returns> public static Dialog CreateServer(SIPStack stack, Message request, Message response, Transaction transaction) { Dialog d = new Dialog(stack, request, true) { Request = request }; if (request.Headers.ContainsKey("Record-Route")) { d.RouteSet = request.Headers["Record-Route"]; foreach (Header h in d.RouteSet) { h.Name = "Route"; } } // TODO: Handle multicast addresses // TODO: Handle tls / secure sip d.LocalSeq = 0; d.RemoteSeq = request.First("CSeq").Number; d.CallID = request.First("Call-ID").Value.ToString(); d.LocalTag = response.First("To").Attributes["tag"]; d.RemoteTag = request.First("From").Attributes["tag"]; d.LocalParty = new Address(request.First("To").Value.ToString()); d.RemoteParty = new Address(request.First("From").Value.ToString()); d.RemoteTarget = new SIPURI(((Address)(request.First("Contact").Value)).Uri.ToString()); // TODO: retransmission timer for 2xx in UAC stack.Dialogs[d.CallID] = d; return(d); }
/// <summary> /// Creates a client transaction /// </summary> /// <param name="stack">The SIP stack to use.</param> /// <param name="app">The associated useragent / application.</param> /// <param name="request">The SIP request.</param> /// <param name="transport">A TransportInfo object representing transmission medium.</param> /// <param name="remote">The remote.</param> /// <returns>Transaction.</returns> public static Transaction CreateClient(SIPStack stack, UserAgent app, Message request, TransportInfo transport, string remote) { Transaction t; lock (stack.TransactionLock) { if (request.Method == "INVITE") { t = new InviteClientTransaction(app); } else { t = new ClientTransaction(app); } t.Stack = stack; t.App = app; t.Request = request; t.Transport = transport; t.Remote = remote; if (request.Headers.ContainsKey("Via") && request.First("Via").Attributes.ContainsKey("branch")) { t.Branch = request.First("Via").Attributes["branch"]; } else { t.Branch = CreateBranch(request, false); } t.ID = CreateId(t.Branch, request.Method); stack.Transactions[t.ID] = t; if (request.Method == "INVITE") { ((InviteClientTransaction)t).Start(); } else { ((ClientTransaction)t).Start(); } } return(t); }
//private void start() //{ // //TODO Transaction start ? // //throw new NotImplementedException(); //} /// <summary> /// Helper function to check whether two Transactions are equal. /// </summary> /// <param name="t1">The first transaction.</param> /// <param name="r">A SIP message to help the comparison.</param> /// <param name="t2">The second transaction.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> public static bool TEquals(Transaction t1, Message r, Transaction t2) { Message t = t1.Request; Address requestTo = (Address)(r.First("To").Value); Address t1To = (Address)(t.First("To").Value); Address requestFrom = (Address)(r.First("To").Value); Address t1From = (Address)(t.First("To").Value); bool a = (String.Compare(requestTo.Uri.ToString(), t1To.Uri.ToString()) == 0); a = a && (String.Compare(requestFrom.Uri.ToString(), t1From.Uri.ToString()) == 0); a = a && (r.First("Call-ID").Value.ToString() == t.First("Call-ID").Value.ToString()); a = a && (r.First("CSeq").Number.ToString() == t.First("CSeq").Number.ToString()); a = a && (r.First("From").Attributes["tag"] == t.First("From").Attributes["tag"]); a = a && (t2.Server == t1.Server); return(a); }
/// <summary> /// Creates the client side dialog. /// </summary> /// <param name="stack">The stack.</param> /// <param name="request">The request.</param> /// <param name="response">The response.</param> /// <param name="transaction">The transaction.</param> /// <returns>Dialog.</returns> public static Dialog CreateClient(SIPStack stack, Message request, Message response, Transaction transaction) { Dialog d = new Dialog(stack, request, false) { Request = request }; if (response.Headers.ContainsKey("Record-Route")) { d.RouteSet = response.Headers["Record-Route"]; d.RouteSet.Reverse(); foreach (Header h in d.RouteSet) { h.Name = "Route"; } } d.LocalSeq = request.First("CSeq").Number; d.RemoteSeq = 0; d.CallID = request.First("Call-ID").Value.ToString(); d.LocalTag = request.First("From").Attributes["tag"]; d.RemoteTag = response.First("To").Attributes["tag"]; d.LocalParty = new Address(request.First("From").Value.ToString()); d.RemoteParty = new Address(request.First("To").Value.ToString()); if (response.Headers.ContainsKey("Contact")) { d.RemoteTarget = new SIPURI(((Address)(response.First("Contact").Value)).Uri.ToString()); } else { d.RemoteTarget = new SIPURI(((Address)(response.First("To").Value)).Uri.ToString()); } try { stack.Dialogs[d.CallID] = d; } catch (Exception) { Debug.Assert(false, "Error assiging callID to stack dialog list"); } return(d); }
/// <summary> /// Creates a server transaction /// </summary> /// <param name="stack">The SIP stack to use.</param> /// <param name="app">The associated useragent / application.</param> /// <param name="request">The SIP request.</param> /// <param name="transport">A TransportInfo object representing transmission medium.</param> /// <param name="tag">The tag.</param> /// <param name="start">Not used.</param> /// <returns>Transaction.</returns> public static Transaction CreateServer(SIPStack stack, UserAgent app, Message request, TransportInfo transport, string tag, Boolean start = true) { Transaction t; if (request.Method == "INVITE") { t = new InviteServerTransaction(app); } else { t = new ServerTransaction(app); } t.Stack = stack; t.App = app; t.Request = request; t.Transport = transport; t.Tag = tag; t.Remote = request.First("Via").ViaUri.HostPort(); if (request.Headers.ContainsKey("Via") && request.First("Via").Attributes.ContainsKey("branch")) { t.Branch = request.First("Via").Attributes["branch"]; } else { t.Branch = CreateBranch(request, true); } t.ID = CreateId(t.Branch, request.Method); stack.Transactions[t.ID] = t; if (request.Method == "INVITE") { ((InviteServerTransaction)t).Start(); } else { ((ServerTransaction)t).Start(); } return(t); }
/// <summary> /// Extracts the call ID from a message. /// </summary> /// <param name="m">The m.</param> /// <returns>System.String.</returns> public static string ExtractID(Message m) { // TODO fix this and use more than just call id ? string temp = m.First("Call-ID").Value.ToString(); // +"|"; //if (m.method != null && m.method.Length > 0) //{ // temp = temp + m.first("To").attributes["tag"] + "|"; // temp = temp + m.first("From").attributes["tag"]; //} //else //{ // temp = temp + m.first("From").attributes["tag"] + "|"; // temp = temp + m.first("To").attributes["tag"] + "|"; //} return(temp); }
/// <summary> /// Creates a SIP request message based on the passed in parameters. /// </summary> /// <param name="method">The SIP method to use.</param> /// <param name="uri">The destination URI used in the first line.</param> /// <param name="headers">The SIP headers.</param> /// <param name="content">The SIP body content.</param> /// <returns>Message.</returns> public static Message CreateRequest(string method, SIPURI uri, Dictionary <string, List <Header> > headers = null, string content = "") { Message m = new Message { Method = method, Uri = uri, Protocol = "SIP/2.0" }; m = PopulateMessage(m, headers, content); if (m.Headers.ContainsKey("CSeq")) { Header cseq = new Header(m.First("CSeq").Number.ToString() + " " + method, "CSeq"); List <Header> cseqHeaders = new List <Header> { cseq }; m.Headers["CSeq"] = cseqHeaders; } return(m); }
public void ProcessRequest(Message request) { if (request.Method.ToUpper().Contains("NOTIFY")) { if (request.Headers.ContainsKey("Content-Length")) { if (request.Body.Length > 0) { try { XDocument xDoc = XDocument.Parse(request.Body.Trim()); string basic = ""; string note = ""; foreach (XElement xElement in xDoc.Descendants()) { switch (xElement.Name.ToString()) { case "{urn:ietf:params:xml:ns:pidf}basic": basic = xElement.Value; break; case "{urn:ietf:params:xml:ns:pidf}note": note = xElement.Value; break; } } if (PresenceChangedEvent != null) { string contact = request.First("From").Value.ToString(); contact = contact.Replace("<",""); contact = contact.Replace(">",""); PresenceChangedEvent(this, new PresenceChangedArgs(contact, basic, note)); } } catch (Exception exception) { MessageBox.Show("Error in handling presence xml: " + exception.Message); } } } } }
/// <summary> /// Creates a proxy branch. /// </summary> /// <param name="request">The request.</param> /// <param name="server">if set to <c>true</c> [server].</param> /// <returns>System.String.</returns> internal static string createProxyBranch(Message request, bool server) { Header via = request.First("Via"); if (via != null && via.Attributes.ContainsKey("branch")) { string data = via.Attributes["branch"]; using (MD5 md5Hash = MD5.Create()) { string hash = Helpers.GetMd5Hash(md5Hash, data); } //TODO fix this ? replace data with hash ? data = Helpers.Base64Encode(data).Replace('=', '.'); return("z9hG4bK" + data); } else { return(CreateBranch(request, server)); } }
/// <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); } }
private static void RouteNewMessage(Message request, Proxy pua) { SIPURI to = request.Uri; string toID = to.User + "@" + to.Host; Address from = (Address)(request.First("From").Value); string fromID = from.Uri.User + "@" + from.Uri.Host; List<ServiceFlow> toUserFlows = GetUserBlocks(toID); List<ServiceFlow> fromUserFlows = GetUserBlocks(fromID); Address dest = new Address(to.ToString()); foreach (ServiceFlow serviceFlow in toUserFlows) { if (serviceFlow.Blocks.Count > 0) { Block firstBlock = serviceFlow.Blocks[serviceFlow.FirstBlockGUID]; Address temp_dest = CheckServiceBlock(request, firstBlock, toID, fromID); if (temp_dest != null) { dest = temp_dest; break; } } else continue; } Message proxiedMessage = pua.CreateRequest(request.Method, dest, true, true); proxiedMessage.First("To").Value = dest; string callID = proxiedMessage.First("Call-ID").ToString(); ActiveFlow af = new ActiveFlow (); af.LastRequest = proxiedMessage; _activeFlows[callID] = af; pua.SendRequest(proxiedMessage); }
/// <summary> /// Authenticates the specified response. /// </summary> /// <param name="response">The response.</param> /// <param name="transaction">The transaction.</param> /// <returns><c>true</c> if attempt to authenticate is created, <c>false</c> otherwise</returns> public virtual bool Authenticate(Message response, Transaction transaction) { Header a; if (response.Headers.ContainsKey("WWW-Authenticate") || response.Headers.ContainsKey("Proxy-Authenticate")) { a = response.Headers["WWW-Authenticate"][0]; } else if (response.Headers.ContainsKey("Proxy-Authenticate")) { a = response.Headers["Proxy-Authenticate"][0]; } else return false; Message request = new Message(transaction.Request.ToString()); bool resend = false, present = false; // foreach (Header h in request.headers["Authorization"].Concat(request.headers["Proxy-Authorization"])) foreach (Header h in request.Headers["Authorization"]) { try { if (a.Attributes["realm"] == h.Attributes["realm"] && (a.Name == "WWW-Authenticate" && h.Name == "Authorization" || a.Name == "Proxy-Authenticate" && h.Name == "Proxy-Authorization")) { present = true; break; } } catch (Exception e) { } } if (!present && a.Attributes.ContainsKey("realm")) { string[] result = Stack.Authenticate(this, a); if (result.Length == 0 || a.Attributes.ContainsKey("password") && a.Attributes.ContainsKey("hashValue")) { return false; } //string value = createAuthorization(a.value, a.attributes["username"], a.attributes["password"], request.uri.ToString(), this.request.method, this.request.body, this.auth); string value = SIP.Authenticate.CreateAuthorization(a.ToString(), result[0], result[1], request.Uri.ToString(), request.Method, request.Body, Auth); if (value.Length > 0) { request.InsertHeader( a.Name == "WWW-Authenticate" ? new Header(value, "Authorization") : new Header(value, "Proxy-Authorization")); resend = true; } } if (resend) { LocalSeq = request.First("CSeq").Number + 1; request.InsertHeader(new Header(LocalSeq.ToString() + " " + request.Method, "CSeq")); //TODO FIX? //request.headers["Via"][0].attributes["branch"] = Transaction.createBranch(request, false); Request = request; Transaction = Transaction.CreateClient(Stack, this, Request, transaction.Transport, transaction.Remote); return true; } return false; }
/// <summary> /// Sends the SIP request. /// </summary> /// <param name="request">The request.</param> public override void SendRequest(Message request) { SIPURI target = null; if (request.First("Route") == null) { target = request.Uri; } else { var routes = request.Headers["Route"]; if (routes.Count > 0) { try { target = ((Address)routes[0].Value).Uri; string test = target.Parameters["lr"]; } catch (Exception) { routes.RemoveAt(0); if (routes.Count > 0) { routes.Add(new Header(request.Uri.ToString(), "Route")); } request.Headers["Route"] = routes; request.Uri = target; } } } Stack.Sending(this, request); ProxyBranch branch = new ProxyBranch(); SIPURI dest = target.Dup(); if (target.Port <= 0) { dest.Port = 5060; } else { dest.Port = target.Port; } if (!Helpers.IsIPv4(dest.Host)) { try { IPAddress[] addresses = Dns.GetHostAddresses(dest.Host); dest.Host = addresses[0].ToString(); } catch (Exception) { } } if (Helpers.IsIPv4(dest.Host)) { branch.RemoteCandidates = new List<SIPURI> { dest }; } if (branch.RemoteCandidates == null || branch.RemoteCandidates.Count == 0) { Error(null, "Cannot resolve DNS target"); return; } target = branch.RemoteCandidates.First(); branch.RemoteCandidates.RemoveAt(0); if (!request.Method.ToUpper().Contains("ACK")) { branch.Transaction = Transaction.CreateClient(Stack, this, request, Stack.Transport, target.HostPort()); branch.Request = request; _branches.Add(branch); } else { Stack.Send(request, target.HostPort()); } }
private static void RouteNewMessage(Message request, Proxy pua) { SIPURI to = request.Uri; string toID = to.User + "@" + to.Host; Address from = (Address)(request.First("From").Value); string fromID = from.Uri.User + "@" + from.Uri.Host; Address dest = new Address(to.ToString()); Message proxiedMessage = pua.CreateRequest(request.Method, dest, true, true); proxiedMessage.First("To").Value = dest; pua.SendRequest(proxiedMessage); }
/// <summary> /// Authenticates the specified response. /// </summary> /// <param name="response">The response.</param> /// <param name="transaction">The transaction.</param> /// <returns><c>true</c> if attempt to authenticate is created, <c>false</c> otherwise</returns> public virtual bool Authenticate(Message response, Transaction transaction) { Header a; if (response.Headers.ContainsKey("WWW-Authenticate") || response.Headers.ContainsKey("Proxy-Authenticate")) { a = response.Headers["WWW-Authenticate"][0]; } else if (response.Headers.ContainsKey("Proxy-Authenticate")) { a = response.Headers["Proxy-Authenticate"][0]; } else { return(false); } Message request = new Message(transaction.Request.ToString()); bool resend = false, present = false; // foreach (Header h in request.headers["Authorization"].Concat(request.headers["Proxy-Authorization"])) foreach (Header h in request.Headers["Authorization"]) { try { if (a.Attributes["realm"] == h.Attributes["realm"] && (a.Name == "WWW-Authenticate" && h.Name == "Authorization" || a.Name == "Proxy-Authenticate" && h.Name == "Proxy-Authorization")) { present = true; break; } } catch (Exception e) { } } if (!present && a.Attributes.ContainsKey("realm")) { string[] result = Stack.Authenticate(this, a); if (result.Length == 0 || a.Attributes.ContainsKey("password") && a.Attributes.ContainsKey("hashValue")) { return(false); } //string value = createAuthorization(a.value, a.attributes["username"], a.attributes["password"], request.uri.ToString(), this.request.method, this.request.body, this.auth); string value = SIP.Authenticate.CreateAuthorization(a.ToString(), result[0], result[1], request.Uri.ToString(), request.Method, request.Body, Auth); if (value.Length > 0) { request.InsertHeader( a.Name == "WWW-Authenticate" ? new Header(value, "Authorization") : new Header(value, "Proxy-Authorization")); resend = true; } } if (resend) { LocalSeq = request.First("CSeq").Number + 1; request.InsertHeader(new Header(LocalSeq.ToString() + " " + request.Method, "CSeq")); //TODO FIX? //request.headers["Via"][0].attributes["branch"] = Transaction.createBranch(request, false); Request = request; Transaction = Transaction.CreateClient(Stack, this, Request, transaction.Transport, transaction.Remote); return(true); } return(false); }
private static bool callerIsBlacklisted(Message request) { return !request.First("From").ToString().ToLower().Contains("bob"); }
/// <summary> /// Creates a SIP request message based on the passed in parameters. /// </summary> /// <param name="method">The SIP method to use.</param> /// <param name="uri">The destination URI used in the first line.</param> /// <param name="headers">The SIP headers.</param> /// <param name="content">The SIP body content.</param> /// <returns>Message.</returns> public static Message CreateRequest(string method, SIPURI uri, Dictionary<string, List<Header>> headers = null, string content = "") { Message m = new Message {Method = method, Uri = uri, Protocol = "SIP/2.0"}; m = PopulateMessage(m, headers, content); if (m.Headers.ContainsKey("CSeq")) { Header cseq = new Header(m.First("CSeq").Number.ToString() + " " + method, "CSeq"); List<Header> cseqHeaders = new List<Header> {cseq}; m.Headers["CSeq"] = cseqHeaders; } return m; }
private static Address RouteService(Message request, Block Block, string toId, string fromId) { string callID = request.First("Call-ID").ToString(); if (_activeFlows.ContainsKey(callID)) { ActiveFlow af = _activeFlows[callID]; af.LastRequest = request; af.LastBlock = Block; } else { ActiveFlow af = new ActiveFlow(); af.OriginalRequest = request; af.LastRequest = request; af.LastBlock = Block; _activeFlows.Add(callID,af); } Address dest = new Address(Block.DestURI); return dest; }
/// <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; } }
private static void LogCallDetails(Message request) { // Stub for logging call details DebugLog.Info("Received call from "+request.First("From")); }
private static void CheckReceivedResponse(Message response, Proxy pua) { string callID = response.First("Call-ID").ToString(); if (_activeFlows.ContainsKey(callID)) { ActiveFlow af = _activeFlows[callID]; Block lastBlock = af.LastBlock; if (lastBlock != null && lastBlock.NextBlocks.Count > 0) { foreach (string code in lastBlock.NextBlocks.Keys) { if ((response.ResponseCode.ToString().Contains("183") && code.Contains("181")) || code.Contains(response.ResponseCode.ToString())) { Block NextBlock = lastBlock.NextBlocks[code]; Message newRequest = af.LastRequest; Header CSeq = newRequest.First("CSeq"); CSeq.Number++; newRequest.InsertHeader(CSeq); RouteNewResponse(response, pua); if (NextBlock.NextBlocks.Count > 0) { ContinueRoutingMessage(newRequest, pua, NextBlock); } } } } else { RouteNewResponse(response, pua); } } else { RouteNewResponse(response, pua); } }
public override void ReceivedRequest(Transaction transaction, Message request) { //try //{ if ((transaction != null) && Transaction != null && Transaction != transaction && request.Method.ToUpper() != "CANCEL") { Debug.Assert(false, "Invalid transaction for received request"); } Server = true; if (!request.Uri.Scheme.ToLower().Equals("sip")) { SendResponse(416, "Unsupported URI scheme"); return; } if (request.First("Max-Forwards") != null && int.Parse(request.First("Max-Forwards").Value.ToString()) < 0) { SendResponse(483, "Too many hops"); return; } if (!request.Headers["To"][0].Attributes.ContainsKey("tag") && transaction != null) { if (Stack.FindOtherTransactions(request, transaction) != null) { //SendResponse(482, "Loop detected - found another transaction"); return; } } if (request.First("Proxy-Require") != null) { if (!request.Method.ToUpper().Contains("CANCEL") && !request.Method.ToUpper().Contains("ACK")) { Message response = CreateResponse(420, "Bad extension"); Header unsupported = request.First("Proxy-Require"); unsupported.Name = "Unsupported"; response.InsertHeader(unsupported); SendResponse(unsupported); return; } } if (transaction != null) { Transaction = transaction; } if (request.Method.ToUpper() == "CANCEL") { string branch; if (request.First("Via") != null && request.First("Via").Attributes.ContainsKey("branch")) { branch = request.First("Via").Attributes["branch"]; } else { branch = Transaction.CreateBranch(request, true); } Transaction original = Stack.FindTransaction(Transaction.CreateId(branch, "INVITE")); if (original != null) { if (original.State == "proceeding" || original.State == "trying") { original.SendResponse(original.CreateResponse(487, "Request terminated")); } transaction = Transaction.CreateServer(Stack, this, request, Stack.Transport, Stack.Tag, false); transaction.SendResponse(transaction.CreateResponse(200, "OK")); } SendCancel(); return; } if (string.IsNullOrEmpty(request.Uri.User) && IsLocal(request.Uri) && request.Uri.Parameters != null && request.First("Route") != null) { Header lastRoute = request.Headers["Route"].Last(); request.Headers["Route"].RemoveAt(request.Headers["Route"].Count - 1); request.Uri = ((Address)(lastRoute.Value)).Uri; } if (request.First("Route") != null && IsLocal(((Address)(request.First("Route").Value)).Uri)) { request.Headers["Route"].RemoveAt(0); request.had_lr = true; } Stack.ReceivedRequest(this, request); //} //catch (Exception) //{ // throw; //} }
public override void ReceivedRequest(Transaction transaction, Message request) { //try //{ if ((transaction != null) && Transaction != null && Transaction != transaction && request.Method.ToUpper() != "CANCEL") { Debug.Assert(false, "Invalid transaction for received request"); } Server = true; if (!request.Uri.Scheme.ToLower().Equals("sip")) { SendResponse(416, "Unsupported URI scheme"); return; } if (request.First("Max-Forwards") != null && int.Parse(request.First("Max-Forwards").Value.ToString()) < 0) { SendResponse(483, "Too many hops"); return; } if (!request.Headers["To"][0].Attributes.ContainsKey("tag") && transaction != null) { if (Stack.FindOtherTransactions(request, transaction) != null) { //SendResponse(482, "Loop detected - found another transaction"); return; } } if (request.First("Proxy-Require") != null) { if (!request.Method.ToUpper().Contains("CANCEL") && !request.Method.ToUpper().Contains("ACK")) { Message response = CreateResponse(420, "Bad extension"); Header unsupported = request.First("Proxy-Require"); unsupported.Name = "Unsupported"; response.InsertHeader(unsupported); SendResponse(unsupported); return; } } if (transaction != null) { Transaction = transaction; } if (request.Method.ToUpper() == "CANCEL") { string branch; if (request.First("Via") != null && request.First("Via").Attributes.ContainsKey("branch")) { branch = request.First("Via").Attributes["branch"]; } else { branch = Transaction.CreateBranch(request, true); } Transaction original = Stack.FindTransaction(Transaction.CreateId(branch, "INVITE")); if (original != null) { if (original.State == "proceeding" || original.State == "trying") { original.SendResponse(original.CreateResponse(487, "Request terminated")); } transaction = Transaction.CreateServer(Stack, this, request, Stack.Transport, Stack.Tag, false); transaction.SendResponse(transaction.CreateResponse(200, "OK")); } SendCancel(); return; } if (string.IsNullOrEmpty(request.Uri.User) && IsLocal(request.Uri) && request.Uri.Parameters != null && request.First("Route") != null) { Header lastRoute = request.Headers["Route"].Last(); request.Headers["Route"].RemoveAt(request.Headers["Route"].Count - 1); request.Uri = ((Address)(lastRoute.Value)).Uri; } if (request.First("Route") != null && IsLocal(((Address)(request.First("Route").Value)).Uri)) { request.Headers["Route"].RemoveAt(0); request.had_lr = true; } Stack.ReceivedRequest(this, request); //} //catch (Exception) //{ // throw; //} }
private static void ContinueRoutingMessage(Message request, Proxy pua, Block block) { SIPURI to = request.Uri; string toID = to.User + "@" + to.Host; Address from = (Address)(request.First("From").Value); string fromID = from.Uri.User + "@" + from.Uri.Host; Address dest = new Address(to.ToString()); Address temp_dest = CheckServiceBlock(request, block, toID, fromID); if (temp_dest != null) { dest = temp_dest; } if (dest.ToString().Contains("anonymous.invalid")) { Message proxiedMessage = pua.CreateResponse(403, "Forbidden"); pua.SendResponse(proxiedMessage); } else { Message proxiedMessage = pua.CreateRequest(request.Method, dest, true, true); proxiedMessage.First("To").Value = dest; pua.SendRequest(proxiedMessage); } }
/// <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> /// Creates a SIP request. /// </summary> /// <param name="method">The SIP method.</param> /// <param name="dest">The dest (either Address or string[]).</param> /// <param name="stateless">if set to <c>true</c> [act as a stateless proxy].</param> /// <param name="recordRoute">if set to <c>true</c> [record the SIP route].</param> /// <param name="headers">The SIP headers to use.</param> /// <param name="route">The route.</param> /// <returns>Message.</returns> public Message CreateRequest(string method, object dest, bool stateless = false, bool recordRoute = false, Dictionary <string, List <Header> > headers = null, List <Header> route = null) { if (method != Request.Method) { Debug.Assert(false, "method in createRequest must be same as original UAS for proxy"); } Message request = Request.Dup(); if (!stateless && Transaction == null) { Transaction = Transaction.CreateServer(Stack, this, Request, Stack.Transport, Stack.Tag, false); } if (dest.GetType() == typeof(Address)) { request.Uri = ((Address)dest).Uri.Dup(); } else if (dest is string[]) { string[] destArray = (string[])dest; string scheme = request.Uri.Scheme; string user = request.Uri.User; request.Uri = new SIPURI { Scheme = scheme, User = user, Host = destArray[0], Port = int.Parse(destArray[1]) }; } else { Debug.Assert(false, "Dest in Proxy Create Request is not a String or Address"); //else: request.uri = dest.dup() } if (request.First("Max-Forwards") != null) { object value = request.First("Max-Forwards").Value; int currentValue = int.Parse(value.ToString()); currentValue = currentValue - 1; request.InsertHeader(new Header(currentValue.ToString(), "Max-Forwards")); } else { request.InsertHeader(new Header("70", "Max-Forwards")); } if (recordRoute) { Address rr = new Address(Stack.Uri.ToString()); rr.Uri.Parameters["lr"] = null; rr.MustQuote = true; request.InsertHeader(new Header(rr.ToString(), "Record-Route")); } if (headers != null) { request.Headers.Concat(headers).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); } if (route != null) { route.Reverse(); foreach (Header header in route) { request.InsertHeader(header); } } Header viaHeader = Stack.CreateVia(); viaHeader.Attributes["branch"] = Transaction.createProxyBranch(request, false); request.InsertHeader(viaHeader, "insert"); return(request); }
private static void CheckReceivedRequest(Message request, Proxy pua) { string callID = request.First("Call-ID").ToString(); if (_activeFlows.ContainsKey(callID)) { ActiveFlow af = _activeFlows[callID]; Block lastBlock = af.LastBlock; if (lastBlock.NextBlocks.Count > 0) { ContinueRoutingMessage(request, pua, lastBlock); } } else { RouteNewMessage(request, pua); } }
internal void AcceptCall(SDP sdp, Message IncomingCall) { foreach (UserAgent userAgent in Useragents.ToArray()) { if (userAgent.CallID == IncomingCall.First("Call-ID").Value.ToString()) { Message response = userAgent.CreateResponse(200, "OK"); response.InsertHeader(new Header("application/sdp", "Content-Type")); response.Body = sdp.ToString(); userAgent.SendResponse(response); } } }
/// <summary> /// Sends the SIP request. /// </summary> /// <param name="request">The request.</param> public override void SendRequest(Message request) { SIPURI target = null; if (request.First("Route") == null) { target = request.Uri; } else { var routes = request.Headers["Route"]; if (routes.Count > 0) { try { target = ((Address)routes[0].Value).Uri; string test = target.Parameters["lr"]; } catch (Exception) { routes.RemoveAt(0); if (routes.Count > 0) { routes.Add(new Header(request.Uri.ToString(), "Route")); } request.Headers["Route"] = routes; request.Uri = target; } } } Stack.Sending(this, request); ProxyBranch branch = new ProxyBranch(); SIPURI dest = target.Dup(); if (target.Port <= 0) { dest.Port = 5060; } else { dest.Port = target.Port; } if (!Helpers.IsIPv4(dest.Host)) { try { IPAddress[] addresses = Dns.GetHostAddresses(dest.Host); dest.Host = addresses[0].ToString(); } catch (Exception) { } } if (Helpers.IsIPv4(dest.Host)) { branch.RemoteCandidates = new List <SIPURI> { dest }; } if (branch.RemoteCandidates == null || branch.RemoteCandidates.Count == 0) { Error(null, "Cannot resolve DNS target"); return; } target = branch.RemoteCandidates.First(); branch.RemoteCandidates.RemoveAt(0); if (!request.Method.ToUpper().Contains("ACK")) { branch.Transaction = Transaction.CreateClient(Stack, this, request, Stack.Transport, target.HostPort()); branch.Request = request; _branches.Add(branch); } else { Stack.Send(request, target.HostPort()); } }