PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/sipsorcery-core/SIPSorcery.SIP.Core/SIP/SIPEndPoint.cs

https://github.com/thecc4re/sipsorcery-mono
C# | 378 lines | 290 code | 77 blank | 11 comment | 66 complexity | 7ebc98b0dd1dae269af149131f8f1071 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Text;
  6. using System.Text.RegularExpressions;
  7. using SIPSorcery.Sys;
  8. using log4net;
  9. #if UNITTEST
  10. using NUnit.Framework;
  11. #endif
  12. namespace SIPSorcery.SIP
  13. {
  14. /// <summary>
  15. /// This class must remain immutable otherwise the SIP stack can develop problems. SIP end points can get
  16. /// passed amongst different servers for logging and forwarding SIP messages and a modification of the end point
  17. /// by one server can result in a problem for a different server. Instead a new SIP end point should be created
  18. /// wherever a modification is required.
  19. /// </summary>
  20. public class SIPEndPoint
  21. {
  22. private static ILog logger = AppState.logger;
  23. private static string m_transportParameterKey = SIPHeaderAncillary.SIP_HEADERANC_TRANSPORT;
  24. private static int m_defaultSIPPort = SIPConstants.DEFAULT_SIP_PORT;
  25. private static int m_defaultSIPTLSPort = SIPConstants.DEFAULT_SIP_TLS_PORT;
  26. public SIPProtocolsEnum Protocol { get; private set; }
  27. public IPAddress Address { get; private set; }
  28. public int Port { get; private set; }
  29. private SIPEndPoint() { }
  30. public SIPEndPoint(IPEndPoint endPoint)
  31. {
  32. Protocol = SIPProtocolsEnum.udp;
  33. Address = endPoint.Address;
  34. Port = endPoint.Port;
  35. }
  36. public SIPEndPoint(SIPProtocolsEnum protocol, IPAddress address, int port)
  37. {
  38. Protocol = protocol;
  39. Address = address;
  40. Port = port;
  41. }
  42. public SIPEndPoint(SIPURI sipURI)
  43. {
  44. Protocol = sipURI.Protocol;
  45. IPEndPoint endPoint = IPSocket.ParseSocketString(sipURI.Host);
  46. Address = endPoint.Address;
  47. Port = endPoint.Port;
  48. }
  49. public SIPEndPoint(SIPProtocolsEnum protocol, IPEndPoint endPoint)
  50. {
  51. Protocol = protocol;
  52. Address = endPoint.Address;
  53. Port = endPoint.Port;
  54. }
  55. public static SIPEndPoint ParseSIPEndPoint(string sipEndPointStr)
  56. {
  57. try
  58. {
  59. if (sipEndPointStr.IsNullOrBlank())
  60. {
  61. return null;
  62. }
  63. if (sipEndPointStr.StartsWith("udp") || sipEndPointStr.StartsWith("tcp") || sipEndPointStr.StartsWith("tls"))
  64. {
  65. return ParseSerialisedSIPEndPoint(sipEndPointStr);
  66. }
  67. string ipAddress = null;
  68. int port = 0;
  69. SIPProtocolsEnum protocol = SIPProtocolsEnum.udp;
  70. if (sipEndPointStr.StartsWith("sip:"))
  71. {
  72. sipEndPointStr = sipEndPointStr.Substring(4);
  73. }
  74. else if (sipEndPointStr.StartsWith("sips:"))
  75. {
  76. sipEndPointStr = sipEndPointStr.Substring(5);
  77. protocol = SIPProtocolsEnum.tls;
  78. }
  79. int colonIndex = sipEndPointStr.IndexOf(':');
  80. int semiColonIndex = sipEndPointStr.IndexOf(';');
  81. if (colonIndex == -1 && semiColonIndex == -1)
  82. {
  83. ipAddress = sipEndPointStr;
  84. }
  85. else if (colonIndex != -1 && semiColonIndex == -1)
  86. {
  87. ipAddress = sipEndPointStr.Substring(0, colonIndex);
  88. port = Convert.ToInt32(sipEndPointStr.Substring(colonIndex + 1));
  89. }
  90. else
  91. {
  92. if (colonIndex != -1 && colonIndex < semiColonIndex)
  93. {
  94. ipAddress = sipEndPointStr.Substring(0, colonIndex);
  95. port = Convert.ToInt32(sipEndPointStr.Substring(colonIndex + 1, semiColonIndex - colonIndex - 1));
  96. }
  97. else
  98. {
  99. ipAddress = sipEndPointStr.Substring(0, semiColonIndex);
  100. }
  101. if (protocol != SIPProtocolsEnum.tls)
  102. {
  103. sipEndPointStr = sipEndPointStr.Substring(semiColonIndex + 1);
  104. int transportIndex = sipEndPointStr.ToLower().IndexOf(m_transportParameterKey + "=");
  105. if (transportIndex != -1)
  106. {
  107. sipEndPointStr = sipEndPointStr.Substring(transportIndex + 10);
  108. semiColonIndex = sipEndPointStr.IndexOf(';');
  109. if (semiColonIndex != -1)
  110. {
  111. protocol = SIPProtocolsType.GetProtocolType(sipEndPointStr.Substring(0, semiColonIndex));
  112. }
  113. else
  114. {
  115. protocol = SIPProtocolsType.GetProtocolType(sipEndPointStr);
  116. }
  117. }
  118. }
  119. }
  120. if (port == 0)
  121. {
  122. port = (protocol == SIPProtocolsEnum.tls) ? m_defaultSIPTLSPort : m_defaultSIPPort;
  123. }
  124. return new SIPEndPoint(protocol, IPAddress.Parse(ipAddress), port);
  125. }
  126. catch (Exception excp)
  127. {
  128. logger.Error("Exception ParseSIPEndPoint (sipEndPointStr=" + sipEndPointStr + "). " + excp.Message);
  129. throw;
  130. }
  131. }
  132. /// <summary>
  133. /// Reverses ToString().
  134. /// </summary>
  135. /// <param name="serialisedSIPEndPoint">The serialised SIP end point MUST be in the form protocol:socket and protocol must
  136. /// be exactly 3 characters. Valid examples are udp:10.0.0.1:5060, invalid example is 10.0.0.1:5060.</param>
  137. private static SIPEndPoint ParseSerialisedSIPEndPoint(string serialisedSIPEndPoint)
  138. {
  139. return new SIPEndPoint(SIPProtocolsType.GetProtocolType(serialisedSIPEndPoint.Substring(0, 3)), IPSocket.ParseSocketString(serialisedSIPEndPoint.Substring(4)));
  140. }
  141. public override string ToString()
  142. {
  143. return Protocol + ":" + Address + ":" + Port;
  144. }
  145. public static bool AreEqual(SIPEndPoint endPoint1, SIPEndPoint endPoint2)
  146. {
  147. return endPoint1 == endPoint2;
  148. }
  149. public override bool Equals(object obj)
  150. {
  151. return AreEqual(this, (SIPEndPoint)obj);
  152. }
  153. public static bool operator ==(SIPEndPoint endPoint1, SIPEndPoint endPoint2)
  154. {
  155. if ((object)endPoint1 == null && (object)endPoint2 == null)
  156. {
  157. return true;
  158. }
  159. else if ((object)endPoint1 == null || (object)endPoint2 == null)
  160. {
  161. return false;
  162. }
  163. else if (endPoint1.ToString() != endPoint2.ToString())
  164. {
  165. return false;
  166. }
  167. return true;
  168. }
  169. public static bool operator !=(SIPEndPoint endPoint1, SIPEndPoint endPoint2)
  170. {
  171. return !(endPoint1 == endPoint2);
  172. }
  173. public override int GetHashCode()
  174. {
  175. return Protocol.GetHashCode() + Address.GetHashCode() + Port.GetHashCode();
  176. }
  177. public SIPEndPoint CopyOf()
  178. {
  179. SIPEndPoint copy = new SIPEndPoint(Protocol, new IPAddress(Address.GetAddressBytes()), Port);
  180. return copy;
  181. }
  182. public IPEndPoint GetIPEndPoint()
  183. {
  184. return new IPEndPoint(Address, Port);
  185. }
  186. #region Unit testing.
  187. #if UNITTEST
  188. [TestFixture]
  189. public class SIPEndPointUnitTest {
  190. [TestFixtureSetUp]
  191. public void Init() { }
  192. [TestFixtureTearDown]
  193. public void Dispose() { }
  194. [Test]
  195. public void SampleTest() {
  196. Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
  197. Assert.IsTrue(true, "True was false.");
  198. }
  199. [Test]
  200. public void AllFieldsParseTest() {
  201. Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
  202. string sipEndPointStr = "sips:10.0.0.100:5060;lr;transport=tcp;";
  203. SIPEndPoint sipEndPoint = SIPEndPoint.ParseSIPEndPoint(sipEndPointStr);
  204. Console.WriteLine("SIPEndPoint=" + sipEndPoint.ToString() + ".");
  205. Assert.IsTrue(sipEndPoint.Protocol == SIPProtocolsEnum.tls, "The SIPEndPoint protocol was incorrectly parsed.");
  206. Assert.IsTrue(sipEndPoint.Address.ToString() == "10.0.0.100", "The SIPEndPoint IP address was incorrectly parsed.");
  207. Assert.IsTrue(sipEndPoint.Port == 5060, "The SIPEndPoint port was incorrectly parsed.");
  208. Assert.IsTrue(true, "True was false.");
  209. }
  210. [Test]
  211. public void HostOnlyParseTest() {
  212. Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
  213. string sipEndPointStr = "10.0.0.100";
  214. SIPEndPoint sipEndPoint = SIPEndPoint.ParseSIPEndPoint(sipEndPointStr);
  215. Console.WriteLine("SIPEndPoint=" + sipEndPoint.ToString() + ".");
  216. Assert.IsTrue(sipEndPoint.Protocol == SIPProtocolsEnum.udp, "The SIPEndPoint protocol was incorrectly parsed.");
  217. Assert.IsTrue(sipEndPoint.Address.ToString() == "10.0.0.100", "The SIPEndPoint IP address was incorrectly parsed.");
  218. Assert.IsTrue(sipEndPoint.Port == 5060, "The SIPEndPoint port was incorrectly parsed.");
  219. Assert.IsTrue(true, "True was false.");
  220. }
  221. [Test]
  222. public void HostAndSchemeParseTest() {
  223. Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
  224. string sipEndPointStr = "sip:10.0.0.100";
  225. SIPEndPoint sipEndPoint = SIPEndPoint.ParseSIPEndPoint(sipEndPointStr);
  226. Console.WriteLine("SIPEndPoint=" + sipEndPoint.ToString() + ".");
  227. Assert.IsTrue(sipEndPoint.Protocol == SIPProtocolsEnum.udp, "The SIPEndPoint protocol was incorrectly parsed.");
  228. Assert.IsTrue(sipEndPoint.Address.ToString() == "10.0.0.100", "The SIPEndPoint IP address was incorrectly parsed.");
  229. Assert.IsTrue(sipEndPoint.Port == 5060, "The SIPEndPoint port was incorrectly parsed.");
  230. Assert.IsTrue(true, "True was false.");
  231. }
  232. [Test]
  233. public void HostAndPortParseTest() {
  234. Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
  235. string sipEndPointStr = "10.0.0.100:5065";
  236. SIPEndPoint sipEndPoint = SIPEndPoint.ParseSIPEndPoint(sipEndPointStr);
  237. Console.WriteLine("SIPEndPoint=" + sipEndPoint.ToString() + ".");
  238. Assert.IsTrue(sipEndPoint.Protocol == SIPProtocolsEnum.udp, "The SIPEndPoint protocol was incorrectly parsed.");
  239. Assert.IsTrue(sipEndPoint.Address.ToString() == "10.0.0.100", "The SIPEndPoint IP address was incorrectly parsed.");
  240. Assert.IsTrue(sipEndPoint.Port == 5065, "The SIPEndPoint port was incorrectly parsed.");
  241. Assert.IsTrue(true, "True was false.");
  242. }
  243. [Test]
  244. public void HostAndTransportParseTest() {
  245. Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
  246. string sipEndPointStr = "10.0.0.100;transport=tcp";
  247. SIPEndPoint sipEndPoint = SIPEndPoint.ParseSIPEndPoint(sipEndPointStr);
  248. Console.WriteLine("SIPEndPoint=" + sipEndPoint.ToString() + ".");
  249. Assert.IsTrue(sipEndPoint.Protocol == SIPProtocolsEnum.tcp, "The SIPEndPoint protocol was incorrectly parsed.");
  250. Assert.IsTrue(sipEndPoint.Address.ToString() == "10.0.0.100", "The SIPEndPoint IP address was incorrectly parsed.");
  251. Assert.IsTrue(sipEndPoint.Port == 5060, "The SIPEndPoint port was incorrectly parsed.");
  252. Assert.IsTrue(true, "True was false.");
  253. }
  254. [Test]
  255. public void SchemeHostPortParseTest() {
  256. Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
  257. string sipEndPointStr = "sips:10.0.0.100:5063";
  258. SIPEndPoint sipEndPoint = SIPEndPoint.ParseSIPEndPoint(sipEndPointStr);
  259. Console.WriteLine("SIPEndPoint=" + sipEndPoint.ToString() + ".");
  260. Assert.IsTrue(sipEndPoint.Protocol == SIPProtocolsEnum.tls, "The SIPEndPoint protocol was incorrectly parsed.");
  261. Assert.IsTrue(sipEndPoint.Address.ToString() == "10.0.0.100", "The SIPEndPoint IP address was incorrectly parsed.");
  262. Assert.IsTrue(sipEndPoint.Port == 5063, "The SIPEndPoint port was incorrectly parsed.");
  263. Assert.IsTrue(true, "True was false.");
  264. }
  265. [Test]
  266. public void SchemeHostTransportParseTest() {
  267. Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
  268. string sipEndPointStr = "sip:10.0.0.100:5063;lr;tag=123;transport=tcp;tag2=abcd";
  269. SIPEndPoint sipEndPoint = SIPEndPoint.ParseSIPEndPoint(sipEndPointStr);
  270. Console.WriteLine("SIPEndPoint=" + sipEndPoint.ToString() + ".");
  271. Assert.IsTrue(sipEndPoint.Protocol == SIPProtocolsEnum.tcp, "The SIPEndPoint protocol was incorrectly parsed.");
  272. Assert.IsTrue(sipEndPoint.Address.ToString() == "10.0.0.100", "The SIPEndPoint IP address was incorrectly parsed.");
  273. Assert.IsTrue(sipEndPoint.Port == 5063, "The SIPEndPoint port was incorrectly parsed.");
  274. Assert.IsTrue(true, "True was false.");
  275. }
  276. [Test]
  277. public void EqualityTestNoPostHostTest() {
  278. Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
  279. SIPEndPoint sipEP1 = SIPEndPoint.ParseSIPEndPoint("10.0.0.100");
  280. SIPEndPoint sipEP2 = SIPEndPoint.ParseSIPEndPoint("10.0.0.100:5060");
  281. Assert.IsTrue(sipEP1 == sipEP2, "The SIP end points should have been detected as equal.");
  282. }
  283. [Test]
  284. public void EqualityTestTLSHostTest() {
  285. Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
  286. SIPEndPoint sipEP1 = SIPEndPoint.ParseSIPEndPoint("sips:10.0.0.100");
  287. SIPEndPoint sipEP2 = SIPEndPoint.ParseSIPEndPoint("10.0.0.100:5061;transport=tls");
  288. Assert.IsTrue(sipEP1 == sipEP2, "The SIP end points should have been detected as equal.");
  289. }
  290. [Test]
  291. public void EqualityTestRouteTest() {
  292. Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
  293. SIPEndPoint sipEP1 = SIPEndPoint.ParseSIPEndPoint("sip:10.0.0.100;lr");
  294. SIPEndPoint sipEP2 = new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(IPAddress.Parse("10.0.0.100"), 5060));
  295. Assert.IsTrue(sipEP1 == sipEP2, "The SIP end points should have been detected as equal.");
  296. }
  297. }
  298. #endif
  299. #endregion
  300. }
  301. }