/// <summary> /// Smart host relay session constructor. /// </summary> /// <param name="server">Owner relay server.</param> /// <param name="realyItem">Relay item.</param> /// <param name="smartHosts">Smart hosts.</param> /// <exception cref="ArgumentNullException">Is raised when <b>server</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, Relay_QueueItem realyItem, Relay_SmartHost[] smartHosts) { if (server == null) { throw new ArgumentNullException("server"); } if (realyItem == null) { throw new ArgumentNullException("realyItem"); } if (smartHosts == null) { throw new ArgumentNullException("smartHosts"); } m_pServer = server; 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>(); m_pSmtpClient = new SMTP_Client(); }
/// <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> /// Processes relay queue. /// </summary> private void Run() { while (m_IsRunning) { try { // Bind info has changed, create new local end points. if (m_HasBindingsChanged) { m_pLocalEndPointIPv4.Clear(); m_pLocalEndPointIPv6.Clear(); foreach (IPBindInfo binding in m_pBindings) { if (binding.IP == IPAddress.Any) { foreach (IPAddress ip in System.Net.Dns.GetHostAddresses("")) { if (ip.AddressFamily == AddressFamily.InterNetwork) { IPBindInfo b = new IPBindInfo(binding.HostName, binding.Protocol, ip, 25); if (!m_pLocalEndPointIPv4.Contains(b)) { m_pLocalEndPointIPv4.Add(b); } } } } else if (binding.IP == IPAddress.IPv6Any) { foreach (IPAddress ip in System.Net.Dns.GetHostAddresses("")) { if (ip.AddressFamily == AddressFamily.InterNetworkV6) { IPBindInfo b = new IPBindInfo(binding.HostName, binding.Protocol, ip, 25); if (!m_pLocalEndPointIPv6.Contains(b)) { m_pLocalEndPointIPv6.Add(b); } } } } else { IPBindInfo b = new IPBindInfo(binding.HostName, binding.Protocol, binding.IP, 25); if (binding.IP.AddressFamily == AddressFamily.InterNetwork) { if (!m_pLocalEndPointIPv4.Contains(b)) { m_pLocalEndPointIPv4.Add(b); } } else { if (!m_pLocalEndPointIPv6.Contains(b)) { m_pLocalEndPointIPv6.Add(b); } } } } m_HasBindingsChanged = false; } // There are no local end points specified. if (m_pLocalEndPointIPv4.Count == 0 && m_pLocalEndPointIPv6.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 { // Relay item has relay target server specified. if (item.TargetServer != null) { Relay_Session session = new Relay_Session(this, item, new Relay_SmartHost[] { item.TargetServer }); m_pSessions.Add(session); ThreadPool.QueueUserWorkItem(new WaitCallback(session.Start)); } else if (m_RelayMode == Relay_Mode.Dns) { Relay_Session session = new Relay_Session(this, item); m_pSessions.Add(session); ThreadPool.QueueUserWorkItem(new WaitCallback(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, item, smartHosts); m_pSessions.Add(session); ThreadPool.QueueUserWorkItem(new WaitCallback(session.Start)); } } } } catch (Exception x) { OnError(x); } } }