PageRenderTime 43ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/sipsorcery-core/SIPSorcery.SIP.App/SIPUserAgents/SIPRegistrationUserAgent.cs

https://github.com/thecc4re/sipsorcery-mono
C# | 553 lines | 456 code | 50 blank | 47 comment | 85 complexity | d58b40e92e1d888386253e90e0b4d054 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. // ============================================================================
  2. // FileName: SIPRegistrationUserAgent.cs
  3. //
  4. // Description:
  5. // A user agent that can register and maintain a binding with a SIP Registrar.
  6. //
  7. // Author(s):
  8. // Aaron Clauson
  9. //
  10. // History:
  11. // 03 Mar 2010 Aaron Clauson Created.
  12. //
  13. // License:
  14. // This software is licensed under the BSD License http://www.opensource.org/licenses/bsd-license.php
  15. //
  16. // Copyright (c) 2010 Aaron Clauson (aaron@sipsorcery.com), SIPSorcery Ltd, London, UK (www.sipsorcery.com)
  17. // All rights reserved.
  18. //
  19. // Redistribution and use in source and binary forms, with or without modification, are permitted provided that
  20. // the following conditions are met:
  21. //
  22. // Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  23. // Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
  24. // disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of Blue Face Ltd.
  25. // nor the names of its contributors may be used to endorse or promote products derived from this software without specific
  26. // prior written permission.
  27. //
  28. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
  29. // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  30. // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  31. // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  32. // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  33. // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  34. // POSSIBILITY OF SUCH DAMAGE.
  35. // ============================================================================
  36. using System;
  37. using System.Collections.Generic;
  38. using System.Linq;
  39. using System.Text;
  40. using System.Threading;
  41. using SIPSorcery.SIP;
  42. using SIPSorcery.Sys;
  43. using log4net;
  44. namespace SIPSorcery.SIP.App
  45. {
  46. public class SIPRegistrationUserAgent
  47. {
  48. private const int MAX_EXPIRY = 7200;
  49. private const int MAX_REGISTRATION_ATTEMPT_TIMEOUT = 60;
  50. private const int REGISTRATION_HEAD_TIME = 5; // Time in seconds to go to next registration to initate.
  51. private const int REGISTER_FAILURERETRY_INTERVAL = 300; // Number of seconds between consecutive register requests in the event of failures or timeouts.
  52. private const int REGISTER_MINIMUM_EXPIRY = 60; // The minimum interval a registration will be accepted for. Anything less than this interval will use this minimum value.
  53. private const int DEFAULT_REGISTER_EXPIRY = 600;
  54. private const int MAX_REGISTER_ATTEMPTS = 3; // The maximum number of registration attempts that will be made without a failure condition before incurring a temporary failure.
  55. private static ILog logger = AppState.logger;
  56. private static readonly string m_userAgent = SIPConstants.SIP_USERAGENT_STRING;
  57. private SIPMonitorLogDelegate Log_External;
  58. private SIPTransport m_sipTransport;
  59. private SIPEndPoint m_outboundProxy;
  60. private SIPEndPoint m_localEndPoint;
  61. private SIPURI m_sipAccountAOR;
  62. private string m_authUsername;
  63. private string m_password;
  64. private string m_realm;
  65. private string m_registrarHost;
  66. private SIPURI m_contactURI;
  67. private int m_expiry;
  68. private string m_owner;
  69. private string m_adminMemberID;
  70. private bool m_isRegistered;
  71. private int m_cseq;
  72. private string m_callID;
  73. private bool m_exit;
  74. private int m_attempts;
  75. private string m_lastServerNonce;
  76. private ManualResetEvent m_waitForRegistrationMRE = new ManualResetEvent(false);
  77. public string UserAgent; // If not null this value will replace the default user agent value in the REGISTER request.
  78. public bool RequestSwitchboardToken; // If set to true a header will be set on the REGISTER request that asks the server to return a toekn that can be used by the switchboard for 3rd party authorisation.
  79. public string SwitchboardToken; // If a switchboard token is provided by the server it will be placed here.
  80. public event Action<SIPURI, string> RegistrationFailed;
  81. public event Action<SIPURI, string> RegistrationTemporaryFailure;
  82. public event Action<SIPURI> RegistrationSuccessful;
  83. public event Action<SIPURI> RegistrationRemoved;
  84. public SIPRegistrationUserAgent(
  85. SIPTransport sipTransport,
  86. SIPEndPoint outboundProxy,
  87. SIPEndPoint localEndPoint,
  88. SIPURI sipAccountAOR,
  89. string authUsername,
  90. string password,
  91. string realm,
  92. string registrarHost,
  93. SIPURI contactURI,
  94. int expiry,
  95. string owner,
  96. string adminMemberID,
  97. SIPMonitorLogDelegate logDelegate)
  98. {
  99. m_sipTransport = sipTransport;
  100. m_outboundProxy = outboundProxy;
  101. m_localEndPoint = localEndPoint;
  102. m_sipAccountAOR = sipAccountAOR;
  103. m_authUsername = authUsername;
  104. m_password = password;
  105. m_realm = realm;
  106. m_registrarHost = registrarHost;
  107. m_contactURI = contactURI;
  108. m_expiry = (expiry >= REGISTER_MINIMUM_EXPIRY && expiry <= MAX_EXPIRY) ? expiry : DEFAULT_REGISTER_EXPIRY;
  109. m_owner = owner;
  110. m_adminMemberID = adminMemberID;
  111. m_callID = Guid.NewGuid().ToString();
  112. Log_External = logDelegate;
  113. }
  114. public void Start()
  115. {
  116. ThreadPool.QueueUserWorkItem(delegate { StartRegistration(); });
  117. }
  118. public void StartRegistration()
  119. {
  120. try
  121. {
  122. logger.Debug("Starting SIPRegistrationUserAgent for " + m_sipAccountAOR.ToString() + ".");
  123. while (!m_exit)
  124. {
  125. m_waitForRegistrationMRE.Reset();
  126. m_attempts = 0;
  127. SendInitialRegister();
  128. if (!m_waitForRegistrationMRE.WaitOne(MAX_REGISTRATION_ATTEMPT_TIMEOUT * 1000))
  129. {
  130. m_isRegistered = false;
  131. if (!m_exit)
  132. {
  133. RegistrationTemporaryFailure(m_sipAccountAOR, "Registration to " + m_registrarHost + " for " + m_sipAccountAOR.ToString() + " timed out.");
  134. }
  135. }
  136. if (!m_exit && m_isRegistered)
  137. {
  138. logger.Debug("SIPRegistrationUserAgent was successful, scheduling next registration to " + m_sipAccountAOR.ToString() + " in " + (m_expiry - REGISTRATION_HEAD_TIME) + "s.");
  139. Thread.Sleep((m_expiry - REGISTRATION_HEAD_TIME) * 1000);
  140. }
  141. else
  142. {
  143. logger.Debug("SIPRegistrationUserAgent temporarily failed, scheduling next registration to " + m_sipAccountAOR.ToString() + " in " + REGISTER_FAILURERETRY_INTERVAL + "s.");
  144. Thread.Sleep(REGISTER_FAILURERETRY_INTERVAL * 1000);
  145. }
  146. }
  147. logger.Debug("SIPRegistrationUserAgent for " + m_sipAccountAOR.ToString() + " stopping.");
  148. }
  149. catch (Exception excp)
  150. {
  151. logger.Error("Exception SIPRegistrationUserAgent Start. " + excp.Message);
  152. }
  153. }
  154. public void Stop()
  155. {
  156. try
  157. {
  158. if (!m_exit)
  159. {
  160. logger.Debug("Stopping SIP registration user agent for " + m_sipAccountAOR.ToString() + ".");
  161. m_exit = true;
  162. m_waitForRegistrationMRE.Set();
  163. if (m_isRegistered)
  164. {
  165. m_attempts = 0;
  166. m_expiry = 0;
  167. ThreadPool.QueueUserWorkItem(delegate { SendInitialRegister(); });
  168. }
  169. }
  170. }
  171. catch (Exception excp)
  172. {
  173. logger.Error("Exception SIPRegistrationUserAgent Stop. " + excp.Message);
  174. }
  175. }
  176. private void SendInitialRegister()
  177. {
  178. try
  179. {
  180. if (m_attempts >= MAX_REGISTER_ATTEMPTS)
  181. {
  182. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration to " + m_sipAccountAOR.ToString() + " reached the maximum number of allowed attempts without a failure condition.", m_owner));
  183. m_isRegistered = false;
  184. RegistrationTemporaryFailure(m_sipAccountAOR, "Registration reached the maximum number of allowed attempts.");
  185. m_waitForRegistrationMRE.Set();
  186. }
  187. else
  188. {
  189. m_attempts++;
  190. SIPEndPoint registrarSIPEndPoint = m_outboundProxy ;
  191. if(registrarSIPEndPoint == null)
  192. {
  193. SIPDNSLookupResult lookupResult = m_sipTransport.GetHostEndPoint(m_registrarHost, false);
  194. if (lookupResult.LookupError != null)
  195. {
  196. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Could not resolve " + m_registrarHost + ", " + lookupResult.LookupError, m_owner));
  197. }
  198. else
  199. {
  200. registrarSIPEndPoint = lookupResult.GetSIPEndPoint();
  201. }
  202. }
  203. if (registrarSIPEndPoint == null)
  204. {
  205. RegistrationFailed(m_sipAccountAOR, "Could not resolve " + m_registrarHost + ".");
  206. }
  207. else
  208. {
  209. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Initiating registration to " + m_registrarHost + " at " + registrarSIPEndPoint.ToString() + " for " + m_sipAccountAOR.ToString() + ".", m_owner));
  210. SIPRequest regRequest = GetRegistrationRequest(m_localEndPoint);
  211. SIPNonInviteTransaction regTransaction = m_sipTransport.CreateNonInviteTransaction(regRequest, registrarSIPEndPoint, m_localEndPoint, m_outboundProxy);
  212. // These handlers need to be on their own threads to take the processing off the SIP transport layer.
  213. regTransaction.NonInviteTransactionFinalResponseReceived += (lep, rep, tn, rsp) => { ThreadPool.QueueUserWorkItem(delegate { ServerResponseReceived(lep, rep, tn, rsp); }); };
  214. regTransaction.NonInviteTransactionTimedOut += (tn) => { ThreadPool.QueueUserWorkItem(delegate { RegistrationTimedOut(tn); }); };
  215. m_sipTransport.SendSIPReliable(regTransaction);
  216. }
  217. }
  218. }
  219. catch (Exception excp)
  220. {
  221. logger.Error("Exception SendInitialRegister to " + m_registrarHost + ". " + excp.Message);
  222. RegistrationFailed(m_sipAccountAOR, "Exception SendInitialRegister to " + m_registrarHost + ". " + excp.Message);
  223. }
  224. }
  225. private void RegistrationTimedOut(SIPTransaction sipTransaction)
  226. {
  227. m_isRegistered = false;
  228. RegistrationTemporaryFailure(m_sipAccountAOR, "Registration transaction to " + m_registrarHost + " for " + m_sipAccountAOR.ToString() + " timed out.");
  229. m_waitForRegistrationMRE.Set();
  230. }
  231. /// <summary>
  232. /// The event handler for responses to the initial register request.
  233. /// </summary>
  234. private void ServerResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
  235. {
  236. try
  237. {
  238. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Server response " + sipResponse.Status + " received for " + m_sipAccountAOR.ToString() + ".", m_owner));
  239. if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
  240. {
  241. if (sipResponse.Header.AuthenticationHeader != null)
  242. {
  243. if (m_attempts >= MAX_REGISTER_ATTEMPTS)
  244. {
  245. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration to " + m_sipAccountAOR.ToString() + " reached the maximum number of allowed attempts without a failure condition.", m_owner));
  246. m_isRegistered = false;
  247. RegistrationTemporaryFailure(m_sipAccountAOR, "Registration reached the maximum number of allowed attempts.");
  248. m_waitForRegistrationMRE.Set();
  249. }
  250. else
  251. {
  252. m_attempts++;
  253. SIPRequest authenticatedRequest = GetAuthenticatedRegistrationRequest(sipTransaction.TransactionRequest, sipResponse);
  254. SIPNonInviteTransaction regAuthTransaction = m_sipTransport.CreateNonInviteTransaction(authenticatedRequest, sipTransaction.RemoteEndPoint, localSIPEndPoint, m_outboundProxy);
  255. regAuthTransaction.NonInviteTransactionFinalResponseReceived += (lep, rep, tn, rsp) => { ThreadPool.QueueUserWorkItem(delegate { AuthResponseReceived(lep, rep, tn, rsp); }); };
  256. regAuthTransaction.NonInviteTransactionTimedOut += (tn) => { ThreadPool.QueueUserWorkItem(delegate { RegistrationTimedOut(tn); }); };
  257. m_sipTransport.SendSIPReliable(regAuthTransaction);
  258. }
  259. }
  260. else
  261. {
  262. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " but no authentication header was supplied for " + m_sipAccountAOR.ToString() + ".", m_owner));
  263. m_isRegistered = false;
  264. RegistrationTemporaryFailure(m_sipAccountAOR, "Registration failed with " + sipResponse.Status + " but no authentication header was supplied.");
  265. m_waitForRegistrationMRE.Set();
  266. }
  267. }
  268. else
  269. {
  270. if (sipResponse.Status == SIPResponseStatusCodesEnum.Ok)
  271. {
  272. if (m_expiry > 0)
  273. {
  274. m_isRegistered = true;
  275. m_expiry = GetUpdatedExpiry(sipResponse);
  276. if (sipResponse.Header.SwitchboardToken != null && m_lastServerNonce != null)
  277. {
  278. SwitchboardToken = Crypto.SymmetricDecrypt(m_password, m_lastServerNonce, sipResponse.Header.SwitchboardToken);
  279. }
  280. RegistrationSuccessful(m_sipAccountAOR);
  281. }
  282. else
  283. {
  284. m_isRegistered = false;
  285. RegistrationRemoved(m_sipAccountAOR);
  286. }
  287. m_waitForRegistrationMRE.Set();
  288. }
  289. else if (sipResponse.Status == SIPResponseStatusCodesEnum.Forbidden || sipResponse.Status == SIPResponseStatusCodesEnum.NotFound)
  290. {
  291. // SIP account does not appear to exist.
  292. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ", no further registration attempts will be made.", m_owner));
  293. string reasonPhrase = (sipResponse.ReasonPhrase.IsNullOrBlank()) ? sipResponse.Status.ToString() : sipResponse.ReasonPhrase;
  294. RegistrationFailed(m_sipAccountAOR, "Registration failed with " + (int)sipResponse.Status + " " + reasonPhrase + ".");
  295. m_exit = true;
  296. m_waitForRegistrationMRE.Set();
  297. }
  298. else if (sipResponse.Status == SIPResponseStatusCodesEnum.IntervalTooBrief && m_expiry != 0)
  299. {
  300. m_expiry = GetUpdatedExpiryForIntervalTooBrief(sipResponse);
  301. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Registration for " + m_sipAccountAOR.ToString() + " had a too short expiry, updated to +" + m_expiry + " and trying again.", m_owner));
  302. SendInitialRegister();
  303. }
  304. else
  305. {
  306. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ".", m_owner));
  307. m_isRegistered = false;
  308. RegistrationTemporaryFailure(m_sipAccountAOR, "Registration failed with " + sipResponse.Status + ".");
  309. m_waitForRegistrationMRE.Set();
  310. }
  311. }
  312. }
  313. catch (Exception excp)
  314. {
  315. logger.Error("Exception SIPRegistrationUserAgent ServerResponseReceived (" + remoteEndPoint + "). " + excp.Message);
  316. }
  317. }
  318. /// <summary>
  319. /// The event handler for responses to the authenticated register request.
  320. /// </summary>
  321. private void AuthResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
  322. {
  323. try
  324. {
  325. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Server auth response " + sipResponse.Status + " received for " + m_sipAccountAOR.ToString() + ".", m_owner));
  326. if (sipResponse.Status == SIPResponseStatusCodesEnum.Ok)
  327. {
  328. if (m_expiry > 0)
  329. {
  330. m_isRegistered = true;
  331. m_expiry = GetUpdatedExpiry(sipResponse);
  332. if (sipResponse.Header.SwitchboardToken != null && m_lastServerNonce != null)
  333. {
  334. SwitchboardToken = Crypto.SymmetricDecrypt(m_password, m_lastServerNonce, sipResponse.Header.SwitchboardToken);
  335. }
  336. RegistrationSuccessful(m_sipAccountAOR);
  337. }
  338. else
  339. {
  340. m_isRegistered = false;
  341. RegistrationRemoved(m_sipAccountAOR);
  342. }
  343. m_waitForRegistrationMRE.Set();
  344. }
  345. else if (sipResponse.Status == SIPResponseStatusCodesEnum.IntervalTooBrief && m_expiry != 0)
  346. {
  347. m_expiry = GetUpdatedExpiryForIntervalTooBrief(sipResponse);
  348. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Registration for " + m_sipAccountAOR.ToString() + " had a too short expiry, updated to +" + m_expiry + " and trying again.", m_owner));
  349. SendInitialRegister();
  350. }
  351. else if (sipResponse.Status == SIPResponseStatusCodesEnum.Forbidden || sipResponse.Status == SIPResponseStatusCodesEnum.NotFound)
  352. {
  353. // SIP account does not appear to exist.
  354. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ", no further registration attempts will be made.", m_owner));
  355. string reasonPhrase = (sipResponse.ReasonPhrase.IsNullOrBlank()) ? sipResponse.Status.ToString() : sipResponse.ReasonPhrase;
  356. RegistrationFailed(m_sipAccountAOR, "Registration failed with " + (int)sipResponse.Status + " " + reasonPhrase + ".");
  357. m_exit = true;
  358. m_waitForRegistrationMRE.Set();
  359. }
  360. else if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
  361. {
  362. // SIP account credentials failed.
  363. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ", no further registration attempts will be made.", m_owner));
  364. string reasonPhrase = (sipResponse.ReasonPhrase.IsNullOrBlank()) ? sipResponse.Status.ToString() : sipResponse.ReasonPhrase;
  365. RegistrationFailed(m_sipAccountAOR, "Registration failed with " + (int)sipResponse.Status + " " + reasonPhrase + ".");
  366. m_exit = true;
  367. m_waitForRegistrationMRE.Set();
  368. }
  369. else
  370. {
  371. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ".", m_owner));
  372. m_isRegistered = false;
  373. RegistrationTemporaryFailure(m_sipAccountAOR, "Registration failed with " + sipResponse.Status + ".");
  374. m_waitForRegistrationMRE.Set();
  375. }
  376. }
  377. catch (Exception excp)
  378. {
  379. logger.Error("Exception SIPRegistrationUserAgent AuthResponseReceived. " + excp.Message);
  380. }
  381. }
  382. private int GetUpdatedExpiryForIntervalTooBrief(SIPResponse sipResponse)
  383. {
  384. int newExpiry = sipResponse.Header.MinExpires;
  385. if (newExpiry != 0 && newExpiry > m_expiry)
  386. {
  387. if(newExpiry > MAX_EXPIRY)
  388. {
  389. return MAX_EXPIRY;
  390. }
  391. else
  392. {
  393. return newExpiry;
  394. }
  395. }
  396. else if(m_expiry < MAX_EXPIRY)
  397. {
  398. return m_expiry * 2;
  399. }
  400. return m_expiry;
  401. }
  402. private int GetUpdatedExpiry(SIPResponse sipResponse)
  403. {
  404. // Find the contact in the list that matches the one being maintained by this agent in order to determine the expiry value.
  405. int serverExpiry = 0;
  406. int headerExpires = sipResponse.Header.Expires;
  407. int contactExpires = -1;
  408. if (sipResponse.Header.Contact != null && sipResponse.Header.Contact.Count > 0)
  409. {
  410. if (sipResponse.Header.Contact.Count == 1)
  411. {
  412. contactExpires = sipResponse.Header.Contact[0].Expires;
  413. }
  414. else
  415. {
  416. foreach (SIPContactHeader contactHeader in sipResponse.Header.Contact)
  417. {
  418. if (contactHeader.ContactURI == m_sipAccountAOR)
  419. {
  420. contactExpires = contactHeader.Expires;
  421. break;
  422. }
  423. }
  424. }
  425. }
  426. if (contactExpires != -1)
  427. {
  428. serverExpiry = contactExpires;
  429. }
  430. else if (headerExpires != -1)
  431. {
  432. serverExpiry = headerExpires;
  433. }
  434. if (serverExpiry < REGISTER_MINIMUM_EXPIRY)
  435. {
  436. // Make sure we don't do a 3CX and send registration floods.
  437. return REGISTER_MINIMUM_EXPIRY;
  438. }
  439. else if (serverExpiry > MAX_EXPIRY)
  440. {
  441. return MAX_EXPIRY;
  442. }
  443. else
  444. {
  445. return serverExpiry;
  446. }
  447. }
  448. private SIPRequest GetRegistrationRequest(SIPEndPoint localSIPEndPoint)
  449. {
  450. try
  451. {
  452. string realm = (m_realm != null) ? m_realm : IPSocket.ParseHostFromSocket(m_registrarHost);
  453. SIPURI registerURI = m_sipAccountAOR.CopyOf();
  454. registerURI.User = null;
  455. SIPRequest registerRequest = m_sipTransport.GetRequest(
  456. SIPMethodsEnum.REGISTER,
  457. registerURI,
  458. new SIPToHeader(null, m_sipAccountAOR, null),
  459. localSIPEndPoint);
  460. registerRequest.Header.From = new SIPFromHeader(null, m_sipAccountAOR, CallProperties.CreateNewTag());
  461. registerRequest.Header.Contact[0] = new SIPContactHeader(null, m_contactURI);
  462. registerRequest.Header.CSeq = ++m_cseq;
  463. registerRequest.Header.CallId = m_callID;
  464. registerRequest.Header.UserAgent = (!UserAgent.IsNullOrBlank()) ? UserAgent : m_userAgent;
  465. registerRequest.Header.Expires = m_expiry;
  466. return registerRequest;
  467. }
  468. catch (Exception excp)
  469. {
  470. logger.Error("Exception GetRegistrationRequest. " + excp.Message);
  471. throw excp;
  472. }
  473. }
  474. private SIPRequest GetAuthenticatedRegistrationRequest(SIPRequest registerRequest, SIPResponse sipResponse)
  475. {
  476. try
  477. {
  478. SIPAuthorisationDigest authRequest = sipResponse.Header.AuthenticationHeader.SIPDigest;
  479. m_lastServerNonce = authRequest.Nonce;
  480. string username = (m_authUsername != null) ? m_authUsername : m_sipAccountAOR.User;
  481. authRequest.SetCredentials(username, m_password, registerRequest.URI.ToString(), SIPMethodsEnum.REGISTER.ToString());
  482. SIPRequest regRequest = registerRequest.Copy();
  483. regRequest.LocalSIPEndPoint = registerRequest.LocalSIPEndPoint;
  484. regRequest.Header.Vias.TopViaHeader.Branch = CallProperties.CreateBranchId();
  485. regRequest.Header.From.FromTag = CallProperties.CreateNewTag();
  486. regRequest.Header.To.ToTag = null;
  487. regRequest.Header.CSeq = ++m_cseq;
  488. regRequest.Header.AuthenticationHeader = new SIPAuthenticationHeader(authRequest);
  489. regRequest.Header.AuthenticationHeader.SIPDigest.Response = authRequest.Digest;
  490. if (RequestSwitchboardToken)
  491. {
  492. regRequest.Header.SwitchboardTokenRequest = m_expiry;
  493. }
  494. return regRequest;
  495. }
  496. catch (Exception excp)
  497. {
  498. logger.Error("Exception GetAuthenticatedRegistrationRequest. " + excp.Message);
  499. throw excp;
  500. }
  501. }
  502. }
  503. }