private async Task HandleListenerCore(CancellationToken token) { try { HttpListenerContext context = await _httpListener.GetContextAsync().ConfigureAwait(false); if (token.IsCancellationRequested) { CleanUpContext(context); return; } var headers = GetCombinedHeaders(context.Request.Headers, context.Request.QueryString); if (IsServerCapabilitiesRequest(context.Request)) { Logger.Info($"Handling ServerCapabilities request from {context.Request.RemoteEndPoint}."); HandleServerCapabilitiesRequest(context.Response, headers); CleanUpContext(context); return; } if (!context.Request.IsWebSocketRequest) { CleanUpContext(context); return; } Logger.Info($"Handling WebSocket request from {context.Request.RemoteEndPoint}."); if (!EtpWebSocketValidation.IsWebSocketRequestUpgrading(headers)) { context.Response.StatusCode = (int)HttpStatusCode.UpgradeRequired; Logger.Debug($"Invalid web socket request"); context.Response.StatusDescription = "Invalid web socket request"; CleanUpContext(context); return; } var preferredProtocol = EtpWebSocketValidation.GetPreferredSubProtocol(headers); if (preferredProtocol == null) { context.Response.StatusCode = (int)HttpStatusCode.BadRequest; context.Response.StatusDescription = "Invalid web socket request"; Logger.Debug($"Invalid web socket request"); CleanUpContext(context); return; } var encoding = EtpWebSocketValidation.GetEtpEncoding(headers); if (encoding == null) { context.Response.StatusCode = (int)HttpStatusCode.PreconditionFailed; Logger.Debug($"Error getting ETP encoding."); context.Response.StatusDescription = "Invalid etp-encoding header"; CleanUpContext(context); return; } if (!Details.IsEncodingSupported(encoding.Value)) { context.Response.StatusCode = (int)HttpStatusCode.PreconditionFailed; Logger.Debug($"Encoding not supported: {encoding.Value}"); context.Response.StatusDescription = "Unsupported etp-encoding"; CleanUpContext(context); return; } HttpListenerWebSocketContext webSocketContext = await context.AcceptWebSocketAsync(preferredProtocol).ConfigureAwait(false); if (token.IsCancellationRequested) { webSocketContext.WebSocket.Dispose(); context.Response.Close(); return; } var version = EtpWebSocketValidation.GetEtpVersion(preferredProtocol); if (!Details.IsVersionSupported(version)) { context.Response.StatusCode = (int)HttpStatusCode.PreconditionFailed; Logger.Debug($"Sub protocol not supported: {preferredProtocol}"); context.Response.StatusDescription = "Sub protocol not supported"; CleanUpContext(context); return; } var ws = new EtpServerWebSocket { WebSocket = webSocketContext.WebSocket }; var server = ServerManager.CreateServer(ws, version, encoding.Value, headers); server.Start(); } catch (Exception ex) { if (!ex.ExceptionMeansConnectionTerminated()) { ServerManager.Log("Error: Exception caught when handling a websocket connection: {0}", ex.Message); Logger.DebugFormat("Exception caught when handling a websocket connection: {0}", ex); throw; } } }
private async Task HandleListener(CancellationToken token) { try { // TODO: Handle server cap URL HttpListenerContext context = await _httpListener.GetContextAsync(); if (token.IsCancellationRequested) { CleanUpContext(context); return; } var headers = GetWebSocketHeaders(context.Request.Headers, context.Request.QueryString); if (!context.Request.IsWebSocketRequest) { CleanUpContext(context); return; } if (!EtpWebSocketValidation.IsWebSocketRequestUpgrading(headers)) { context.Response.StatusCode = (int)HttpStatusCode.UpgradeRequired; context.Response.StatusDescription = "Invalid web socket request"; CleanUpContext(context); return; } var preferredProtocol = EtpWebSocketValidation.GetPreferredSubProtocol(headers); if (preferredProtocol == null) { context.Response.StatusCode = (int)HttpStatusCode.BadRequest; context.Response.StatusDescription = "Invalid web socket request"; CleanUpContext(context); return; } if (!EtpWebSocketValidation.IsEtpEncodingValid(headers)) { context.Response.StatusCode = (int)HttpStatusCode.PreconditionFailed; context.Response.StatusDescription = "Invalid etp-encoding header"; CleanUpContext(context); return; } HttpListenerWebSocketContext webSocketContext = await context.AcceptWebSocketAsync(preferredProtocol); if (token.IsCancellationRequested) { webSocketContext.WebSocket.Dispose(); context.Response.Close(); return; } var server = new EtpServer(webSocketContext.WebSocket, ApplicationName, ApplicationVersion, headers); server.SupportedObjects = SupportedObjects; RegisterAll(server); _servers[server.SessionId] = server; _serverTasks[server.SessionId] = Task.Run(async() => { try { InvokeSessionConnected(server); await server.HandleConnection(token); } finally { InvokeSessionClosed(server); CleanUpServer(server); webSocketContext.WebSocket.Dispose(); CleanUpContext(context); } }, token); } catch (Exception ex) { if (!ex.ExceptionMeansConnectionTerminated()) { Log("Error: Exception caught when handling a websocket connection: {0}", ex.Message); Logger.DebugFormat("Exception caught when handling a websocket connection: {0}", ex); throw; } } }