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

Language C# Lines 195
MD5 Hash 17de38e23f06aebab5f831adf432e743
Repository https://github.com/thecc4re/sipsorcery-mono.git View Raw File
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
// ============================================================================
// FileName: SIPRegistrarDaemon.cs
//
// Description:
// A daemon to configure and start a SIP Registration Agent.
//
// Author(s):
// Aaron Clauson
//
// History:
// 29 Mar 2009	Aaron Clauson	Created.
//
// License: 
// This software is licensed under the BSD License http://www.opensource.org/licenses/bsd-license.php
//
// Copyright (c) 2009 Aaron Clauson (aaronc@blueface.ie), Blue Face Ltd, Dublin, Ireland (www.blueface.ie)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that 
// the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 
// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
// disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of Blue Face Ltd. 
// nor the names of its contributors may be used to endorse or promote products derived from this software without specific 
// prior written permission. 
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
// POSSIBILITY OF SUCH DAMAGE.
// ============================================================================

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Xml;
using SIPSorcery.Persistence;
using SIPSorcery.SIP;
using SIPSorcery.SIP.App;
using SIPSorcery.Servers;
using SIPSorcery.Sys;
using log4net;

namespace SIPSorcery.SIPRegistrar {
    public class SIPRegistrarDaemon {
        private ILog logger = AppState.logger;

        private XmlNode m_sipRegistrarSocketsNode = SIPRegistrarState.SIPRegistrarSocketsNode;
        private XmlNode m_userAgentsConfigNode = SIPRegistrarState.UserAgentsConfigNode;
        private int m_monitorLoopbackPort = SIPRegistrarState.MonitorLoopbackPort;
        private int m_maximumAccountBindings = SIPRegistrarState.MaximumAccountBindings;
        private IPEndPoint m_natKeepAliveRelaySocket = SIPRegistrarState.NATKeepAliveRelaySocket;
        private string m_switchboardCertificateName = SIPRegistrarState.SwitchboardCertificateName;
        private int m_threadCount = SIPRegistrarState.ThreadCount;

        private SIPTransport m_sipTransport;
        private SIPMonitorEventWriter m_monitorEventWriter;
        private RegistrarCore m_registrarCore;
        private SIPRegistrarBindingsManager m_registrarBindingsManager;
        private UdpClient m_natKeepAliveSender;

        private GetCanonicalDomainDelegate GetCanonicalDomain_External;
        private SIPAssetGetDelegate<SIPAccount> GetSIPAccount_External;
        //private SIPAssetGetFromDirectQueryDelegate<SIPAccount> GetSIPAccountFromQuery_External;
        private SIPAssetPersistor<SIPRegistrarBinding> m_registrarBindingsPersistor;
        private SIPAuthenticateRequestDelegate SIPAuthenticateRequest_External;
       
        public SIPRegistrarDaemon(
            GetCanonicalDomainDelegate getDomain,
            SIPAssetGetDelegate<SIPAccount> getSIPAccount,
            //SIPAssetGetFromDirectQueryDelegate<SIPAccount> getSIPAccountFromQuery,
            SIPAssetPersistor<SIPRegistrarBinding> registrarBindingsPersistor,
            SIPAuthenticateRequestDelegate sipRequestAuthenticator
            ) {
            GetCanonicalDomain_External = getDomain;
            GetSIPAccount_External = getSIPAccount;
            //GetSIPAccountFromQuery_External = getSIPAccountFromQuery;
            m_registrarBindingsPersistor = registrarBindingsPersistor;
            SIPAuthenticateRequest_External = sipRequestAuthenticator;
        }

        public void Start() {
            try {
                logger.Debug("SIP Registrar daemon starting...");

                // Pre-flight checks.
                if (m_sipRegistrarSocketsNode == null || m_sipRegistrarSocketsNode.ChildNodes.Count == 0) {
                    throw new ApplicationException("The SIP Registrar cannot start without at least one socket specified to listen on, please check config file.");
                }

                // Send events from this process to the monitoring socket.
                if (m_monitorLoopbackPort != 0) {
                    // Events will be sent by the monitor channel to the loopback interface and this port.
                    m_monitorEventWriter = new SIPMonitorEventWriter(m_monitorLoopbackPort);
                    logger.Debug("Monitor channel initialised for 127.0.0.1:" + m_monitorLoopbackPort + ".");
                }

                // Configure the SIP transport layer.
                m_sipTransport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine(), false);
                m_sipTransport.PerformanceMonitorPrefix = SIPSorceryPerformanceMonitor.REGISTRAR_PREFIX;
                List<SIPChannel> sipChannels = SIPTransportConfig.ParseSIPChannelsNode(m_sipRegistrarSocketsNode);
                m_sipTransport.AddSIPChannel(sipChannels);

                // Create and configure the SIP Registrar core.
                if (m_natKeepAliveRelaySocket != null) {
                    m_natKeepAliveSender = new UdpClient();
                }

                SIPUserAgentConfigurationManager userAgentConfigManager = new SIPUserAgentConfigurationManager(m_userAgentsConfigNode);
                if (m_userAgentsConfigNode == null) {
                    logger.Warn("The UserAgent config's node was missing.");
                }
                m_registrarBindingsManager = new SIPRegistrarBindingsManager(FireSIPMonitorEvent, m_registrarBindingsPersistor, SendNATKeepAlive, m_maximumAccountBindings, userAgentConfigManager);
                m_registrarBindingsManager.Start();

                m_registrarCore = new RegistrarCore(m_sipTransport, m_registrarBindingsManager, GetSIPAccount_External, GetCanonicalDomain_External, true, true, FireSIPMonitorEvent, userAgentConfigManager, SIPAuthenticateRequest_External, m_switchboardCertificateName);
                m_registrarCore.Start(m_threadCount);
                m_sipTransport.SIPTransportRequestReceived += m_registrarCore.AddRegisterRequest;

                logger.Debug("SIP Registrar successfully started.");
            }
            catch (Exception excp) {
                logger.Error("Exception SIPRegistrarDaemon Start. " + excp.Message);
            }
        }

        /// <summary>
        /// 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
        /// open through the user's NAT server. In this case the NATKeepAlive messages are forwarded onto the NATKeepAlive relay which requests the SIPTransport
        /// 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
        /// firing this event every 15s to send the null payloads to each of its registered contacts.
        /// </summary>
        private void SendNATKeepAlive(NATKeepAliveMessage keepAliveMessage) {
            try {
                byte[] buffer = keepAliveMessage.ToBuffer();
                m_natKeepAliveSender.Send(buffer, buffer.Length, m_natKeepAliveRelaySocket);
            }
            catch (Exception natSendExcp) {
                logger.Warn("Exception SendNATKeepAlive " + keepAliveMessage.RemoteEndPoint + ". " + natSendExcp.Message);
            }
        }

        public void Stop() {
            try {
                logger.Debug("SIP Registrar daemon stopping...");

                logger.Debug("Shutting down Registrar Bindings Manager.");
                m_registrarBindingsManager.Stop();

                logger.Debug("Shutting down SIP Transport.");
                m_sipTransport.Shutdown();

                logger.Debug("SIP Registrar daemon stopped.");
            }
            catch (Exception excp) {
                logger.Error("Exception SIPRegistrarDaemon Stop. " + excp.Message);
            }
        }

        private void FireSIPMonitorEvent(SIPMonitorEvent sipMonitorEvent) {
            try {
                if (sipMonitorEvent != null && m_monitorEventWriter != null)
                {
                    if (sipMonitorEvent is SIPMonitorConsoleEvent)
                    {
                        SIPMonitorConsoleEvent consoleEvent = sipMonitorEvent as SIPMonitorConsoleEvent;

                        if (consoleEvent.EventType != SIPMonitorEventTypesEnum.NATKeepAlive)
                        {
                            logger.Debug("re: " + sipMonitorEvent.Message);
                        }

                        m_monitorEventWriter.Send(sipMonitorEvent);
                    }
                    else
                    {
                        m_monitorEventWriter.Send(sipMonitorEvent);
                    }
                }
            }
            catch (Exception excp) {
                logger.Error("Exception FireSIPMonitorEvent. " + excp.Message);
            }
        }
    }
}
Back to Top