PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/sipsorcery-servers/SIPSorcery.SIPRegistrar/SIPRegistrarDaemon.cs

https://github.com/thecc4re/sipsorcery-mono
C# | 194 lines | 123 code | 22 blank | 49 comment | 17 complexity | 17de38e23f06aebab5f831adf432e743 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. // ============================================================================
  2. // FileName: SIPRegistrarDaemon.cs
  3. //
  4. // Description:
  5. // A daemon to configure and start a SIP Registration Agent.
  6. //
  7. // Author(s):
  8. // Aaron Clauson
  9. //
  10. // History:
  11. // 29 Mar 2009 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) 2009 Aaron Clauson (aaronc@blueface.ie), Blue Face Ltd, Dublin, Ireland (www.blueface.ie)
  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.IO;
  39. using System.Linq;
  40. using System.Net;
  41. using System.Net.Sockets;
  42. using System.Text;
  43. using System.Xml;
  44. using SIPSorcery.Persistence;
  45. using SIPSorcery.SIP;
  46. using SIPSorcery.SIP.App;
  47. using SIPSorcery.Servers;
  48. using SIPSorcery.Sys;
  49. using log4net;
  50. namespace SIPSorcery.SIPRegistrar {
  51. public class SIPRegistrarDaemon {
  52. private ILog logger = AppState.logger;
  53. private XmlNode m_sipRegistrarSocketsNode = SIPRegistrarState.SIPRegistrarSocketsNode;
  54. private XmlNode m_userAgentsConfigNode = SIPRegistrarState.UserAgentsConfigNode;
  55. private int m_monitorLoopbackPort = SIPRegistrarState.MonitorLoopbackPort;
  56. private int m_maximumAccountBindings = SIPRegistrarState.MaximumAccountBindings;
  57. private IPEndPoint m_natKeepAliveRelaySocket = SIPRegistrarState.NATKeepAliveRelaySocket;
  58. private string m_switchboardCertificateName = SIPRegistrarState.SwitchboardCertificateName;
  59. private int m_threadCount = SIPRegistrarState.ThreadCount;
  60. private SIPTransport m_sipTransport;
  61. private SIPMonitorEventWriter m_monitorEventWriter;
  62. private RegistrarCore m_registrarCore;
  63. private SIPRegistrarBindingsManager m_registrarBindingsManager;
  64. private UdpClient m_natKeepAliveSender;
  65. private GetCanonicalDomainDelegate GetCanonicalDomain_External;
  66. private SIPAssetGetDelegate<SIPAccount> GetSIPAccount_External;
  67. //private SIPAssetGetFromDirectQueryDelegate<SIPAccount> GetSIPAccountFromQuery_External;
  68. private SIPAssetPersistor<SIPRegistrarBinding> m_registrarBindingsPersistor;
  69. private SIPAuthenticateRequestDelegate SIPAuthenticateRequest_External;
  70. public SIPRegistrarDaemon(
  71. GetCanonicalDomainDelegate getDomain,
  72. SIPAssetGetDelegate<SIPAccount> getSIPAccount,
  73. //SIPAssetGetFromDirectQueryDelegate<SIPAccount> getSIPAccountFromQuery,
  74. SIPAssetPersistor<SIPRegistrarBinding> registrarBindingsPersistor,
  75. SIPAuthenticateRequestDelegate sipRequestAuthenticator
  76. ) {
  77. GetCanonicalDomain_External = getDomain;
  78. GetSIPAccount_External = getSIPAccount;
  79. //GetSIPAccountFromQuery_External = getSIPAccountFromQuery;
  80. m_registrarBindingsPersistor = registrarBindingsPersistor;
  81. SIPAuthenticateRequest_External = sipRequestAuthenticator;
  82. }
  83. public void Start() {
  84. try {
  85. logger.Debug("SIP Registrar daemon starting...");
  86. // Pre-flight checks.
  87. if (m_sipRegistrarSocketsNode == null || m_sipRegistrarSocketsNode.ChildNodes.Count == 0) {
  88. throw new ApplicationException("The SIP Registrar cannot start without at least one socket specified to listen on, please check config file.");
  89. }
  90. // Send events from this process to the monitoring socket.
  91. if (m_monitorLoopbackPort != 0) {
  92. // Events will be sent by the monitor channel to the loopback interface and this port.
  93. m_monitorEventWriter = new SIPMonitorEventWriter(m_monitorLoopbackPort);
  94. logger.Debug("Monitor channel initialised for 127.0.0.1:" + m_monitorLoopbackPort + ".");
  95. }
  96. // Configure the SIP transport layer.
  97. m_sipTransport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine(), false);
  98. m_sipTransport.PerformanceMonitorPrefix = SIPSorceryPerformanceMonitor.REGISTRAR_PREFIX;
  99. List<SIPChannel> sipChannels = SIPTransportConfig.ParseSIPChannelsNode(m_sipRegistrarSocketsNode);
  100. m_sipTransport.AddSIPChannel(sipChannels);
  101. // Create and configure the SIP Registrar core.
  102. if (m_natKeepAliveRelaySocket != null) {
  103. m_natKeepAliveSender = new UdpClient();
  104. }
  105. SIPUserAgentConfigurationManager userAgentConfigManager = new SIPUserAgentConfigurationManager(m_userAgentsConfigNode);
  106. if (m_userAgentsConfigNode == null) {
  107. logger.Warn("The UserAgent config's node was missing.");
  108. }
  109. m_registrarBindingsManager = new SIPRegistrarBindingsManager(FireSIPMonitorEvent, m_registrarBindingsPersistor, SendNATKeepAlive, m_maximumAccountBindings, userAgentConfigManager);
  110. m_registrarBindingsManager.Start();
  111. m_registrarCore = new RegistrarCore(m_sipTransport, m_registrarBindingsManager, GetSIPAccount_External, GetCanonicalDomain_External, true, true, FireSIPMonitorEvent, userAgentConfigManager, SIPAuthenticateRequest_External, m_switchboardCertificateName);
  112. m_registrarCore.Start(m_threadCount);
  113. m_sipTransport.SIPTransportRequestReceived += m_registrarCore.AddRegisterRequest;
  114. logger.Debug("SIP Registrar successfully started.");
  115. }
  116. catch (Exception excp) {
  117. logger.Error("Exception SIPRegistrarDaemon Start. " + excp.Message);
  118. }
  119. }
  120. /// <summary>
  121. /// This event handler is fired when the SIP Registrar wants to send a NATKeepAlive message to a user contact to make an attempt to keep the connection
  122. /// open through the user's NAT server. In this case the NATKeepAlive messages are forwarded onto the NATKeepAlive relay which requests the SIPTransport
  123. /// layer to multiplex a 4 byte null payload onto one of its sockets and send to the specified agent. A typical scenario would have the SIP Registrar
  124. /// firing this event every 15s to send the null payloads to each of its registered contacts.
  125. /// </summary>
  126. private void SendNATKeepAlive(NATKeepAliveMessage keepAliveMessage) {
  127. try {
  128. byte[] buffer = keepAliveMessage.ToBuffer();
  129. m_natKeepAliveSender.Send(buffer, buffer.Length, m_natKeepAliveRelaySocket);
  130. }
  131. catch (Exception natSendExcp) {
  132. logger.Warn("Exception SendNATKeepAlive " + keepAliveMessage.RemoteEndPoint + ". " + natSendExcp.Message);
  133. }
  134. }
  135. public void Stop() {
  136. try {
  137. logger.Debug("SIP Registrar daemon stopping...");
  138. logger.Debug("Shutting down Registrar Bindings Manager.");
  139. m_registrarBindingsManager.Stop();
  140. logger.Debug("Shutting down SIP Transport.");
  141. m_sipTransport.Shutdown();
  142. logger.Debug("SIP Registrar daemon stopped.");
  143. }
  144. catch (Exception excp) {
  145. logger.Error("Exception SIPRegistrarDaemon Stop. " + excp.Message);
  146. }
  147. }
  148. private void FireSIPMonitorEvent(SIPMonitorEvent sipMonitorEvent) {
  149. try {
  150. if (sipMonitorEvent != null && m_monitorEventWriter != null)
  151. {
  152. if (sipMonitorEvent is SIPMonitorConsoleEvent)
  153. {
  154. SIPMonitorConsoleEvent consoleEvent = sipMonitorEvent as SIPMonitorConsoleEvent;
  155. if (consoleEvent.EventType != SIPMonitorEventTypesEnum.NATKeepAlive)
  156. {
  157. logger.Debug("re: " + sipMonitorEvent.Message);
  158. }
  159. m_monitorEventWriter.Send(sipMonitorEvent);
  160. }
  161. else
  162. {
  163. m_monitorEventWriter.Send(sipMonitorEvent);
  164. }
  165. }
  166. }
  167. catch (Exception excp) {
  168. logger.Error("Exception FireSIPMonitorEvent. " + excp.Message);
  169. }
  170. }
  171. }
  172. }