async Task <int> CreateTransportAsync(HttpListenerContext context, IHandler handler) { X509Certificate2 clientCertificate = null; if (this.Listener.sslSettings != null && this.Listener.sslSettings.ClientCertificateRequired) { clientCertificate = await context.Request.GetClientCertificateAsync().ConfigureAwait(false); if (clientCertificate == null) { return(40300); } if (this.Listener.sslSettings.RemoteCertificateValidationCallback != null) { SslPolicyErrors sslError = SslPolicyErrors.None; X509Chain chain = new X509Chain(); chain.ChainPolicy.RevocationMode = this.Listener.sslSettings.CheckCertificateRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck; chain.Build(clientCertificate); if (chain.ChainStatus.Length > 0) { sslError = SslPolicyErrors.RemoteCertificateChainErrors; } bool success = this.Listener.sslSettings.RemoteCertificateValidationCallback( this, clientCertificate, chain, sslError); if (!success) { return(40301); } } else if (context.Request.ClientCertificateError != 0) { return(40302); } } IPrincipal principal = context.User; if (principal == null && clientCertificate != null) { principal = new GenericPrincipal(new X509Identity(clientCertificate), new string[0]); } string subProtocol = null; string[] subProtocols = context.Request.Headers.GetValues("Sec-WebSocket-Protocol"); for (int i = 0; i < subProtocols.Length; i++) { if (subProtocols[i].Equals(WebSocketTransport.WebSocketSubProtocol) || subProtocols[i].Equals("AMQPWSB10") // defined by the previous draft ) { subProtocol = subProtocols[i]; break; } } if (subProtocol == null) { return(40003); } var wsContext = await context.AcceptWebSocketAsync(subProtocol).ConfigureAwait(false); if (handler != null && handler.CanHandle(EventId.WebSocketAccept)) { handler.Handle(Event.Create(EventId.WebSocketAccept, null, context: wsContext)); } var wsTransport = new ListenerWebSocketTransport(wsContext.WebSocket, principal); await this.Listener.HandleTransportAsync(wsTransport, handler, wsContext.WebSocket).ConfigureAwait(false); return(0); }
private async Task <bool> ProcessConnectionAsync( CancellationToken cancellationToken, HttpListenerContext httpContext) { Logger.Debug("ProcessConnectionAsync"); WebSocketContext webSocketContext = null; try { webSocketContext = await httpContext.AcceptWebSocketAsync(null); } catch (Exception ex) { Logger.Error(ex, "AcceptWebSocketAsync"); // The upgrade process failed somehow. For simplicity lets assume it was a failure on the part of the server and indicate this using 500. httpContext.Response.StatusCode = 500; httpContext.Response.Close(); return(false); } WebSocket webSocket = webSocketContext.WebSocket; MemoryStream ms = new MemoryStream(); try { IWebSocketConnectionHandler handler = this.createConnectionHandler(); byte[] receiveBuffer = null; // While the WebSocket connection remains open run a simple loop that receives data and sends it back. while (webSocket.State == WebSocketState.Open) { try { if (receiveBuffer == null) { receiveBuffer = new byte[MaxBufferSize]; } WebSocketReceiveResult receiveResult = await webSocket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer), cancellationToken); if (receiveResult.MessageType == WebSocketMessageType.Close) { Logger.Debug("ProcessConnectionAsync: closing websocket"); await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", cancellationToken); continue; } if (receiveResult.EndOfMessage) { await ms.WriteAsync(receiveBuffer, 0, receiveResult.Count, cancellationToken); receiveBuffer = ms.ToArray(); ms.Dispose(); ms = new MemoryStream(); } else { await ms.WriteAsync(receiveBuffer, 0, receiveResult.Count, cancellationToken); continue; } byte[] wsresponse = null; try { // dispatch to App provided function with requested payload wsresponse = await handler.ProcessWsMessageAsync(receiveBuffer, cancellationToken); } catch (Exception ex) { // catch any error in the appAction and notify the client wsresponse = await new ProtobufWsSerializer().SerializeAsync( new WsResponseMessage { Result = WsResult.Error, Value = Encoding.UTF8.GetBytes(ex.Message) }); } // Send Result back to client await webSocket.SendAsync( new ArraySegment <byte>(wsresponse), WebSocketMessageType.Binary, true, cancellationToken); } catch (WebSocketException ex) { Logger.Error(ex, "ProcessConnectionAsync: WebSocketException={0}", webSocket.State); } } return(true); } catch (Exception ex) { Logger.Error(ex, "ProcessConnectionAsync"); throw; } }
/// <inheritdoc /> public async Task <IWebSocketContext> AcceptWebSocketAsync(int receiveBufferSize) => new WebSocketContext(await _context.AcceptWebSocketAsync(subProtocol: null, receiveBufferSize: receiveBufferSize, keepAliveInterval: TimeSpan.FromSeconds(30)) .ConfigureAwait(false));
public async Task AcceptWebSocket(HttpListenerContext context, CancellationToken ct) #endif { _ct = ct; // first, accept the websocket $"{ServerName} - Accepting WebSocket . . .".Debug(nameof(WebSocketsServer)); #if NET47 const int receiveBufferSize = 2048; #endif var webSocketContext = #if NET47 await context.AcceptWebSocketAsync( subProtocol : null, receiveBufferSize : receiveBufferSize, keepAliveInterval : TimeSpan.FromSeconds(30)); #else await context.AcceptWebSocketAsync(); #endif // remove the disconnected clients CollectDisconnected(); lock (_syncRoot) { // add the newly-connected client _mWebSockets.Add(webSocketContext); } $"{ServerName} - WebSocket Accepted - There are {WebSockets.Count} sockets connected.".Debug( nameof(WebSocketsServer)); // call the abstract member #if NET47 OnClientConnected(webSocketContext, context.Request.LocalEndPoint, context.Request.RemoteEndPoint); #else OnClientConnected(webSocketContext); #endif try { #if NET47 // define a receive buffer var receiveBuffer = new byte[receiveBufferSize]; // define a dynamic buffer that holds multi-part receptions var receivedMessage = new List <byte>(receiveBuffer.Length * 2); // poll the WebSockets connections for reception while (webSocketContext.WebSocket.State == WebSocketState.Open) { // retrieve the result (blocking) var receiveResult = await webSocketContext.WebSocket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer), ct); if (receiveResult.MessageType == WebSocketMessageType.Close) { // close the connection if requested by the client await webSocketContext.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, ct); return; } var frameBytes = new byte[receiveResult.Count]; Array.Copy(receiveBuffer, frameBytes, frameBytes.Length); this.OnFrameReceived(webSocketContext, frameBytes, receiveResult); // add the response to the multi-part response receivedMessage.AddRange(frameBytes); if (receivedMessage.Count > _maximumMessageSize && _maximumMessageSize > 0) { // close the connection if message exceeds max length await webSocketContext.WebSocket.CloseAsync(WebSocketCloseStatus.MessageTooBig, $"Message too big. Maximum is {_maximumMessageSize} bytes.", ct); // exit the loop; we're done return; } // if we're at the end of the message, process the message if (receiveResult.EndOfMessage) { this.OnMessageReceived(webSocketContext, receivedMessage.ToArray(), receiveResult); receivedMessage.Clear(); } } #else webSocketContext.WebSocket.OnMessage += (s, e) => { var isText = e.IsText ? WebSocketMessageType.Text : WebSocketMessageType.Binary; OnMessageReceived(webSocketContext, e.RawData, new WebSocketReceiveResult(e.RawData.Length, isText, e.Opcode == Opcode.Close)); }; while (webSocketContext.WebSocket.IsConnected) { await Task.Delay(500, ct); } #endif } catch (Exception ex) { ex.Log(nameof(WebSocketsServer)); } finally { // once the loop is completed or connection aborted, remove the WebSocket RemoveWebSocket(webSocketContext); } }
public async Task AcceptWebSocketAsync_InvalidKeepAlive_ThrowsWebSocketException() { HttpListenerContext context = await GetWebSocketContext(); TimeSpan keepAlive = TimeSpan.FromMilliseconds(-2); await Assert.ThrowsAsync <ArgumentOutOfRangeException>("keepAliveInterval", () => context.AcceptWebSocketAsync(null, keepAlive)); }
public async Task AcceptWebSocketAsync_NullArrayInArraySegment_ThrowsArgumentNullException() { HttpListenerContext context = await GetWebSocketContext(); ArraySegment <byte> internalBuffer = new FakeArraySegment() { Array = null }.ToActual(); await AssertExtensions.ThrowsAsync <ArgumentNullException>("internalBuffer.Array", () => context.AcceptWebSocketAsync(null, 1024, TimeSpan.MaxValue, internalBuffer)); }
private static async Task ListenerProcessingLoopAsync() { var cancellationToken = ListenerLoopTokenSource.Token; try { while (!cancellationToken.IsCancellationRequested) { HttpListenerContext context = await Listener.GetContextAsync(); if (ServerIsRunning) { if (context.Request.IsWebSocketRequest) { // HTTP is only the initial connection; upgrade to a client-specific websocket HttpListenerWebSocketContext wsContext = null; try { wsContext = await context.AcceptWebSocketAsync(subProtocol : null); int socketId = Interlocked.Increment(ref SocketCounter); var client = new ConnectedClient(socketId, wsContext.WebSocket); Clients.TryAdd(socketId, client); Console.WriteLine($"Socket {socketId}: New connection."); _ = Task.Run(() => SocketProcessingLoopAsync(client).ConfigureAwait(false)); } catch (Exception) { // server error if upgrade from HTTP to WebSocket fails context.Response.StatusCode = 500; context.Response.StatusDescription = "WebSocket upgrade failed"; context.Response.Close(); return; } } else { if (context.Request.AcceptTypes.Contains("text/html")) { Console.WriteLine("Sending HTML to client."); ReadOnlyMemory <byte> HtmlPage = new ReadOnlyMemory <byte>(Encoding.UTF8.GetBytes(SimpleHtmlClient.HTML)); context.Response.ContentType = "text/html; charset=utf-8"; context.Response.StatusCode = 200; context.Response.StatusDescription = "OK"; context.Response.ContentLength64 = HtmlPage.Length; await context.Response.OutputStream.WriteAsync(HtmlPage, CancellationToken.None); await context.Response.OutputStream.FlushAsync(CancellationToken.None); } else { context.Response.StatusCode = 400; } context.Response.Close(); } } else { // HTTP 409 Conflict (with server's current state) context.Response.StatusCode = 409; context.Response.StatusDescription = "Server is shutting down"; context.Response.Close(); return; } } } catch (HttpListenerException ex) when(ServerIsRunning) { Program.ReportException(ex); } }
public async Task AcceptWebSocketAsync_InvalidSubProtocol_ThrowsArgumentException(string subProtocol) { HttpListenerContext context = await GetWebSocketContext(); await AssertExtensions.ThrowsAsync <ArgumentException>("subProtocol", () => context.AcceptWebSocketAsync(subProtocol)); }
// a web socket is attaching private async void ProcessWebSocket(HttpListenerContext ctx, string protocol, Tuple <WebSocketsResponderFunc, Object> responder, CancellationToken canceltk) { WebSocketContext wsctx; try { System.Diagnostics.Debug.WriteLine("WEBSOCKET Accepting on " + prefixesString + " protocol " + protocol); wsctx = await ctx.AcceptWebSocketAsync(protocol); } catch (Exception e) { // The upgrade process failed somehow. For simplicity lets assume it was a failure on the part of the server and indicate this using 500. ctx.Response.StatusCode = 500; ctx.Response.Close(); System.Diagnostics.Debug.WriteLine("Exception: {0}", e); return; } ServerLog?.Invoke("WEBSOCKET accepted " + prefixesString); System.Diagnostics.Debug.WriteLine("WEBSOCKET accepted " + prefixesString); WebSocket webSocket = wsctx.WebSocket; lock (webSockets) webSockets.Add(webSocket); // add to the pool of web sockets to throw data at. try { byte[] receiveBuffer = new byte[WebSocketMsgBufferSize]; while (webSocket.State == WebSocketState.Open) { WebSocketReceiveResult receiveResult = await webSocket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer), canceltk); ServerLog?.Invoke("WEBSOCKET request " + prefixesString + ": " + receiveResult.MessageType); System.Diagnostics.Debug.WriteLine("WEBSOCKET request " + prefixesString + " type " + receiveResult.MessageType + " len " + receiveResult.Count); if (receiveResult.MessageType == WebSocketMessageType.Close) { System.Diagnostics.Debug.WriteLine("WEBSOCKET close req " + prefixesString); webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None).Wait(); // here we block until complete } else { responder.Item1(ctx.Request, webSocket, receiveResult, receiveBuffer, responder.Item2); } } System.Diagnostics.Debug.WriteLine("WEBSOCKET closed on " + prefixesString); } catch (System.Threading.Tasks.TaskCanceledException) { // normal task canceled exception } catch (Exception e) { // Just log any exceptions to the console. Pretty much any exception that occurs when calling `SendAsync`/`ReceiveAsync`/`CloseAsync` is unrecoverable in that it will abort the connection and leave the `WebSocket` instance in an unusable state. System.Diagnostics.Debug.WriteLine("Exception: {0}", e); } finally { if (webSocket != null) // Clean up by disposing the WebSocket once it is closed/aborted. { lock (webSockets) webSockets.Remove(webSocket); webSocket.Dispose(); } } System.Diagnostics.Debug.WriteLine("WEBSOCKET terminate " + prefixesString); }
public virtual async void ProcessWebSocketRequest(HttpListenerContext context) { WebSocketContext webSocketContext = null; try { // When calling `AcceptWebSocketAsync` the negotiated subprotocol must be specified. For simplicity now we assumes that no subprotocol // was requested. webSocketContext = await context.AcceptWebSocketAsync(null); if (_websocketConnectionCount == int.MaxValue) { Log("[VERBOSE] Websocket reset connection count"); _websocketConnectionCount = 0; } Interlocked.Increment(ref _websocketConnectionCount); Log(string.Format("[VERBOSE] Websocket #{0}", _websocketConnectionCount)); } catch (Exception ex) { // The upgrade process failed somehow. For simplicity lets assume it was a failure on the part of the server and indicate this using 500. context.Response.StatusCode = 500; context.Response.Close(); Log(string.Format("[ERROR] {0}", ex.Message)); return; } WebSocket webSocket = webSocketContext.WebSocket; string clientId = WebSocketClients.AddSocket(webSocket); try { Log("[VERBOSE] Websocket is receiving"); //### Receiving // Define a receive buffer to hold data received on the WebSocket connection. The buffer will be reused as we only need to hold on to the data // long enough to send it back to the sender. ArraySegment <byte> receiveBuffer = new ArraySegment <byte>(new byte[1024]); // 8192; MemoryStream msText = null; MemoryStream msBin = null; // While the WebSocket connection remains open run a simple loop that receives data and sends it back. while (webSocket.State == WebSocketState.Open) { // The first step is to begin a receive operation on the WebSocket. `ReceiveAsync` takes two parameters: // // * An `ArraySegment` to write the received data to. // * A cancellation token. In this example we are not using any timeouts so we use `CancellationToken.None`. // // `ReceiveAsync` returns a `Task<WebSocketReceiveResult>`. The `WebSocketReceiveResult` provides information on the receive operation that was just // completed, such as: // // * `WebSocketReceiveResult.MessageType` - What type of data was received and written to the provided buffer. Was it binary, utf8, or a close message? // * `WebSocketReceiveResult.Count` - How many bytes were read? // * `WebSocketReceiveResult.EndOfMessage` - Have we finished reading the data for this message or is there more coming? WebSocketReceiveResult receiveResult = await webSocket.ReceiveAsync(receiveBuffer, CancellationToken.None); if (receiveResult.MessageType == WebSocketMessageType.Close) { // The WebSocket protocol defines a close handshake that allows a party to send a close frame when they wish to gracefully shut down the connection. // The party on the other end can complete the close handshake by sending back a close frame. // // If we received a close frame then lets participate in the handshake by sending a close frame back. This is achieved by calling `CloseAsync`. // `CloseAsync` will also terminate the underlying TCP connection once the close handshake is complete. // // The WebSocket protocol defines different status codes that can be sent as part of a close frame and also allows a close message to be sent. // If we are just responding to the client's request to close we can just use `WebSocketCloseStatus.NormalClosure` and omit the close message. Log(string.Format("[VERBOSE] Websocket for client {0} graceful close", clientId)); await WebSocketClients.RemoveSocket(clientId); } else if (receiveResult.MessageType == WebSocketMessageType.Text) { // We received text! if (msText == null) { Log("[VERBOSE] Websocket text frame"); msText = new MemoryStream(); } else { Log("[VERBOSE] Websocket text frame (append)"); } msText.Write(receiveBuffer.Array, receiveBuffer.Offset, receiveResult.Count); if (receiveResult.EndOfMessage) { msText.Seek(0, SeekOrigin.Begin); using (var reader = new StreamReader(msText, Encoding.UTF8)) { string receiveText = reader.ReadToEnd(); string sendText = ProcessWebSocketTextRequest(clientId, receiveText); byte[] encoded = Encoding.UTF8.GetBytes(sendText); var sendBuffer = new ArraySegment <byte>(encoded, 0, encoded.Length); await webSocket.SendAsync(sendBuffer, WebSocketMessageType.Text, true, CancellationToken.None); } msText.Close(); msText.Dispose(); msText = null; } } else { // We received binary data! if (msBin == null) { Log("[VERBOSE] Websocket bin frame"); msBin = new MemoryStream(); } else { Log("[VERBOSE] Websocket bin frame (append)"); } msBin.Write(receiveBuffer.Array, receiveBuffer.Offset, receiveResult.Count); if (receiveResult.EndOfMessage) { msBin.Seek(0, SeekOrigin.Begin); Stream sendStream = ProcessWebSocketBinaryRequest(clientId, msBin); sendStream.Seek(0, SeekOrigin.Begin); byte[] sendBytes = new byte[sendStream.Length]; sendStream.Read(sendBytes, 0, (int)sendStream.Length); var sendBuffer = new ArraySegment <byte>(sendBytes, 0, sendBytes.Length); await webSocket.SendAsync(sendBuffer, WebSocketMessageType.Binary, true, CancellationToken.None); msBin.Close(); msBin.Dispose(); msBin = null; } } } } catch (Exception ex) { Log(string.Format("[ERROR] {0}", ex.Message)); } finally { // Clean up by disposing the WebSocket once it is closed/aborted. if (webSocket != null) { Log(string.Format("[VERBOSE] Websocket for client {0} is being disposed", clientId)); webSocket.Dispose(); } } }
async Task ExecuteRequest(HttpListenerContext listenerContext) { // By default we will close the stream to cater for failure scenarios var keepConnection = false; var clientName = listenerContext.Request.RemoteEndPoint; WebSocketStream webSocketStream = null; try { var webSocketContext = await listenerContext.AcceptWebSocketAsync("Octopus").ConfigureAwait(false); webSocketStream = new WebSocketStream(webSocketContext.WebSocket); var req = await webSocketStream.ReadTextMessage().ConfigureAwait(false); // Initial message if (string.IsNullOrEmpty(req)) { log.Write(EventType.Diagnostic, "Ignoring empty request"); return; } if (req.Substring(0, 2) != "MX") { log.Write(EventType.Diagnostic, "Appears to be a web browser, sending friendly HTML response"); return; } var authorized = await Authorize(listenerContext, clientName).ConfigureAwait(false); if (authorized) { // Delegate the open stream to the protocol handler - we no longer own the stream lifetime await ExchangeMessages(webSocketStream).ConfigureAwait(false); // Mark the stream as delegated once everything has succeeded keepConnection = true; } } catch (TaskCanceledException) { if (!cts.Token.IsCancellationRequested) { log.Write(EventType.Error, "A timeout occurred while receiving data"); } } catch (Exception ex) { log.WriteException(EventType.Error, "Unhandled error when handling request from client: {0}", ex, clientName); } finally { if (!keepConnection) { // Closing an already closed stream or client is safe, better not to leak webSocketStream?.Dispose(); listenerContext.Response.Close(); } } }
public Task <HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol) { return(inner.AcceptWebSocketAsync(subProtocol)); }
private async void _Accept(HttpListenerContext context) { System.Net.WebSockets.HttpListenerWebSocketContext webSocketContext = await context.AcceptWebSocketAsync(null); var webSocket = webSocketContext.WebSocket; var status = await Task <System.Net.WebSockets.WebSocketState> .Factory.StartNew(() => { while (webSocket.State == System.Net.WebSockets.WebSocketState.Connecting) { System.Threading.Thread.Sleep(1); } return(webSocket.State); }); if (status == System.Net.WebSockets.WebSocketState.Open) { _AcceptEvent(new Peer(webSocket)); } }
public async Task AcceptWebSocketAsync_UnsupportedProtocol_ThrowsWebSocketException() { HttpListenerContext context = await GetWebSocketContext(new string[] { "MyProtocol" }); await Assert.ThrowsAsync <WebSocketException>(() => context.AcceptWebSocketAsync("MyOtherProtocol")); }
static async System.Threading.Tasks.Task Main(string[] args) { Console.WriteLine("TaxcomAgent2"); HttpListener httpListener = new HttpListener(); httpListener.Prefixes.Add("http://localhost:4500/"); httpListener.Start(); Console.WriteLine("Started!"); for (; ;) { HttpListenerContext context = await httpListener.GetContextAsync(); if (context.Request.IsWebSocketRequest) { HttpListenerWebSocketContext webSocketContext = await context.AcceptWebSocketAsync(null); WebSocket socket = webSocketContext.WebSocket; while (socket.State == WebSocketState.Open) { const int maxMessageSize = 4096; byte[] receiveBuffer = new byte[maxMessageSize]; WebSocketReceiveResult receiveResult = await socket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer), CancellationToken.None); if (receiveResult.MessageType == WebSocketMessageType.Close) { await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); } else if (receiveResult.MessageType == WebSocketMessageType.Binary) { await socket.CloseAsync(WebSocketCloseStatus.InvalidMessageType, "Cannot accept binary frame", CancellationToken.None); } else { int count = receiveResult.Count; while (receiveResult.EndOfMessage == false) { if (count >= maxMessageSize) { string closeMessage = string.Format("Maximum message size: {0} bytes.", maxMessageSize); await socket.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, CancellationToken.None); return; } receiveResult = await socket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer, count, maxMessageSize - count), CancellationToken.None); count += receiveResult.Count; } var receivedString = Encoding.UTF8.GetString(receiveBuffer, 0, count); var echoString = WebSocketHandler(receivedString); ArraySegment <byte> outputBuffer = new ArraySegment <byte>(Encoding.UTF8.GetBytes(echoString)); await socket.SendAsync(outputBuffer, WebSocketMessageType.Text, true, CancellationToken.None); } } } else { context.Response.StatusCode = 400; } } }
public async Task AcceptWebSocketAsync_NoClientSubProtocol_ThrowsWebSocketException() { HttpListenerContext context = await GetWebSocketContext(); await Assert.ThrowsAsync <WebSocketException>(() => context.AcceptWebSocketAsync("SubProtocol")); }
public async Task GetResponseAsync(HttpListenerContext context, string localBaseUrl, string remoteBaseUrl, CancellationToken ct) { string postUri = null; if (context.Request.IsWebSocketRequest) { UriBuilder ub = new UriBuilder(PostUri) { Scheme = "wss" }; postUri = ub.Uri.ToString(); } else { postUri = PostUri.ToString(); } HttpWebRequest request = (HttpWebRequest)WebRequest.Create(postUri); request.Method = context.Request.HttpMethod; request.ServerCertificateValidationCallback += ValidateCertificate; if (!context.Request.IsWebSocketRequest) { SetRequestHeaders(request, context.Request.Headers, localBaseUrl, remoteBaseUrl); } // Add RTVS headers request.Headers.Add(CustomHttpHeaders.RTVSRequestedURL, GetRemoteUrl(context.Request.Url, remoteBaseUrl)); if (context.Request.InputStream.CanSeek && context.Request.InputStream.Length > 0) { using (Stream reqStream = await request.GetRequestStreamAsync()) { await context.Request.InputStream.CopyAndFlushAsync(reqStream); } } HttpWebResponse response = null; try { response = (HttpWebResponse)await request.GetResponseAsync(); } catch (WebException wex) { if (wex.Status == WebExceptionStatus.ProtocolError) { response = wex.Response as HttpWebResponse; } else { throw wex; } } finally { if (response != null) { if (context.Request.IsWebSocketRequest && response.StatusCode == HttpStatusCode.SwitchingProtocols) { Stream respStream = response.GetResponseStream(); string subProtocol = response.Headers[Constants.Headers.SecWebSocketProtocol]; var remoteWebSocket = CommonWebSocket.CreateClientWebSocket(respStream, subProtocol, TimeSpan.FromMinutes(10), receiveBufferSize: 65335, useZeroMask: true); var websocketContext = await context.AcceptWebSocketAsync(subProtocol, receiveBufferSize : 65335, keepAliveInterval : TimeSpan.FromMinutes(10)); await WebSocketHelper.SendReceiveAsync(websocketContext.WebSocket, remoteWebSocket, ct); } else { context.Response.StatusCode = (int)response.StatusCode; SetResponseHeaders(response, context.Response, localBaseUrl, remoteBaseUrl); using (Stream respStream = response.GetResponseStream()) using (Stream outStream = context.Response.OutputStream) { await respStream.CopyAndFlushAsync(outStream); } response.Close(); } } } }
public async Task AcceptWebSocketAsync_NoSuchSubProtocol_ThrowsWebSocketException(string subProtocol) { HttpListenerContext context = await GetWebSocketContext(); await Assert.ThrowsAsync <WebSocketException>(() => context.AcceptWebSocketAsync(subProtocol)); }
// ------------------------------------------------------------------------------------ public async Task Spawn_Context(HttpListenerContext context, uint idx_context) { // AcceptWebSocketAsync() は、キャンセルトークンをサポートしていない // 引数: サポートされている WebSocket サブプロトコル HttpListenerWebSocketContext wsc = await context.AcceptWebSocketAsync(null); MainForm.StdOut("--- WebSocket 接続完了\r\n"); using (m_WS = wsc.WebSocket) using (WS_Buf_Pool.MemBlock mem_blk = WS_Buf_Pool.Lease_MemBlock()) { m_read_WS_buf = new Read_WS_Buf(mem_blk.m_ary_buf); m_write_WS_buf = new Write_WS_Buffer(mem_blk.m_ary_buf); try { // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< #if CREATE_TEST_LEXED_CODE // Test Lexed Code を送信する Write_WS_Buffer write_ws_buf = MainForm.ms_DBG_write_WS_buf; await m_WS.SendAsync( new ArraySegment <byte>(write_ws_buf.Get_buf(), 0, write_ws_buf.Get_idx_byte_cur()) , WebSocketMessageType.Binary, true, ms_cts_shutdown.Token); #else // まずはルートフォルダのファイル情報を送信しておく FileLister.Set_DirFileNames(m_write_WS_buf, "./"); await m_write_WS_buf.SendAsync(m_WS, ms_cts_shutdown); #endif while (true) { WebSocketReceiveResult rslt = await m_WS.ReceiveAsync( new ArraySegment <byte>(mem_blk.m_ary_buf), ms_cts_shutdown.Token); if (rslt.EndOfMessage == false) { MainForm.StdOut("--- 不正な大きさのデータを受信しました。クライアントを切断します\r\n"); break; } if (m_WS.State == WebSocketState.CloseReceived) { MainForm.StdOut("--- クライアントが接続を Close しました\r\n"); break; } m_read_WS_buf.Renew(rslt.Count); switch (m_read_WS_buf.Read_ID()) { case ID.DirFileList: { ID id = m_read_WS_buf.Read_ID(); if (id != ID.Text) { throw new Exception($"不正なパラメータを受信 DirFileList / id -> {((byte)id).ToString()}"); } FileLister.Set_DirFileNames(m_write_WS_buf, m_read_WS_buf.Get_text_cur()); await m_write_WS_buf.SendAsync(m_WS, ms_cts_shutdown); } continue; case ID.Files_inDir: { ID id = m_read_WS_buf.Read_ID(); if (id != ID.Text) { throw new Exception($"不正なパラメータを受信 Files_inDir / id -> {((byte)id).ToString()}"); } string str_path_dir = m_read_WS_buf.Get_text_cur(); id = m_read_WS_buf.Read_ID(); if (id != ID.Num_int) { throw new Exception($"不正なパラメータを受信 Files_inDir / id -> {((byte)id).ToString()}"); } int SEC_Updated_recv = m_read_WS_buf.Get_Num_int(); FileLister.OnFiles_inDir(m_write_WS_buf, str_path_dir, SEC_Updated_recv); await m_write_WS_buf.SendAsync(m_WS, ms_cts_shutdown); } continue; case ID.MD_file: { var(path_md_file, SEC_Updated, idx_byte_SEC_updated) = m_read_WS_buf.Read_Req_MD(); MainForm.StdOut($"path_md_file : {path_md_file} / SEC_Updated : {SEC_Updated.ToString()}\r\n"); // ID.MD_file -> ID_Text (path_dir) -> ID_Text (file name) は Receive時の値を流用 m_write_WS_buf.Set_idx_byte(idx_byte_SEC_updated); m_write_WS_buf.Wrt_Num_int(1000); // 1000 は試験値 Lexer.LexFile(m_write_WS_buf, path_md_file); MainForm.StdOut("--- Lexing 処理完了\r\n"); m_write_WS_buf.Simplify_Buf(); MainForm.StdOut("--- Simplify_Buf 処理完了\r\n"); await m_write_WS_buf.SendAsync(m_WS, ms_cts_shutdown); } continue; } MainForm.StdOut($"--- ReceiveAsync() : 受信バイト数 -> {rslt.Count}\r\n"); MainForm.HexDump(mem_blk.m_ary_buf, 0, 20); DBG_WS_Buffer.Show_WS_buf(MainForm.ms_RBox_stdout, mem_blk.m_ary_buf, rslt.Count); // 今は、index.md のみを解析するようにしている // string ret_str = Lexer.LexFile(m_write_WS_buf, "md_root/index.md"); // string str_recv = ms_utf16_encoding.GetString(mem_blk.m_ary_buf, 0, rslt.Count); // MainForm.StdOut(str_recv); } await m_WS.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "接続を終了します", ms_cts_shutdown.Token); } catch (OperationCanceledException) { MainForm.StdOut("--- サーバーシャットダウンのシグナルを受信しました\r\n"); } catch (WebSocketException ex) { MainForm.StdOut($"!!! 例外発を補足しました WebSoketErrorCode : {ex.WebSocketErrorCode.ToString()}\r\n"); MainForm.StdOut($" {ex.ToString()}\r\n"); } catch (Exception ex) { MainForm.StdOut($"!!! 例外を補足しました : {ex.ToString()}\r\n"); } } MdSvr.Remove_task_context(idx_context); MainForm.StdOut("--- WebSocket 切断完了\r\n"); }
public async Task AcceptWebSocketAsync_InvalidReceiveBufferSize_ThrowsWebSocketException(int receiveBufferSize) { HttpListenerContext context = await GetWebSocketContext(); await Assert.ThrowsAsync <ArgumentOutOfRangeException>("receiveBufferSize", () => context.AcceptWebSocketAsync(null, receiveBufferSize, TimeSpan.MaxValue)); }
public async Task GetResponseAsync(HttpListenerContext context, string localBaseUrl, string remoteBaseUrl, CancellationToken ct) { string postUri; if (context.Request.IsWebSocketRequest) { var ub = new UriBuilder(PostUri) { Scheme = "wss" }; postUri = ub.Uri.ToString(); } else { postUri = PostUri.ToString(); } var request = (HttpWebRequest)WebRequest.Create(postUri); request.Method = context.Request.HttpMethod; request.ServerCertificateValidationCallback += ValidateCertificate; if (!context.Request.IsWebSocketRequest) { SetRequestHeaders(request, context.Request.Headers, localBaseUrl, remoteBaseUrl); } // Add RTVS headers var remoteUri = GetRemoteUri(context.Request.Url, remoteBaseUrl); request.Headers.Add(CustomHttpHeaders.RTVSRequestedURL, remoteUri.ToString()); if (context.Request.ContentLength64 > 0) { using (var reqStream = await request.GetRequestStreamAsync()) { await context.Request.InputStream.CopyAndFlushAsync(reqStream, null, ct); } } HttpWebResponse response = null; try { response = (HttpWebResponse)await request.GetResponseAsync(); if (response != null) { if (context.Request.IsWebSocketRequest && response.StatusCode == HttpStatusCode.SwitchingProtocols) { var respStream = response.GetResponseStream(); var subProtocol = response.Headers[Constants.Headers.SecWebSocketProtocol]; var remoteWebSocket = CommonWebSocket.CreateClientWebSocket(respStream, subProtocol, TimeSpan.FromMinutes(10), receiveBufferSize: _receiveBufferSize, useZeroMask: true); var websocketContext = await context.AcceptWebSocketAsync(subProtocol, receiveBufferSize : _receiveBufferSize, keepAliveInterval : TimeSpan.FromMinutes(10)); await WebSocketHelper.SendReceiveAsync(websocketContext.WebSocket, remoteWebSocket, ct); } else { context.Response.StatusCode = (int)response.StatusCode; SetResponseHeaders(response, context.Response, localBaseUrl, remoteBaseUrl); using (var respStream = response.GetResponseStream()) using (var outStream = context.Response.OutputStream) { await respStream.CopyAndFlushAsync(outStream, null, ct); } response.Close(); } } } catch (WebException wex) when(wex.Status == WebExceptionStatus.ProtocolError) { response = wex.Response as HttpWebResponse; } catch (OperationCanceledException) { WebServer.Stop(remoteUri.Port); } catch (Exception ex) when(!ex.IsCriticalException()) { _log.WriteLine(LogVerbosity.Normal, MessageCategory.Error, Resources.Error_RemoteWebServerException.FormatInvariant(ex.Message)); _console?.WriteErrorLine(Resources.Error_RemoteWebServerException.FormatInvariant(ex.Message)); WebServer.Stop(remoteUri.Port); } finally { response?.Close(); } }
public async Task AcceptWebSocketAsync_InvalidCountInArraySegment_ThrowsArgumentNullException(int offset, int count) { HttpListenerContext context = await GetWebSocketContext(); ArraySegment <byte> internalBuffer = new FakeArraySegment() { Array = new byte[10], Offset = offset, Count = count }.ToActual(); await AssertExtensions.ThrowsAsync <ArgumentOutOfRangeException>("internalBuffer.Count", () => context.AcceptWebSocketAsync(null, 1024, TimeSpan.MaxValue, internalBuffer)); }
public async Task <HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol) { return(await CoreContext.AcceptWebSocketAsync(subProtocol)); }