/// <summary> /// Constructs a <b>Via</b> header from a transport type and sent-by value. /// </summary> /// <param name="transportType">The transport type.</param> /// <param name="sentBy">The sent-by value.</param> public SipViaValue(SipTransportType transportType, string sentBy) : base() { this.transportType = transportType; this.sentBy = sentBy; SetText(); }
/// <summary> /// Parses the value from the text passed. /// </summary> /// <param name="rawText">The input text.</param> internal override void Parse(string rawText) { base.Parse(rawText); int p, pEnd; string v; // I'm going to tolerate badly formatted Via headers. p = rawText.IndexOf('/'); if (p == -1) { return; } p = rawText.IndexOf('/', p + 1); if (p == -1) { return; } version = rawText.Substring(0, p).ToUpper(); p++; pEnd = rawText.IndexOfAny(whitespace, p); if (pEnd == -1) { return; } v = rawText.Substring(p, pEnd - p).Trim().ToUpper(); switch (v) { case "UDP": transportType = SipTransportType.UDP; break; case "TCP": transportType = SipTransportType.TCP; break; case "TLS": transportType = SipTransportType.TLS; break; default: return; } p = pEnd + 1; pEnd = rawText.IndexOf(';'); if (pEnd == -1) { sentBy = rawText.Substring(p).Trim(); } else { sentBy = rawText.Substring(p, pEnd - p).Trim(); } }
/// <summary> /// Constructs an instance from settings passed as explicit parameters. /// </summary> /// <param name="transportType">The desired <see cref="SipTransportType" />.</param> /// <param name="binding">The network binding to be associated with the transport.</param> /// <param name="bufferSize">Size of the transport socket's send and receive buffers (or 0 for a reasonable default).</param> public SipTransportSettings(SipTransportType transportType, NetworkBinding binding, int bufferSize) { this.TransportType = transportType; this.Binding = binding; this.BaseTimers = new SipBaseTimers(); if (bufferSize > 0) { this.BufferSize = bufferSize; } }
/// <summary> /// Constructs a SIP URI from the parameters passed. /// </summary> /// <param name="transportType">The transport type.</param> /// <param name="binding">The <see cref="NetworkBinding" />.</param> /// <remarks> /// Passing <paramref name="transportType"/> as <see cref="SipTransportType.TLS" /> /// will result in a <i>secure</i> URI. Passing <paramref name="transportType"/> as /// <see cref="SipTransportType.TCP" /> will return a URI with a <b>transport=tcp</b> /// parameter. /// </remarks> public SipUri(SipTransportType transportType, NetworkBinding binding) { this.isSecure = transportType == SipTransportType.TLS; this.host = binding.IsHost ? binding.Host : binding.Address.ToString(); this.port = binding.Port; if (transportType == SipTransportType.TCP) { parameters.Add("transport", "tcp"); } }
/// <summary> /// Constructs a SIP URI from the parameters passed. /// </summary> /// <param name="transportType">The transport type.</param> /// <param name="user">The user (or <c>null</c>).</param> /// <param name="host">The host.</param> /// <param name="port">The port (or <b>0</b>).</param> /// <remarks> /// Passing <paramref name="transportType"/> as <see cref="SipTransportType.TLS" /> /// will result in a <i>secure</i> URI. Passing <paramref name="transportType"/> as /// <see cref="SipTransportType.TCP" /> will return a URI with a <b>transport=tcp</b> /// parameter. /// </remarks> public SipUri(SipTransportType transportType, string user, string host, int port) { this.isSecure = transportType == SipTransportType.TLS; this.user = user; this.host = host; this.port = port; if (transportType == SipTransportType.TCP) { parameters.Add("transport", "tcp"); } }
/// <summary> /// Returns the default network port for the specified transport. /// </summary> /// <param name="transportType">Indicates the transport type.</param> /// <returns>The port number.</returns> public static int GetDefaultPort(SipTransportType transportType) { switch (transportType) { case SipTransportType.UDP: case SipTransportType.TCP: return(NetworkPort.SIP); case SipTransportType.TLS: return(NetworkPort.SIPS); default: throw new ArgumentException("Unspecified transport type."); } }
private void Blast(SipTransportType transportType) { TestCore serverCore = null; TestCore clientCore = null; SipServerAgent serverAgent; SipClientAgent clientAgent; SipCoreSettings settings; SipRequest request; SipResponse response; SipResult result; try { // Initialize the test cores settings = new SipCoreSettings(); settings.TransportSettings = new SipTransportSettings[] { new SipTransportSettings(SipTransportType.UDP, NetworkBinding.Parse("ANY:5060"), 0), new SipTransportSettings(SipTransportType.TCP, NetworkBinding.Parse("ANY:5060"), 0) }; serverCore = new TestCore(settings); serverAgent = new SipServerAgent(serverCore, serverCore); serverCore.Start(serverAgent); serverCore.SetHandler(new SipRequestDelegate(OnRequest)); settings = new SipCoreSettings(); settings.TransportSettings = new SipTransportSettings[] { new SipTransportSettings(SipTransportType.UDP, NetworkBinding.Parse("ANY:0"), 0), new SipTransportSettings(SipTransportType.TCP, NetworkBinding.Parse("ANY:0"), 0) }; clientCore = new TestCore(settings); clientAgent = new SipClientAgent(clientCore, clientCore); clientCore.Start(clientAgent); clientCore.SetHandler(new SipResponseDelegate(OnResponse)); // Do a bunch of requests for (int i = 0; i < 1000; i++) { Clear(); request = new SipRequest(SipMethod.Register, string.Format("sip:127.0.0.1:5060;transport={0}", transportType.ToString().ToLowerInvariant()), null); request.AddHeader(SipHeader.To, "sip:[email protected]"); request.AddHeader(SipHeader.From, "sip:[email protected]"); request.Contents = new byte[] { (byte)i }; serverOp = ServerOp.OK; result = clientAgent.Request(request, null); response = result.Response; Thread.Sleep(100); Assert.AreEqual(SipStatus.OK, result.Status); CollectionAssert.AreEqual(request.Contents, response.Contents); } } finally { if (clientCore != null) { clientCore.Stop(); } if (serverCore != null) { serverCore.Stop(); } } }
private void Provisional(SipTransportType transportType) { TestCore serverCore = null; TestCore clientCore = null; SipServerAgent serverAgent; SipClientAgent clientAgent; SipCoreSettings settings; SipRequest request; SipResponse response; SipResult result; try { // Initialize the test cores settings = new SipCoreSettings(); settings.TransportSettings = new SipTransportSettings[] { new SipTransportSettings(SipTransportType.UDP, NetworkBinding.Parse("ANY:5060"), 0), new SipTransportSettings(SipTransportType.TCP, NetworkBinding.Parse("ANY:5060"), 0) }; serverCore = new TestCore(settings); serverAgent = new SipServerAgent(serverCore, serverCore); serverCore.Start(serverAgent); serverCore.SetHandler(new SipRequestDelegate(OnRequest)); settings = new SipCoreSettings(); settings.TransportSettings = new SipTransportSettings[] { new SipTransportSettings(SipTransportType.UDP, NetworkBinding.Parse("ANY:0"), 0), new SipTransportSettings(SipTransportType.TCP, NetworkBinding.Parse("ANY:0"), 0) }; clientCore = new TestCore(settings); clientAgent = new SipClientAgent(clientCore, clientCore); clientCore.Start(clientAgent); clientCore.SetHandler(new SipResponseDelegate(OnResponse)); // Verify a transaction with a single provisional response. // // I'm also going to verify that setting SipRequest.ViaInstanceParam // resulted in the "instance" parameter being added to the requests // Via header. Clear(); request = new SipRequest(SipMethod.Register, string.Format("sip:127.0.0.1:5060;transport={0}", transportType.ToString().ToLowerInvariant()), null); request.AddHeader(SipHeader.To, "sip:[email protected]"); request.AddHeader(SipHeader.From, "sip:[email protected]"); serverOp = ServerOp.ProvisionalOK; result = clientAgent.Request(request, null); Thread.Sleep(100); Assert.AreEqual(SipStatus.OK, result.Status); // Verify the response headers request = result.Request; response = result.Response; Assert.AreEqual(1, requestArgs.Count); Assert.AreEqual(2, responseArgs.Count); Assert.AreEqual(SipStatus.Trying, responseArgs[0].Response.Status); Assert.AreEqual(SipStatus.OK, responseArgs[1].Response.Status); Assert.AreEqual(request.Headers[SipHeader.To].Text, new SipValue(request.Headers[SipHeader.To].Text).Text); Assert.IsTrue(string.IsNullOrWhiteSpace(new SipValue(response.Headers[SipHeader.To].Text)["tag"])); Assert.AreEqual(request.Headers[SipHeader.From].Text, response.Headers[SipHeader.From].Text); Assert.AreEqual(request.Headers[SipHeader.CallID].Text, response.Headers[SipHeader.CallID].Text); Assert.AreEqual(request.Headers[SipHeader.CSeq].Text, response.Headers[SipHeader.CSeq].Text); Assert.AreEqual(request.Headers[SipHeader.Via].Text, response.Headers[SipHeader.Via].Text); // Verify a transaction with two provisional responses Clear(); request = new SipRequest(SipMethod.Register, string.Format("sip:127.0.0.1:5060;transport={0}", transportType.ToString().ToLowerInvariant()), null); request.AddHeader(SipHeader.To, "sip:[email protected]"); request.AddHeader(SipHeader.From, "sip:[email protected]"); serverOp = ServerOp.ProvisionalProvisionalOK; result = clientAgent.Request(request, null); Thread.Sleep(100); Assert.AreEqual(SipStatus.OK, result.Status); // Verify the response headers request = result.Request; response = result.Response; Assert.AreEqual(1, requestArgs.Count); Assert.AreEqual(3, responseArgs.Count); Assert.AreEqual(SipStatus.Trying, responseArgs[0].Response.Status); Assert.AreEqual("0", responseArgs[0].Response["Test"].Text); Assert.AreEqual(SipStatus.Trying, responseArgs[1].Response.Status); Assert.AreEqual("1", responseArgs[1].Response["Test"].Text); Assert.AreEqual(SipStatus.OK, responseArgs[2].Response.Status); Assert.AreEqual("2", responseArgs[2].Response["Test"].Text); Assert.AreEqual(request.Headers[SipHeader.To].Text, new SipValue(request.Headers[SipHeader.To].Text).Text); Assert.IsTrue(string.IsNullOrWhiteSpace(new SipValue(response.Headers[SipHeader.To].Text)["tag"])); Assert.AreEqual(request.Headers[SipHeader.From].Text, response.Headers[SipHeader.From].Text); Assert.AreEqual(request.Headers[SipHeader.CallID].Text, response.Headers[SipHeader.CallID].Text); Assert.AreEqual(request.Headers[SipHeader.CSeq].Text, response.Headers[SipHeader.CSeq].Text); Assert.AreEqual(request.Headers[SipHeader.Via].Text, response.Headers[SipHeader.Via].Text); } finally { if (clientCore != null) { clientCore.Stop(); } if (serverCore != null) { serverCore.Stop(); } } }
//--------------------------------------------------------------------- // Tests private void Basic(SipTransportType transportType) { TestCore serverCore = null; TestCore clientCore = null; SipServerAgent serverAgent; SipClientAgent clientAgent; SipCoreSettings settings; SipRequest request; SipResponse response; SipResult result; try { // Initialize the test cores settings = new SipCoreSettings(); settings.TransportSettings = new SipTransportSettings[] { new SipTransportSettings(SipTransportType.UDP, NetworkBinding.Parse("ANY:5060"), 0), new SipTransportSettings(SipTransportType.TCP, NetworkBinding.Parse("ANY:5060"), 0) }; serverCore = new TestCore(settings); serverAgent = new SipServerAgent(serverCore, serverCore); serverCore.Start(serverAgent); serverCore.SetHandler(new SipRequestDelegate(OnRequest)); settings = new SipCoreSettings(); settings.TransportSettings = new SipTransportSettings[] { new SipTransportSettings(SipTransportType.UDP, NetworkBinding.Parse("ANY:0"), 0), new SipTransportSettings(SipTransportType.TCP, NetworkBinding.Parse("ANY:0"), 0) }; clientCore = new TestCore(settings); clientAgent = new SipClientAgent(clientCore, clientCore); clientCore.Start(clientAgent); clientCore.SetHandler(new SipResponseDelegate(OnResponse)); // Verify a basic Request/OK transaction Clear(); request = new SipRequest(SipMethod.Register, string.Format("sip:127.0.0.1:5060;transport={0}", transportType.ToString().ToLowerInvariant()), null); request.AddHeader(SipHeader.To, "sip:[email protected]"); request.AddHeader(SipHeader.From, "sip:[email protected]"); serverOp = ServerOp.OK; result = clientAgent.Request(request, null); Thread.Sleep(100); Assert.AreEqual(SipStatus.OK, result.Status); // Verify the response headers request = result.Request; response = result.Response; Assert.AreEqual(1, requestArgs.Count); Assert.AreEqual(1, responseArgs.Count); Assert.AreEqual(request.Headers[SipHeader.To].Text, new SipValue(request.Headers[SipHeader.To].Text).Text); Assert.IsTrue(string.IsNullOrWhiteSpace(new SipValue(response.Headers[SipHeader.To].Text)["tag"])); Assert.AreEqual(request.Headers[SipHeader.From].Text, response.Headers[SipHeader.From].Text); Assert.AreEqual(request.Headers[SipHeader.CallID].Text, response.Headers[SipHeader.CallID].Text); Assert.AreEqual(request.Headers[SipHeader.CSeq].Text, response.Headers[SipHeader.CSeq].Text); Assert.AreEqual(request.Headers[SipHeader.Via].Text, response.Headers[SipHeader.Via].Text); // Verify that "Max-Forwards: 70" headers were added to the request message. Assert.AreEqual(SipHelper.MaxForwards, requestArgs[0].Request.GetHeaderText(SipHeader.MaxForwards)); // Verify requests that result in errors. Clear(); request = new SipRequest(SipMethod.Register, string.Format("sip:127.0.0.1:5060;transport={0}", transportType.ToString().ToLowerInvariant()), null); request.AddHeader(SipHeader.To, "sip:[email protected]"); request.AddHeader(SipHeader.From, "sip:[email protected]"); serverOp = ServerOp.Error; result = clientAgent.Request(request, null); Thread.Sleep(100); Assert.AreEqual(SipStatus.NotImplemented, result.Status); // Verify the response headers request = result.Request; response = result.Response; Assert.AreEqual(1, requestArgs.Count); Assert.AreEqual(1, responseArgs.Count); Assert.AreEqual(request.Headers[SipHeader.To].Text, new SipValue(request.Headers[SipHeader.To].Text).Text); Assert.IsTrue(string.IsNullOrWhiteSpace(new SipValue(response.Headers[SipHeader.To].Text)["tag"])); Assert.AreEqual(request.Headers[SipHeader.From].Text, response.Headers[SipHeader.From].Text); Assert.AreEqual(request.Headers[SipHeader.CallID].Text, response.Headers[SipHeader.CallID].Text); Assert.AreEqual(request.Headers[SipHeader.CSeq].Text, response.Headers[SipHeader.CSeq].Text); Assert.AreEqual(request.Headers[SipHeader.Via].Text, response.Headers[SipHeader.Via].Text); } finally { if (clientCore != null) { clientCore.Stop(); } if (serverCore != null) { serverCore.Stop(); } } }
/// <summary> /// Converts a contact style header value into the <see cref="NetworkBinding" /> /// and optional <see cref="SipTransportType" /> to be used when figuring out /// how to deliver an outbound SIP message. /// </summary> /// <param name="contactText">The <b>Contact</b> header text.</param> /// <param name="binding">Returns as the <see cref="NetworkBinding" /> to use.</param> /// <param name="transportType">Returns the <see cref="SipTransportType" /> to use</param> /// <returns></returns> /// <remarks> /// <para> /// The <paramref name="contactText" /> parameter should be passed as the SIP request URI, /// or the value of a <b>To</b>, <b>From</b>, or a <b>Contact</b> header value. The method /// parses this value, looking for the IP address, port, and transport information to be used /// when selecting a transport to communicate with this entity. The method will perform an /// necessary DNS lookups to resolve host names into IP addresses. /// </para> /// <para> /// If the operation was successful, the method returns <c>true</c> and sets the <paramref name="binding" /> /// and <paramref name="transportType" /> values. /// </para> /// <note> /// <paramref name="transportType" /> will return as <see cref="SipTransportType.Unspecified" /> if the /// contact information didn't explicitly specify a transport. /// </note> /// </remarks> public static bool TryGetRemoteBinding(string contactText, out NetworkBinding binding, out SipTransportType transportType) { SipContactValue v = new SipContactValue(contactText); IPAddress address; int port; SipUri uri; string transport; string sHost, sPort; int p; binding = null; transportType = SipTransportType.Unspecified; // First try to parse the text as a SIP URI. if (SipUri.TryParse(v.Uri, out uri)) { if (!IPAddress.TryParse(uri.Host, out address)) { try { address = Dns.GetHostEntry(uri.Host).AddressList[0]; } catch { return(false); } } binding = new NetworkBinding(address, uri.Port); if (uri.Parameters.TryGetValue("transport", out transport)) { switch (transport.ToUpper()) { case "UDP": transportType = SipTransportType.UDP; break; case "TCP": transportType = SipTransportType.TCP; break; case "TLS": transportType = SipTransportType.TLS; break; } } return(true); } // Now look for <ip-address> [":" <port>] p = v.Uri.IndexOf(':'); if (p == -1) { if (!IPAddress.TryParse(v.Uri, out address)) { try { address = Dns.GetHostEntry(v.Uri).AddressList.IPv4Only()[0]; } catch { return(false); } } binding = new NetworkBinding(address, NetworkPort.SIP); return(true); } sHost = v.Uri.Substring(0, p).Trim(); sPort = v.Uri.Substring(p + 1).Trim(); if (sHost.Length == 0 || sPort.Length == 0) { return(false); } if (!int.TryParse(sPort, out port) || port <= 0 || port > ushort.MaxValue) { return(false); } if (IPAddress.TryParse(sHost, out address)) { binding = new NetworkBinding(address, port); return(true); } // The host portion is not an IP address so perform a host lookup if (!IPAddress.TryParse(sHost, out address)) { try { address = Dns.GetHostEntry(sHost).AddressList.IPv4Only()[0]; } catch { return(false); } } binding = new NetworkBinding(address, port); return(true); }