private static void OnConnection(UvConnectRequest req, int status, Exception exception, object state) { var client = (UvTcpClient)state; var connection = new UvTcpConnection(client._thread, client._connectSocket); client._connectTcs.TrySetResult(connection); }
private static void OnConnection(UvConnectRequest req, int status, Exception exception, object state) { var client = (UvTcpClient)state; var connection = new UvTcpConnection(client._thread, client._connectSocket); Task.Run(() => client._connectTcs.TrySetResult(connection)); }
private static async void ExecuteCallback(UvTcpListener listener, UvTcpConnection connection) { try { await listener._callback?.Invoke(connection); } catch { // Swallow exceptions } finally { await connection.DisposeAsync(); } }
private static void OnConnectionCallback(UvStreamHandle listenSocket, int status, Exception error, object state) { var listener = (UvTcpListener)state; var acceptSocket = new UvTcpHandle(); try { acceptSocket.Init(listener._thread.Loop, null); acceptSocket.NoDelay(true); listenSocket.Accept(acceptSocket); var connection = new UvTcpConnection(listener._thread, acceptSocket); ExecuteCallback(listener, connection); } catch (UvException) { acceptSocket.Dispose(); } }
private static async void ExecuteCallback(UvTcpListener listener, UvTcpConnection connection) { try { await listener._callback?.Invoke(connection); // Make sure we dispose off the libuv thread await Task.Yield(); } catch { // Swallow exceptions } finally { // Dispose the connection on task completion connection.Dispose(); } }
private static async void ExecuteCallback(UvTcpListener listener, UvTcpConnection connection) { try { await listener._callback?.Invoke(connection); } catch { // Swallow exceptions } finally { // Dispose the connection on task completion connection.Dispose(); } }
private static async Task ProduceResponse(ConnectionState state, UvTcpConnection connection, HttpResponseMessage response) { // TODO: pipelining support! while (true) { var result = await connection.Input.ReadAsync(); var responseBuffer = result.Buffer; var consumed = responseBuffer.Start; var needMoreData = true; try { if (consumed == state.Consumed) { var oldBody = responseBuffer.Slice(0, state.PreviousContentLength); if (oldBody.Length != state.PreviousContentLength) { // Not enough data continue; } // The caller didn't read the body responseBuffer = responseBuffer.Slice(state.PreviousContentLength); consumed = responseBuffer.Start; state.Consumed = default(ReadCursor); } if (responseBuffer.IsEmpty && result.IsCompleted) { break; } ReadCursor delim; ReadableBuffer responseLine; if (!responseBuffer.TrySliceTo((byte)'\r', (byte)'\n', out responseLine, out delim)) { continue; } responseBuffer = responseBuffer.Slice(delim).Slice(2); ReadableBuffer httpVersion; if (!responseLine.TrySliceTo((byte)' ', out httpVersion, out delim)) { // Bad request throw new InvalidOperationException(); } consumed = responseBuffer.Start; responseLine = responseLine.Slice(delim).Slice(1); ReadableBuffer statusCode; if (!responseLine.TrySliceTo((byte)' ', out statusCode, out delim)) { // Bad request throw new InvalidOperationException(); } response.StatusCode = (HttpStatusCode)statusCode.GetUInt32(); responseLine = responseLine.Slice(delim).Slice(1); ReadableBuffer remaining; if (!responseLine.TrySliceTo((byte)' ', out remaining, out delim)) { // Bad request throw new InvalidOperationException(); } while (!responseBuffer.IsEmpty) { var ch = responseBuffer.Peek(); if (ch == -1) { break; } if (ch == '\r') { // Check for final CRLF. responseBuffer = responseBuffer.Slice(1); ch = responseBuffer.Peek(); responseBuffer = responseBuffer.Slice(1); if (ch == -1) { break; } else if (ch == '\n') { consumed = responseBuffer.Start; needMoreData = false; break; } // Headers don't end in CRLF line. throw new Exception(); } var headerName = default(ReadableBuffer); var headerValue = default(ReadableBuffer); // End of the header // \n ReadableBuffer headerPair; if (!responseBuffer.TrySliceTo((byte)'\n', out headerPair, out delim)) { break; } responseBuffer = responseBuffer.Slice(delim).Slice(1); // : if (!headerPair.TrySliceTo((byte)':', out headerName, out delim)) { throw new Exception(); } headerName = headerName.TrimStart(); headerPair = headerPair.Slice(headerName.End).Slice(1); // \r if (!headerPair.TrySliceTo((byte)'\r', out headerValue, out delim)) { // Bad request throw new Exception(); } headerValue = headerValue.TrimStart(); var hKey = headerName.GetAsciiString(); var hValue = headerValue.GetAsciiString(); if (!response.Content.Headers.TryAddWithoutValidation(hKey, hValue)) { response.Headers.TryAddWithoutValidation(hKey, hValue); } // Move the consumed consumed = responseBuffer.Start; } } catch (Exception ex) { // Close the connection connection.Output.Complete(ex); break; } finally { connection.Input.Advance(consumed); } if (needMoreData) { continue; } // Only handle content length for now var length = response.Content.Headers.ContentLength; if (!length.HasValue) { throw new NotSupportedException(); } checked { // BAD but it's a proof of concept ok? state.PreviousContentLength = (int)length.Value; ((PipelineHttpContent)response.Content).ContentLength = (int)length; state.Consumed = consumed; } break; } }