/// <summary> /// Sends query to server. /// </summary> /// <param name="timeout">Query timeout in milli seconds.</param> /// <param name="qname">Query text.</param> /// <param name="qtype">Query type.</param> /// <param name="qclass">Query class.</param> /// <returns>Returns DNS server response.</returns> private DnsServerResponse QueryServer(int timeout, string qname, QTYPE qtype, int qclass) { if (m_DnsServers == null || m_DnsServers.Length == 0) { throw new Exception("Dns server isn't specified !"); } // See if query is in cache if (m_UseDnsCache) { DnsServerResponse resopnse = DnsCache.GetFromCache(qname, (int)qtype); if (resopnse != null) { return(resopnse); } } int queryID = Dns_Client.ID; byte[] query = CreateQuery(queryID, qname, qtype, qclass); // Create transcation and start processing it. using (DnsTransaction transaction = new DnsTransaction(this, queryID, qname, (int)qtype, timeout, query)){ ManualResetEvent wait = new ManualResetEvent(false); transaction.Timeout += delegate(object s, EventArgs e){ wait.Set(); }; transaction.Completed += delegate(object s, EventArgs e){ wait.Set(); }; m_pTransactions.Add(transaction.ID, transaction); // Start transaction processing and wait transaction to complete. transaction.Start(); wait.WaitOne(); // DNS server response received. if (transaction.Response != null) { return(transaction.Response); } // No server response - timeout. else { throw new Exception("Timeout - no response from DNS server."); } } }
/// <summary> /// Is called when IPv6 socket has received data. /// </summary> /// <param name="ar">The result of the asynchronous operation.</param> private void IPv6ReceiveCompleted(IAsyncResult ar) { try{ if (m_IsDisposed) { return; } EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); int count = m_pIPv6Socket.EndReceiveFrom(ar, ref remoteEP); DnsServerResponse serverResponse = ParseQuery((byte[])ar.AsyncState); DnsTransaction transaction = null; // Pass response to transaction. if (m_pTransactions.TryGetValue(serverResponse.ID, out transaction)) { transaction.ProcessResponse(serverResponse); } // No such transaction or transaction has timed out before answer received. //else{ //} // Cache query. if (m_UseDnsCache && serverResponse.ResponseCode == RCODE.NO_ERROR) { DnsCache.AddToCache(transaction.QName, transaction.QType, serverResponse); } } catch { // Skip receiving socket errors. } try{ StartWaitingIPv6Packet(); } catch { } }
public DnsTransaction.ResourceRecord lookup(DnsTransaction.QuestionRecord record) { uint qid = getDnsQueryId(record); using (MySqlCommand sql = new MySqlCommand("SELECT (ttl,data) FROM records WHERE query=@query ORDER BY cached DESC LIMIT 1", db)) { sql.Parameters.AddWithValue("@query", qid); sql.Prepare(); using (MySqlDataReader results = sql.ExecuteReader()) { byte[] chunk = new byte[1024]; long n = 0; long r; MemoryStream s = new MemoryStream(); do { r = results.GetBytes(1, n, chunk, 0,chunk.Length); s.Write(chunk, 0,(int) r); } while(r == chunk.Length); return new DnsTransaction.ResourceRecord(record, results.GetUInt32(0), s.ToArray()); } } }
public uint getDnsQueryId(DnsTransaction.QuestionRecord query, uint labelId = 0) { if (labelId == 0) labelId = getDnsLabelId(query.name); MySqlCommand sql = new MySqlCommand("SELECT (id) FROM queries WHERE label=@label AND type=@type AND class=@class LIMIT 1", db); sql.Parameters.AddWithValue("@label", labelId.ToString()); sql.Parameters.AddWithValue("@type", (uint)query._type); sql.Parameters.AddWithValue("@class", (uint)query._class); sql.Prepare(); object r = sql.ExecuteScalar(); if (r != null) return (uint)r; // Doesn't Exist, lets create sql.CommandText = "INSERT INTO queries (label,type,class) VALUES (@label,@type,@class)"; sql.Prepare(); sql.ExecuteNonQuery(); return (uint)sql.LastInsertedId; }