/// <summary>
        /// Smart host relay session constructor.
        /// </summary>
        /// <param name="server">Owner relay server.</param>
        /// <param name="localBindInfo">Local bind info.</param>
        /// <param name="realyItem">Relay item.</param>
        /// <param name="smartHosts">Smart hosts.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>server</b>,<b>localBindInfo</b>,<b>realyItem</b> or <b>smartHosts</b>is null.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        internal Relay_Session(Relay_Server server,
                               IPBindInfo localBindInfo,
                               Relay_QueueItem realyItem,
                               Relay_SmartHost[] smartHosts)
        {
            if (server == null)
            {
                throw new ArgumentNullException("server");
            }
            if (localBindInfo == null)
            {
                throw new ArgumentNullException("localBindInfo");
            }
            if (realyItem == null)
            {
                throw new ArgumentNullException("realyItem");
            }
            if (smartHosts == null)
            {
                throw new ArgumentNullException("smartHosts");
            }

            m_pServer        = server;
            m_pLocalBindInfo = localBindInfo;
            m_pRelayItem     = realyItem;
            m_pSmartHosts    = smartHosts;

            m_RelayMode         = Relay_Mode.SmartHost;
            m_SessionID         = Guid.NewGuid().ToString();
            m_SessionCreateTime = DateTime.Now;
            m_pTargets          = new List <Relay_Target>();
        }
        /// <summary>
        /// Completes relay session and does clean up. This method is thread-safe.
        /// </summary>
        /// <param name="exception">Exception happened or null if relay completed successfully.</param>
        public void Dispose(Exception exception)
        {
            try
            {
                lock (this)
                {
                    if (m_IsDisposed)
                    {
                        return;
                    }
                    try
                    {
                        m_pServer.OnSessionCompleted(this, exception);
                    }
                    catch {}
                    m_pServer.Sessions.Remove(this);
                    m_IsDisposed = true;

                    m_pLocalBindInfo = null;
                    m_pRelayItem     = null;
                    m_pSmartHosts    = null;
                    if (m_pSmtpClient != null)
                    {
                        m_pSmtpClient.Dispose();
                        m_pSmtpClient = null;
                    }
                    m_pTargets = null;
                    if (m_pActiveTarget != null)
                    {
                        m_pServer.RemoveIpUsage(m_pActiveTarget.Target.Address);
                        m_pActiveTarget = null;
                    }
                    m_pServer = null;
                }
            }
            catch (Exception x)
            {
                if (m_pServer != null)
                {
                    m_pServer.OnError(x);
                }
            }
        }
        /// <summary>
        /// Dns relay session constructor.
        /// </summary>
        /// <param name="server">Owner relay server.</param>
        /// <param name="localBindInfo">Local bind info.</param>
        /// <param name="realyItem">Relay item.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>server</b>,<b>localBindInfo</b> or <b>realyItem</b> is null.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        internal Relay_Session(Relay_Server server, IPBindInfo localBindInfo, Relay_QueueItem realyItem)
        {
            if (server == null)
            {
                throw new ArgumentNullException("server");
            }
            if (localBindInfo == null)
            {
                throw new ArgumentNullException("localBindInfo");
            }
            if (realyItem == null)
            {
                throw new ArgumentNullException("realyItem");
            }

            m_pServer = server;
            m_pLocalBindInfo = localBindInfo;
            m_pRelayItem = realyItem;

            m_SessionID = Guid.NewGuid().ToString();
            m_SessionCreateTime = DateTime.Now;
            m_pTargets = new List<Relay_Target>();
        }
        /// <summary>
        /// Completes relay session and does clean up. This method is thread-safe.
        /// </summary>
        /// <param name="exception">Exception happened or null if relay completed successfully.</param>
        public void Dispose(Exception exception)
        {
            try
            {
                lock (this)
                {
                    if (m_IsDisposed)
                    {
                        return;
                    }
                    try
                    {
                        m_pServer.OnSessionCompleted(this, exception);
                    }
                    catch {}
                    m_pServer.Sessions.Remove(this);
                    m_IsDisposed = true;

                    m_pLocalBindInfo = null;
                    m_pRelayItem = null;
                    m_pSmartHosts = null;
                    if (m_pSmtpClient != null)
                    {
                        m_pSmtpClient.Dispose();
                        m_pSmtpClient = null;
                    }
                    m_pTargets = null;
                    if (m_pActiveTarget != null)
                    {
                        m_pServer.RemoveIpUsage(m_pActiveTarget.Target.Address);
                        m_pActiveTarget = null;
                    }
                    m_pServer = null;
                }
            }
            catch (Exception x)
            {
                if (m_pServer != null)
                {
                    m_pServer.OnError(x);
                }
            }
        }
Exemple #5
0
        /// <summary>
        /// Processes relay queue.
        /// </summary>
        private void Run()
        {
            while (m_IsRunning)
            {
                try
                {
                    // Bind info has changed, create new local end points.
                    if (m_HasBindingsChanged)
                    {
                        m_pLocalEndPoints.Clear();

                        foreach (IPBindInfo binding in m_pBindings)
                        {
                            if (binding.IP == IPAddress.Any)
                            {
                                foreach (IPAddress ip in Dns.GetHostAddresses(""))
                                {
                                    if (ip.AddressFamily == AddressFamily.InterNetwork)
                                    {
                                        IPBindInfo b = new IPBindInfo(binding.HostName,
                                                                      binding.Protocol,
                                                                      ip,
                                                                      25);
                                        if (!m_pLocalEndPoints.Contains(b))
                                        {
                                            m_pLocalEndPoints.Add(b);
                                        }
                                    }
                                }
                            }
                            else if (binding.IP == IPAddress.IPv6Any)
                            {
                                foreach (IPAddress ip in Dns.GetHostAddresses(""))
                                {
                                    if (ip.AddressFamily == AddressFamily.InterNetworkV6)
                                    {
                                        IPBindInfo b = new IPBindInfo(binding.HostName,
                                                                      binding.Protocol,
                                                                      ip,
                                                                      25);
                                        if (!m_pLocalEndPoints.Contains(b))
                                        {
                                            m_pLocalEndPoints.Add(b);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                IPBindInfo b = new IPBindInfo(binding.HostName,
                                                              binding.Protocol,
                                                              binding.IP,
                                                              25);
                                if (!m_pLocalEndPoints.Contains(b))
                                {
                                    m_pLocalEndPoints.Add(b);
                                }
                            }
                        }

                        m_HasBindingsChanged = false;
                    }

                    // There are no local end points specified.
                    if (m_pLocalEndPoints.Count == 0)
                    {
                        Thread.Sleep(10);
                    }
                    // Maximum allowed relay sessions exceeded, skip adding new ones.
                    else if (m_MaxConnections != 0 && m_pSessions.Count >= m_MaxConnections)
                    {
                        Thread.Sleep(10);
                    }
                    else
                    {
                        Relay_QueueItem item = null;

                        // Get next queued message from highest possible priority queue.
                        foreach (Relay_Queue queue in m_pQueues)
                        {
                            item = queue.DequeueMessage();
                            // There is queued message.
                            if (item != null)
                            {
                                break;
                            }
                            // No messages in this queue, see next lower priority queue.
                        }

                        // There are no messages in any queue.
                        if (item == null)
                        {
                            Thread.Sleep(10);
                        }
                        // Create new session for queued relay item.
                        else
                        {
                            // Get round-robin local end point for that session.
                            // This ensures if multiple network connections, all will be load balanced.
                            IPBindInfo localBindInfo = m_pLocalEndPoints.Next();

                            if (m_RelayMode == Relay_Mode.Dns)
                            {
                                Relay_Session session = new Relay_Session(this, localBindInfo, item);
                                m_pSessions.Add(session);
                                ThreadPool.QueueUserWorkItem(session.Start);
                            }
                            else if (m_RelayMode == Relay_Mode.SmartHost)
                            {
                                // Get smart hosts in balance mode order.
                                Relay_SmartHost[] smartHosts = null;
                                if (m_SmartHostsBalanceMode == BalanceMode.FailOver)
                                {
                                    smartHosts = m_pSmartHosts.ToArray();
                                }
                                else
                                {
                                    smartHosts = m_pSmartHosts.ToCurrentOrderArray();
                                }

                                Relay_Session session = new Relay_Session(this,
                                                                          localBindInfo,
                                                                          item,
                                                                          smartHosts);
                                m_pSessions.Add(session);
                                ThreadPool.QueueUserWorkItem(session.Start);
                            }
                        }
                    }
                }
                catch (Exception x)
                {
                    OnError(x);
                }
            }
        }