Example #1
0
        /// <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);
            }
        }
Example #2
0
        /// <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);
                }
            }
        }