public override DnsResponseMessage Query( IPEndPoint server, DnsRequestMessage request, TimeSpan timeout) { UdpClient udpClient = GetNextUdpClient(server.AddressFamily); // -1 indicates infinite int timeoutInMillis = timeout.TotalMilliseconds >= int.MaxValue ? -1 : (int)timeout.TotalMilliseconds; udpClient.Client.ReceiveTimeout = timeoutInMillis; udpClient.Client.SendTimeout = timeoutInMillis; bool mustDispose = false; try { using (var writer = new DnsDatagramWriter()) { GetRequestData(request, writer); udpClient.Client.SendTo(writer.Data.Array, writer.Data.Offset, writer.Data.Count, SocketFlags.None, server); } var readSize = udpClient.Available > MaxSize ? udpClient.Available : MaxSize; using (var memory = new PooledBytes(readSize)) { var received = udpClient.Client.Receive(memory.Buffer, 0, readSize, SocketFlags.None); var response = GetResponseMessage(new ArraySegment <byte>(memory.Buffer, 0, received)); Enqueue(server.AddressFamily, udpClient); return(response); } } catch { mustDispose = true; throw; } finally { if (!_enableClientQueue || mustDispose) { try { #if !NET45 udpClient.Dispose(); #else udpClient.Close(); #endif } catch { } } } }
private async Task HandleResponseSocketPooledAsync(Socket server, EndPoint remoteEndpoint, ArraySegment <byte> receiveBuffer) { using (var memory = new PooledBytes(Response.Length)) { //Buffer.BlockCopy(Response, 0, memory.Buffer, 0, Response.Length); memory.Buffer[0] = receiveBuffer.Array[0]; memory.Buffer[1] = receiveBuffer.Array[1]; for (var i = 2; i < Response.Length; i++) { memory.Buffer[i] = Response[i]; } await server.SendToAsync(new ArraySegment <byte>(memory.Buffer, 0, memory.Buffer.Length), SocketFlags.None, remoteEndpoint); } }
private void HandleResponseSocketPooled(Socket server, EndPoint remoteEndpoint, byte[] receiveBuffer) { using (var memory = new PooledBytes(Response.Length)) { //Buffer.BlockCopy(Response, 0, memory.Buffer, 0, Response.Length); memory.Buffer[0] = receiveBuffer[0]; memory.Buffer[1] = receiveBuffer[1]; for (var i = 2; i < Response.Length; i++) { memory.Buffer[i] = Response[i]; } server.SendTo(memory.Buffer, 0, memory.Buffer.Length, SocketFlags.None, remoteEndpoint); } }
private void HandleRequest(int id) { var obj = new object(); while (!_cancelSource.IsCancellationRequested) { try { using (var memory = new PooledBytes(512)) { EndPoint endpoint = AnyIPEndPoint; var result = _server.Client.ReceiveFrom(memory.Buffer, 0, memory.Buffer.Length, SocketFlags.None, ref endpoint); Interlocked.Increment(ref _workerHitCounter[id]); HandleResponseSocketPooled(_server.Client, endpoint, memory.Buffer); } } catch { break; } } }
private async Task HandleRequestAsync(int id) { var obj = new object(); while (!_cancelSource.IsCancellationRequested) { try { using (var memory = new PooledBytes(512)) { var segment = new ArraySegment <byte>(memory.Buffer, 0, memory.Buffer.Length); var result = await _server.Client.ReceiveFromAsync(segment, SocketFlags.None, AnyIPEndPoint); Interlocked.Increment(ref _workerHitCounter[id]); await HandleResponseSocketPooledAsync(_server.Client, result.RemoteEndPoint, segment); } } catch { break; } } }
public override async Task <DnsResponseMessage> QueryAsync( IPEndPoint server, DnsRequestMessage request, CancellationToken cancellationToken, Action <Action> cancelationCallback) { cancellationToken.ThrowIfCancellationRequested(); UdpClient udpClient = GetNextUdpClient(server.AddressFamily); bool mustDispose = false; try { // setup timeout cancelation, dispose socket (the only way to acutally cancel the request in async... cancelationCallback(() => { #if PORTABLE udpClient.Dispose(); #else udpClient.Close(); #endif }); using (var writer = new DnsDatagramWriter()) { GetRequestData(request, writer); await udpClient.SendAsync(writer.Data.Array, writer.Data.Count, server).ConfigureAwait(false); } var readSize = udpClient.Available > MaxSize ? udpClient.Available : MaxSize; using (var memory = new PooledBytes(readSize)) { #if PORTABLE int received = await udpClient.Client.ReceiveAsync(new ArraySegment <byte>(memory.Buffer), SocketFlags.None).ConfigureAwait(false); var response = GetResponseMessage(new ArraySegment <byte>(memory.Buffer, 0, received)); #else var result = await udpClient.ReceiveAsync().ConfigureAwait(false); var response = GetResponseMessage(new ArraySegment <byte>(result.Buffer, 0, result.Buffer.Length)); #endif if (request.Header.Id != response.Header.Id) { throw new DnsResponseException("Header id missmatch."); } Enqueue(server.AddressFamily, udpClient); return(response); } } catch (ObjectDisposedException) { // we disposed it in case of a timeout request, lets indicate it actually timed out... throw new TimeoutException(); } catch { mustDispose = true; throw; } finally { if (!_enableClientQueue || mustDispose) { try { #if PORTABLE udpClient.Dispose(); #else udpClient.Close(); #endif } catch { } } } }
public override async Task <DnsResponseMessage> QueryAsync( IPEndPoint server, DnsRequestMessage request, CancellationToken cancellationToken, Action <Action> cancelationCallback) { cancellationToken.ThrowIfCancellationRequested(); using (var client = new TcpClient(server.AddressFamily)) { cancelationCallback(() => { #if PORTABLE client.Dispose(); #else client.Close(); #endif }); cancellationToken.ThrowIfCancellationRequested(); await client.ConnectAsync(server.Address, server.Port).ConfigureAwait(false); using (var stream = client.GetStream()) { // use a pooled buffer to writer the data + the length of the data later into the frist two bytes using (var memory = new PooledBytes(DnsDatagramWriter.BufferSize + 2)) using (var writer = new DnsDatagramWriter(new ArraySegment <byte>(memory.Buffer, 2, memory.Buffer.Length - 2))) { GetRequestData(request, writer); int dataLength = writer.Index; memory.Buffer[0] = (byte)((dataLength >> 8) & 0xff); memory.Buffer[1] = (byte)(dataLength & 0xff); //var sendData = new byte[dataLength + 2]; //sendData[0] = (byte)((dataLength >> 8) & 0xff); //sendData[1] = (byte)(dataLength & 0xff); //Array.Copy(data, 0, sendData, 2, dataLength); await stream.WriteAsync(memory.Buffer, 0, dataLength + 2, cancellationToken).ConfigureAwait(false); await stream.FlushAsync(cancellationToken).ConfigureAwait(false); } int length = stream.ReadByte() << 8 | stream.ReadByte(); if (length <= 0) { throw new DnsResponseException("Received no answer."); } var resultData = new byte[length]; int bytesReceived = 0; while (bytesReceived < length) { int read = await stream.ReadAsync(resultData, bytesReceived, length - bytesReceived, cancellationToken).ConfigureAwait(false); bytesReceived += read; if (read == 0 && bytesReceived < length) { // disconnected throw new SocketException(-1); } } var response = GetResponseMessage(new ArraySegment <byte>(resultData, 0, bytesReceived)); if (request.Header.Id != response.Header.Id) { throw new DnsResponseException("Header id missmatch."); } return(response); } } }
private async Task <DnsResponseMessage> QueryAsyncInternal( Stream stream, DnsRequestMessage request, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); // use a pooled buffer to writer the data + the length of the data later into the frist two bytes using (var memory = new PooledBytes(DnsDatagramWriter.BufferSize + 2)) { var writer = new DnsDatagramWriter(new ArraySegment <byte>(memory.Buffer, 2, memory.Buffer.Length - 2)); GetRequestData(request, writer); var dataLength = writer.Index; memory.Buffer[0] = (byte)((dataLength >> 8) & 0xff); memory.Buffer[1] = (byte)(dataLength & 0xff); //await client.Client.SendAsync(new ArraySegment<byte>(memory.Buffer, 0, dataLength + 2), SocketFlags.None).ConfigureAwait(false); await stream.WriteAsync(memory.Buffer, 0, dataLength + 2, cancellationToken).ConfigureAwait(false); await stream.FlushAsync(cancellationToken).ConfigureAwait(false); } if (!stream.CanRead) { return(null); } cancellationToken.ThrowIfCancellationRequested(); int length; try { length = stream.ReadByte() << 8 | stream.ReadByte(); } catch (Exception ex) when(ex is IOException || ex is SocketException) { return(null); } if (length <= 0) { // server signals close/disconnecting return(null); } using (var memory = new PooledBytes(length)) { var bytesReceived = 0; var readSize = length > 4096 ? 4096 : length; while ((bytesReceived += await stream.ReadAsync(memory.Buffer, bytesReceived, readSize).ConfigureAwait(false)) < length) { if (bytesReceived <= 0) { // disconnected return(null); } if (bytesReceived + readSize > length) { readSize = length - bytesReceived; if (readSize <= 0) { break; } } } var response = GetResponseMessage(new ArraySegment <byte>(memory.Buffer, 0, bytesReceived)); if (request.Header.Id != response.Header.Id) { throw new DnsResponseException("Header id mismatch."); } return(response); } }
private async Task <DnsResponseMessage> QueryAsyncInternal(TcpClient client, DnsRequestMessage request, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var stream = client.GetStream(); // use a pooled buffer to writer the data + the length of the data later into the first two bytes using (var memory = new PooledBytes(DnsDatagramWriter.BufferSize + 2)) using (var writer = new DnsDatagramWriter(new ArraySegment <byte>(memory.Buffer, 2, memory.Buffer.Length - 2))) { GetRequestData(request, writer); int dataLength = writer.Index; memory.Buffer[0] = (byte)((dataLength >> 8) & 0xff); memory.Buffer[1] = (byte)(dataLength & 0xff); //await client.Client.SendAsync(new ArraySegment<byte>(memory.Buffer, 0, dataLength + 2), SocketFlags.None).ConfigureAwait(false); await stream.WriteAsync(memory.Buffer, 0, dataLength + 2, cancellationToken).ConfigureAwait(false); await stream.FlushAsync(cancellationToken).ConfigureAwait(false); } if (!stream.CanRead) { return(null); } cancellationToken.ThrowIfCancellationRequested(); var responses = new List <DnsResponseMessage>(); do { int length; try { //length = stream.ReadByte() << 8 | stream.ReadByte(); using (var lengthBuffer = new PooledBytes(2)) { int bytesReceived = 0, read; while ((bytesReceived += (read = await stream.ReadAsync(lengthBuffer.Buffer, bytesReceived, 2, cancellationToken).ConfigureAwait(false))) < 2) { if (read <= 0) { // disconnected, might retry return(null); } } length = lengthBuffer.Buffer[0] << 8 | lengthBuffer.Buffer[1]; } } catch (Exception ex) when(ex is IOException || ex is SocketException) { return(null); } if (length <= 0) { // server signals close/disconnecting return(null); } using (var memory = new PooledBytes(length)) { int bytesReceived = 0, read; int readSize = length > 4096 ? 4096 : length; while (!cancellationToken.IsCancellationRequested && (bytesReceived += (read = await stream.ReadAsync(memory.Buffer, bytesReceived, readSize, cancellationToken).ConfigureAwait(false))) < length) { if (read <= 0) { // disconnected return(null); } if (bytesReceived + readSize > length) { readSize = length - bytesReceived; if (readSize <= 0) { break; } } } DnsResponseMessage response = GetResponseMessage(new ArraySegment <byte>(memory.Buffer, 0, bytesReceived)); if (request.Header.Id != response.Header.Id) { throw new DnsResponseException("Header id mismatch."); } responses.Add(response); } } while (stream.DataAvailable && !cancellationToken.IsCancellationRequested); return(DnsResponseMessage.Combine(responses)); }
public DnsDatagramWriter() { _pooledBytes = new PooledBytes(BufferSize); _buffer = new ArraySegment <byte>(_pooledBytes.Buffer, 0, BufferSize); }
public override async Task <DnsResponseMessage> QueryAsync( IPEndPoint server, DnsRequestMessage request, CancellationToken cancellationToken, Action <Action> cancelationCallback) { cancellationToken.ThrowIfCancellationRequested(); var udpClient = GetNextUdpClient(server.AddressFamily); var mustDispose = false; try { // setup timeout cancelation, dispose socket (the only way to acutally cancel the request in async... cancelationCallback(() => { udpClient.Close(); }); using (var pool = new PooledBytes(DnsDatagramWriter.BufferSize)) { var writer = new DnsDatagramWriter(new ArraySegment <byte>(pool.Buffer)); GetRequestData(request, writer); await udpClient.SendAsync(writer.Data.Array, writer.Data.Count, server).ConfigureAwait(false); } var result = await udpClient.ReceiveAsync().ConfigureAwait(false); var response = GetResponseMessage(new ArraySegment <byte>(result.Buffer, 0, result.Buffer.Length)); if (request.Header.Id != response.Header.Id) { throw new DnsResponseException("Header id mismatch."); } Enqueue(server.AddressFamily, udpClient); return(response); } catch (ObjectDisposedException) { // we disposed it in case of a timeout request, lets indicate it actually timed out... throw new TimeoutException(); } catch { mustDispose = true; throw; } finally { if (!_enableClientQueue || mustDispose) { try { udpClient.Close(); } catch { // ignored } } } }
public override DnsResponseMessage Query( IPEndPoint server, DnsRequestMessage request, TimeSpan timeout) { var udpClient = GetNextUdpClient(server.AddressFamily); // -1 indicates infinite var timeoutInMillis = timeout.TotalMilliseconds >= int.MaxValue ? -1 : (int)timeout.TotalMilliseconds; udpClient.Client.ReceiveTimeout = timeoutInMillis; udpClient.Client.SendTimeout = timeoutInMillis; var mustDispose = false; try { using (var pool = new PooledBytes(DnsDatagramWriter.BufferSize)) { var writer = new DnsDatagramWriter(new ArraySegment <byte>(pool.Buffer)); GetRequestData(request, writer); Debug.Assert(writer.Data.Array != null); udpClient.Client.SendTo(writer.Data.Array, writer.Data.Offset, writer.Data.Count, SocketFlags.None, server); } var readSize = udpClient.Available > MaxSize ? udpClient.Available : MaxSize; using (var memory = new PooledBytes(readSize)) { var received = udpClient.Client.Receive(memory.Buffer, 0, readSize, SocketFlags.None); var response = GetResponseMessage(new ArraySegment <byte>(memory.Buffer, 0, received)); if (request.Header.Id != response.Header.Id) { throw new DnsResponseException("Header id mismatch."); } Enqueue(server.AddressFamily, udpClient); return(response); } } catch { mustDispose = true; throw; } finally { if (!_enableClientQueue || mustDispose) { try { udpClient.Close(); } catch { // ignored } } } }