/// <summary> /// Initializes a new instance of the <see cref="EtpServer"/> class. /// </summary> /// <param name="webSocket">The web socket.</param> /// <param name="application">The server application name.</param> /// <param name="version">The server application version.</param> /// <param name="headers">The WebSocket or HTTP headers.</param> public EtpServer(WebSocket webSocket, string application, string version, IDictionary <string, string> headers) : base(EtpWebSocketValidation.GetEtpVersion(webSocket.SubProtocol), webSocket, application, version, headers, false) { var etpVersion = EtpWebSocketValidation.GetEtpVersion(Socket.SubProtocol); SessionId = Guid.NewGuid().ToString(); }
/// <summary> /// Initializes a new instance of the <see cref="EtpClient"/> class. /// </summary> /// <param name="uri">The ETP server URI.</param> /// <param name="application">The client application name.</param> /// <param name="version">The client application version.</param> /// <param name="etpSubProtocol">The ETP sub protocol.</param> /// <param name="headers">The WebSocket headers.</param> public EtpClient(string uri, string application, string version, string etpSubProtocol, IDictionary <string, string> headers) : base(EtpWebSocketValidation.GetEtpVersion(etpSubProtocol), application, version, headers, true) { var headerItems = Headers.Union(BinaryHeaders.Where(x => !Headers.ContainsKey(x.Key))).ToList(); _socket = new WebSocket(uri, subProtocol: etpSubProtocol, cookies: null, customHeaderItems: headerItems, userAgent: application); }
/// <summary> /// Initializes a new instance of the <see cref="EtpClient"/> class. /// </summary> /// <param name="uri">The ETP server URI.</param> /// <param name="application">The client application name.</param> /// <param name="version">The client application version.</param> /// <param name="etpSubProtocol">The ETP sub protocol.</param> /// <param name="headers">The WebSocket headers.</param> public EtpClient(string uri, string application, string version, string etpSubProtocol, IDictionary <string, string> headers) : base(EtpWebSocketValidation.GetEtpVersion(etpSubProtocol), new ClientWebSocket(), application, version, headers, true) { var headerItems = Headers.Union(BinaryHeaders.Where(x => !Headers.ContainsKey(x.Key))).ToList(); ClientSocket.Options.AddSubProtocol(etpSubProtocol); foreach (var item in headerItems) { ClientSocket.Options.SetRequestHeader(item.Key, item.Value); } Uri = new Uri(uri); // NOTE: User-Agent cannot be set on a .NET Framework ClientWebSocket: // https://github.com/dotnet/corefx/issues/26627 }
/// <summary> /// Called when a WebSocket session is connected. /// </summary> /// <param name="session">The session.</param> private void OnNewSessionConnected(WebSocketSession session) { Logger.Info($"Handling WebSocket request from {session.RemoteEndPoint}."); var ws = new EtpServerWebSocket { WebSocketSession = session }; _webSockets[session.SessionID] = ws; var headers = new Dictionary <string, string>(); foreach (var item in session.Items) { headers[item.Key.ToString()] = item.Value.ToString(); } var version = EtpWebSocketValidation.GetEtpVersion(session.SubProtocol.Name); var encoding = EtpWebSocketValidation.GetEtpEncoding(headers); if (!Details.IsVersionSupported(version)) { Logger.Debug($"Sub protocol not supported: {session.SubProtocol.Name}"); session.Close(CloseReason.ApplicationError); return; } if (encoding == null) { Logger.Debug($"Error getting ETP encoding."); session.Close(CloseReason.ApplicationError); return; } if (!Details.IsEncodingSupported(encoding.Value)) { Logger.Debug($"Encoding not supported: {encoding.Value}"); session.Close(CloseReason.ApplicationError); return; } var server = ServerManager.CreateServer(ws, version, encoding.Value, headers); server.Start(); }
/// <summary> /// Initializes a new instance of the <see cref="EtpServer"/> class. /// </summary> /// <param name="session">The web socket session.</param> /// <param name="application">The serve application name.</param> /// <param name="version">The server application version.</param> /// <param name="headers">The WebSocket or HTTP headers.</param> public EtpServer(WebSocketSession session, string application, string version, IDictionary <string, string> headers) : base(EtpWebSocketValidation.GetEtpVersion(session.SubProtocol.Name), application, version, headers, false, false) { SessionId = session.SessionID; _session = session; }
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; } } }