/// <summary> /// Starts connecting to best target. /// </summary> private void BeginConnect() { // No tagets, abort relay. if (m_pTargets.Count == 0) { LogText("No relay target(s) for '" + m_pRelayItem.To + "', aborting."); Dispose(new Exception("No relay target(s) for '" + m_pRelayItem.To + "', aborting.")); return; } // If maximum connections to specified target exceeded and there are more targets, try to get limit free target. if (m_pServer.MaxConnectionsPerIP > 0) { // For DNS or load-balnced smart host relay, search free target if any. if (m_pServer.RelayMode == Relay_Mode.Dns || m_pServer.SmartHostsBalanceMode == BalanceMode.LoadBalance) { foreach (Relay_Target t in m_pTargets) { // We found free target, stop searching. if (m_pServer.TryAddIpUsage(m_pTargets[0].Target.Address)) { m_pActiveTarget = t; m_pTargets.Remove(t); break; } } } // Smart host fail-over mode, just check if it's free. else { // Smart host IP limit not reached. if (m_pServer.TryAddIpUsage(m_pTargets[0].Target.Address)) { m_pActiveTarget = m_pTargets[0]; m_pTargets.RemoveAt(0); } } } // Just get first target. else { m_pActiveTarget = m_pTargets[0]; m_pTargets.RemoveAt(0); } // If all targets has exeeded maximum allowed connection per IP address, end relay session, // next relay cycle will try to relay again. if (m_pActiveTarget == null) { LogText("All targets has exeeded maximum allowed connection per IP address, skip relay."); Dispose(new Exception("All targets has exeeded maximum allowed connection per IP address, skip relay.")); return; } m_pSmtpClient.BeginConnect(new IPEndPoint(m_pLocalBindInfo.IP, 0), m_pActiveTarget.Target, false, new AsyncCallback(this.ConnectCallback), null); }
/// <summary> /// Starts connecting to best target. /// </summary> private void BeginConnect() { // No tagets, abort relay. if (m_pTargets.Count == 0) { LogText("No relay target(s) for '" + m_pRelayItem.To + "', aborting."); Dispose(new Exception("No relay target(s) for '" + m_pRelayItem.To + "', aborting.")); return; } // Maximum connections per IP limited. if (m_pServer.MaxConnectionsPerIP > 0) { // For DNS or load-balnced smart host relay, search free target if any. if (m_pServer.RelayMode == Relay_Mode.Dns || m_pServer.SmartHostsBalanceMode == BalanceMode.LoadBalance) { foreach (Relay_Target t in m_pTargets) { // Get local IP binding for remote IP. m_pLocalBindInfo = m_pServer.GetLocalBinding(t.Target.Address); // We have suitable local IP binding for the target. if (m_pLocalBindInfo != null) { // We found free target, stop searching. if (m_pServer.TryAddIpUsage(t.Target.Address)) { m_pActiveTarget = t; m_pTargets.Remove(t); break; } // Connection per IP limit reached. else { LogText("Skipping relay target (" + t.HostName + "->" + t.Target.Address + "), maximum connections to the specified IP has reached."); } } // No suitable local IP binding, try next target. else { LogText("Skipping relay target (" + t.HostName + "->" + t.Target.Address + "), no suitable local IPv4/IPv6 binding."); } } } // Smart host fail-over mode, just check if it's free. else { // Get local IP binding for remote IP. m_pLocalBindInfo = m_pServer.GetLocalBinding(m_pTargets[0].Target.Address); // We have suitable local IP binding for the target. if (m_pLocalBindInfo != null) { // Smart host IP limit not reached. if (m_pServer.TryAddIpUsage(m_pTargets[0].Target.Address)) { m_pActiveTarget = m_pTargets[0]; m_pTargets.RemoveAt(0); } // Connection per IP limit reached. else { LogText("Skipping relay target (" + m_pTargets[0].HostName + "->" + m_pTargets[0].Target.Address + "), maximum connections to the specified IP has reached."); } } // No suitable local IP binding, try next target. else { LogText("Skipping relay target (" + m_pTargets[0].HostName + "->" + m_pTargets[0].Target.Address + "), no suitable local IPv4/IPv6 binding."); } } } // Just get first target. else { // Get local IP binding for remote IP. m_pLocalBindInfo = m_pServer.GetLocalBinding(m_pTargets[0].Target.Address); // We have suitable local IP binding for the target. if (m_pLocalBindInfo != null) { m_pActiveTarget = m_pTargets[0]; m_pTargets.RemoveAt(0); } // No suitable local IP binding, try next target. else { LogText("Skipping relay target (" + m_pTargets[0].HostName + "->" + m_pTargets[0].Target.Address + "), no suitable local IPv4/IPv6 binding."); } } // We don't have suitable local IP end point for relay target. // This may heppen for example: if remote server supports only IPv6 and we don't have local IPv6 local end point. if (m_pLocalBindInfo == null) { LogText("No suitable IPv4/IPv6 local IP endpoint for relay target."); Dispose(new Exception("No suitable IPv4/IPv6 local IP endpoint for relay target.")); return; } // If all targets has exeeded maximum allowed connection per IP address, end relay session, // next relay cycle will try to relay again. if (m_pActiveTarget == null) { LogText("All targets has exeeded maximum allowed connection per IP address, skip relay."); Dispose(new Exception("All targets has exeeded maximum allowed connection per IP address, skip relay.")); return; } // Set SMTP host name. m_pSmtpClient.LocalHostName = m_pLocalBindInfo.HostName; // Start connecting to remote end point. TCP_Client.ConnectAsyncOP connectOP = new TCP_Client.ConnectAsyncOP(new IPEndPoint(m_pLocalBindInfo.IP, 0), m_pActiveTarget.Target, false, null); connectOP.CompletedAsync += delegate(object s, EventArgs <TCP_Client.ConnectAsyncOP> e){ ConnectCompleted(connectOP); }; if (!m_pSmtpClient.ConnectAsync(connectOP)) { ConnectCompleted(connectOP); } }