Esempio n. 1
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="dnsClient">DNS client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>dnsClient</b> is null reference.</exception>
            internal bool Start(Dns_Client dnsClient)
            {                
                if(dnsClient == null){
                    throw new ArgumentNullException("dnsClient");
                }

                SetState(AsyncOP_State.Active);

                // Argument 'hostNameOrIP' is IP address.
                if(Net_Utils.IsIPAddress(m_HostNameOrIP)){
                    m_pIPv4Addresses.Add(IPAddress.Parse(m_HostNameOrIP));

                    SetState(AsyncOP_State.Completed);
                }
                // This is probably NetBios name.
			    if(m_HostNameOrIP.IndexOf(".") == -1){
                    try{
                        // This callback is called when BeginGetHostAddresses method has completed.
                        AsyncCallback callback = delegate(IAsyncResult ar){
                            try{
                                foreach(IPAddress ip in  System.Net.Dns.EndGetHostAddresses(ar)){
                                    if(ip.AddressFamily == AddressFamily.InterNetwork){
                                        m_pIPv4Addresses.Add(ip);
                                    }
                                    else{
                                        m_pIPv6Addresses.Add(ip);
                                    }
                                }
                            }
                            catch(Exception x){
                                m_pException = x;
                            }

                            SetState(AsyncOP_State.Completed);
                        };

                        // Start resolving host ip addresses.
                        System.Net.Dns.BeginGetHostAddresses(m_HostNameOrIP,callback,null); 
                    }
                    catch(Exception x){
                        m_pException = x;
                    }
			    }
                // Query A/AAAA records.
                else{
                    #region A records transaction

                    DNS_ClientTransaction transaction_A = dnsClient.CreateTransaction(DNS_QType.A,m_HostNameOrIP,2000);
                    transaction_A.StateChanged += delegate(object s1,EventArgs<DNS_ClientTransaction> e1){ 
                        if(e1.Value.State == DNS_ClientTransactionState.Completed){
                            lock(m_pLock){ 
                                if(e1.Value.Response.ResponseCode != DNS_RCode.NO_ERROR){
                                    m_pException = new DNS_ClientException(e1.Value.Response.ResponseCode);
                                }
                                else{
                                    foreach(DNS_rr_A record in e1.Value.Response.GetARecords()){
                                        m_pIPv4Addresses.Add(record.IP);
                                    }
                                }

                                m_Counter++;

                                // Both A and AAAA transactions are completed, we are done.
                                if(m_Counter == 2){
                                    SetState(AsyncOP_State.Completed);
                                }
                            }
                        }
                    };
                    transaction_A.Timeout += delegate(object s1,EventArgs e1){
                        lock(m_pLock){
                            m_pException = new IOException("DNS transaction timeout, no response from DNS server.");
                            m_Counter++;

                            // Both A and AAAA transactions are completed, we are done.
                            if(m_Counter == 2){
                                SetState(AsyncOP_State.Completed);
                            }
                        }
                    };
                    transaction_A.Start();
                    
                    #endregion

                    #region AAAA records transaction

                    DNS_ClientTransaction transaction_AAAA = dnsClient.CreateTransaction(DNS_QType.AAAA,m_HostNameOrIP,2000);
                    transaction_AAAA.StateChanged += delegate(object s1,EventArgs<DNS_ClientTransaction> e1){
                        if(e1.Value.State == DNS_ClientTransactionState.Completed){
                            lock(m_pLock){
                                if(e1.Value.Response.ResponseCode != DNS_RCode.NO_ERROR){
                                    m_pException = new DNS_ClientException(e1.Value.Response.ResponseCode);
                                }
                                else{
                                    foreach(DNS_rr_AAAA record in e1.Value.Response.GetAAAARecords()){
                                        m_pIPv6Addresses.Add(record.IP);
                                    }
                                }

                                m_Counter++;

                                // Both A and AAAA transactions are completed, we are done.
                                if(m_Counter == 2){
                                    SetState(AsyncOP_State.Completed);
                                }
                            }
                        }
                    };
                    transaction_AAAA.Timeout += delegate(object s1,EventArgs e1){
                        lock(m_pLock){
                            m_pException = new IOException("DNS transaction timeout, no response from DNS server.");
                            m_Counter++;

                            // Both A and AAAA transactions are completed, we are done.
                            if(m_Counter == 2){
                                SetState(AsyncOP_State.Completed);
                            }
                        }
                    };
                    transaction_AAAA.Start();

                    #endregion
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }
Esempio n. 2
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();
            }