Exemple #1
0
            /// <summary>
            /// Starts looking up MX records for specified domain.
            /// </summary>
            /// <param name="dnsClient">DNS client.</param>
            /// <param name="domain">Domain name.</param>
            /// <param name="domainIsCName">If true domain name is CNAME(alias).</param>
            /// <exception cref="ArgumentNullException">Is riased when <b>dnsClient</b> or <b>domain</b> is null reference.</exception>
            private void LookupMX(Dns_Client dnsClient,string domain,bool domainIsCName)
            {
                if(dnsClient == null){
                    throw new ArgumentNullException("dnsClient");
                }
                if(domain == null){
                    throw new ArgumentNullException("domain");
                }

                // Try to get MX records.
                DNS_ClientTransaction transaction_MX = dnsClient.CreateTransaction(DNS_QType.MX,domain,2000);
                transaction_MX.StateChanged += delegate(object s1,EventArgs<DNS_ClientTransaction> e1){
                    try{
                        if(e1.Value.State == DNS_ClientTransactionState.Completed){
                            // No errors.
                            if(e1.Value.Response.ResponseCode == DNS_RCode.NO_ERROR){
                                List<DNS_rr_MX> mxRecords = new List<DNS_rr_MX>();
                                foreach(DNS_rr_MX mx in e1.Value.Response.GetMXRecords()){
                                    // Skip invalid MX records.
                                    if(string.IsNullOrEmpty(mx.Host)){
                                    }
                                    else{
                                        mxRecords.Add(mx);
                                    }
                                }

                                // Use MX records.
                                if(mxRecords.Count > 0){
                                    m_pHosts = new HostEntry[mxRecords.Count];
                                    
                                    // Create name to index map, so we can map asynchronous A/AAAA lookup results back to MX priority index.
                                    Dictionary<string,int> name_to_index_map = new Dictionary<string,int>();
                                    List<string>           lookupQueue       = new List<string>();

                                    // Process MX records.
                                    for(int i=0;i<m_pHosts.Length;i++){
                                        DNS_rr_MX mx = mxRecords[i];
                                    
                                        IPAddress[] ips = Get_A_or_AAAA_FromResponse(mx.Host,e1.Value.Response);
                                        // No A or AAAA records in addtional answers section for MX, we need todo new query for that.
                                        if(ips.Length == 0){
                                            name_to_index_map[mx.Host] = i;
                                            lookupQueue.Add(mx.Host);
                                        }
                                        else{
                                            m_pHosts[i] = new HostEntry(mx.Host,ips,null);
                                        }                                        
                                    }

                                    // We have MX records which A or AAAA records not provided in DNS response, lookup them.
                                    if(lookupQueue.Count > 0){
                                        GetHostsAddressesAsyncOP op = new GetHostsAddressesAsyncOP(lookupQueue.ToArray(),true);
                                        // This event is raised when lookup completes asynchronously.
                                        op.CompletedAsync += delegate(object s2,EventArgs<GetHostsAddressesAsyncOP> e2){
                                            LookupCompleted(op,name_to_index_map);
                                        };
                                        // Lookup completed synchronously.
                                        if(!dnsClient.GetHostsAddressesAsync(op)){
                                            LookupCompleted(op,name_to_index_map);
                                        }
                                    }
                                    // All MX records resolved.
                                    else{
                                        SetState(AsyncOP_State.Completed);
                                    }
                                }
                                // Use CNAME as initial domain name.
                                else if(e1.Value.Response.GetCNAMERecords().Length > 0){
                                    if(domainIsCName){
                                        m_pException = new Exception("CNAME to CNAME loop dedected.");
                                        SetState(AsyncOP_State.Completed);
                                    }
                                    else{
                                        LookupMX(dnsClient,e1.Value.Response.GetCNAMERecords()[0].Alias,true);
                                    }
                                }
                                // Use domain name as MX.
                                else{
                                    m_pHosts = new HostEntry[1];

                                    // Create name to index map, so we can map asynchronous A/AAAA lookup results back to MX priority index.
                                    Dictionary<string,int> name_to_index_map = new Dictionary<string,int>();
                                    name_to_index_map.Add(domain,0);

                                    GetHostsAddressesAsyncOP op = new GetHostsAddressesAsyncOP(new string[]{domain});
                                    // This event is raised when lookup completes asynchronously.
                                    op.CompletedAsync += delegate(object s2,EventArgs<GetHostsAddressesAsyncOP> e2){
                                        LookupCompleted(op,name_to_index_map);
                                    };
                                    // Lookup completed synchronously.
                                    if(!dnsClient.GetHostsAddressesAsync(op)){
                                        LookupCompleted(op,name_to_index_map);
                                    }
                                }
                            }
                            // DNS server returned error, just return error.
                            else{
                                m_pException = new DNS_ClientException(e1.Value.Response.ResponseCode);
                                SetState(AsyncOP_State.Completed);
                            }
                        }
                        transaction_MX.Timeout += delegate(object s2,EventArgs e2){
                            m_pException = new IOException("DNS transaction timeout, no response from DNS server.");
                            SetState(AsyncOP_State.Completed);
                        };
                    }
                    catch(Exception x){
                        m_pException = x;
                        SetState(AsyncOP_State.Completed);
                    }
                };
                transaction_MX.Start();
            }
Exemple #2
0
            /// <summary>
            /// This method is called when A/AAAA lookup has completed.
            /// </summary>
            /// <param name="op">Asynchronous operation.</param>
            /// <param name="name_to_index">Dns name to index lookup table.</param>
            /// <exception cref="ArgumentNullException">Is raised when <b>op</b> or <b>name_to_index</b> is null reference value.</exception>
            private void LookupCompleted(GetHostsAddressesAsyncOP op,Dictionary<string,int> name_to_index)
            {
                if(op == null){
                    throw new ArgumentNullException("op");
                }
                                
                if(op.Error != null){
                    // If we have any resolved DNS, we don't return error if any.
                    bool anyResolved = false;
                    foreach(HostEntry host in m_pHosts){
                        if(host != null){
                            anyResolved = true;

                            break;
                        }
                    }
                    if(!anyResolved){
                        m_pException = op.Error;
                    }
                }
                else{
                    foreach(HostEntry host in op.HostEntries){
                        m_pHosts[name_to_index[host.HostName]] = host;
                    }                   
                }                

                op.Dispose();

                // Remove unresolved DNS entries from response.
                List<HostEntry> retVal = new List<HostEntry>();
                foreach(HostEntry host in m_pHosts){
                    if(host != null){
                        retVal.Add(host);
                    }
                }
                m_pHosts = retVal.ToArray();

                SetState(AsyncOP_State.Completed);
            }
Exemple #3
0
        /// <summary>
        /// Starts resolving multiple host IPv4 and IPv6 addresses.
        /// </summary>
        /// <param name="op">Asynchronous operation.</param>
        /// <returns>Returns true if aynchronous operation is pending (The <see cref="GetHostsAddressesAsyncOP.CompletedAsync"/> event is raised upon completion of the operation).
        /// Returns false if operation completed synchronously.</returns>
        /// <exception cref="ObjectDisposedException">Is raised when this object is disposed and and this method is accessed.</exception>
        /// <exception cref="ArgumentNullException">Is raised when <b>op</b> is null reference.</exception>
        public bool GetHostsAddressesAsync(GetHostsAddressesAsyncOP op)
        {
            if(m_IsDisposed){
                throw new ObjectDisposedException(this.GetType().Name);
            }
            if(op == null){
                throw new ArgumentNullException("op");
            }
            if(op.State != AsyncOP_State.WaitingForStart){
                throw new ArgumentException("Invalid argument 'op' state, 'op' must be in 'AsyncOP_State.WaitingForStart' state.","op");
            }

            return op.Start(this);
        }