/// <summary> /// Constructor. /// </summary> /// <param name="request">The DNS request.</param> /// <param name="nameServers">The name server IP addresses.</param> /// <param name="maxSendCount"> /// The number of times a request should be sent to a /// particular name server. /// </param> /// <param name="timeout">The timeout to use for each request retry.</param> /// <param name="callback">The deleate to be called when the operation completes (or <c>null</c>).</param> /// <param name="state">The application defined state (or <c>null</c>).</param> /// <remarks> /// <para> /// Note that a random name server endpoint from the list will be /// selected and moved to the head of the list. /// </para> /// <para> /// This initializes <see cref="SendCount" /> to 1 under the assumption /// that the first request will be sent out immediately. /// </para> /// </remarks> public DnsRetryAsyncResult(DnsRequest request, IPAddress[] nameServers, int maxSendCount, TimeSpan timeout, AsyncCallback callback, object state) : base(null, callback, state) { this.NameServers = new List <IPAddress>(nameServers.Length); for (int i = 0; i < nameServers.Length; i++) { this.NameServers.Add(nameServers[i]); } this.Request = request; this.Response = null; this.MaxSendCount = maxSendCount; this.SendCount = 1; this.Timeout = timeout; RandomizeNameServers(); }
/// <summary> /// Initiates an asynchronous DNS request to a name server. /// </summary> /// <param name="nameServer">IP address of the name server.</param> /// <param name="request">The DNS request.</param> /// <param name="timeout">The maximum time to wait for a response.</param> /// <param name="callback">The delegate to be called when the operation completes (or <c>null</c>).</param> /// <param name="state">Application state to be passed to the callback (or <c>null</c>).</param> /// <returns>The IAsyncResult object to be used to track the operation.</returns> /// <remarks> /// <note> /// This DNS resolver does not implement any local caching of DNS /// responses. /// </note> /// <para> /// This method in combination with <see cref="EndQuery" /> does not perform any /// iterative processing on the request or implement any retry behavior. It simply /// sends a DNS message to the name server and returns the response message or throws a /// <see cref="TimeoutException" />. /// </para> /// <note> /// The method will initialize the request's <see cref="DnsMessage.QID" /> /// property with a unique 16-bit query ID. /// </note> /// </remarks> public static IAsyncResult BeginQuery(IPAddress nameServer, DnsRequest request, TimeSpan timeout, AsyncCallback callback, object state) { DnsAsyncResult arDns; byte[] packet; int cbPacket; lock (syncLock) { arDns = PrepareQuery(request, timeout, callback, state); packet = request.FormatPacket(out cbPacket); arDns.TimerStart = HiResTimer.Count; request.Trace(TraceSubSystem, 0, nameServer, null); arDns.DnsSocket.Socket.SendTo(packet, 0, cbPacket, SocketFlags.None, new IPEndPoint(nameServer, NetworkPort.DNS)); arDns.Started(); } return(arDns); }
/// <summary> /// Constructor. /// </summary> /// <param name="remoteEP">The <see cref="IPEndPoint" /> of the DNS resolver making the request.</param> /// <param name="request">The received <see cref="DnsRequest" />.</param> internal DnsServerEventArgs(IPEndPoint remoteEP, DnsRequest request) { this.RemoteEP = remoteEP; this.Request = request; this.Response = null; }
/// <summary> /// Handles received packets. /// </summary> /// <param name="ar">The <see cref="IAsyncResult" /> instance.</param> private void OnReceive(IAsyncResult ar) { DnsRequest request = null; int cbRecv; IPEndPoint ep; try { cbRecv = ((EnhancedSocket)ar.AsyncState).EndReceiveFrom(ar, ref remoteEP); } catch { cbRecv = 0; } if (sock == null) { return; // The server has stopped } if (cbRecv != 0) { // Parse the request packet try { request = new DnsRequest(); request.ParsePacket(recvBuf, cbRecv); } catch (Exception e) { SysLog.LogException(e); } } // Save the remote EP and then initiate another async // packet receive. ep = (IPEndPoint)remoteEP; remoteEP = new IPEndPoint(IPAddress.Any, 0); sock.BeginReceiveFrom(recvBuf, 0, recvBuf.Length, SocketFlags.None, ref remoteEP, onReceive, sock); // Process the request and transmit the response (if there is one). if (request != null && RequestEvent != null) { var args = new DnsServerEventArgs(ep, request); RequestEvent(this, args); if (args.Response != null) { byte[] sendBuf; int cbSend; // $todo(jeff.lill): // // Remove this exception code after figuring out why the // response's QName field is sometimes NULL. try { sendBuf = args.Response.FormatPacket(out cbSend); } catch { SysLog.LogError("DNS Formatting Error:\r\n\r\n" + args.Request.GetTraceDetails(ep.Address) + "\r\n" + args.Response.GetTraceDetails(ep.Address)); throw; } lock (syncLock) { if (sock != null) { sock.SendTo(sendBuf, cbSend, SocketFlags.None, args.RemoteEP); } } } } }
/// <summary> /// Performs a more advanced query that load balances against a set of /// DNS server endpoints and also implements retry behaviors. /// </summary> /// <param name="nameServers">The set of name server IP addresses.</param> /// <param name="request">The DNS request.</param> /// <param name="timeout">The timeout to use for the initial request as well as the retries.</param> /// <param name="maxSendCount">The maximum number of requests to send to any single name server.</param> /// <returns>The received DNS response message.</returns> /// <remarks> /// <note> /// This DNS resolver does not implement any local caching of DNS /// responses. /// </note> /// </remarks> public static DnsResponse QueryWithRetry(IPAddress[] nameServers, DnsRequest request, TimeSpan timeout, int maxSendCount) { var ar = BeginQueryWithRetry(nameServers, request, timeout, maxSendCount, null, null); return(EndQueryWithRetry(ar)); }
/// <summary> /// Transmits a DNS request to a name server and then waits for and /// then returns the response. /// </summary> /// <param name="nameServer">IP address of the name server.</param> /// <param name="request">The DNS request.</param> /// <param name="timeout">The maximum time to wait for a response.</param> /// <returns>The query response.</returns> /// <remarks> /// <note> /// This DNS resolver does not implement any local caching of DNS /// responses. /// </note> /// <para> /// This method does not perform any iterative processing on the request /// or implement any retry behavior. It simply sends a DNS message to the /// name server and returns the response message or throws a /// <see cref="TimeoutException" />. /// </para> /// <note> /// The method will initialize the request's <see cref="DnsMessage.QID" /> /// property with a unique 16-bit query ID. /// </note> /// <note> /// This method performs no checks to verify that the /// response returned actually answers the question posed in the /// request. The only validation performed is to verify that the /// message is a valid response and that its QID matches that /// of the request. /// </note> /// </remarks> public static DnsResponse Query(IPAddress nameServer, DnsRequest request, TimeSpan timeout) { var arDns = BeginQuery(nameServer, request, timeout, null, null); return(EndQuery(arDns)); }