#if !BESTHTTP_DISABLE_SIGNALR #if !BESTHTTP_DISABLE_WEBSOCKET using System; using System.Text; using BestHTTP; using BestHTTP.JSON; using BestHTTP.SignalR.Hubs; using BestHTTP.SignalR.Messages; using BestHTTP.SignalR.JsonEncoders; namespace BestHTTP.SignalR.Transports { public sealed class WebSocketTransport : TransportBase { #region Overridden Properties public override bool SupportsKeepAlive { get { return true; } } public override TransportTypes Type { get { return TransportTypes.WebSocket; } } #endregion private WebSocket.WebSocket wSocket; public WebSocketTransport(Connection connection) : base("webSockets", connection) { } #region Overrides from TransportBase /// /// Websocket transport specific connection logic. It will create a WebSocket instance, and starts to connect to the server. /// public override void Connect() { if (wSocket != null) { HTTPManager.Logger.Warning("WebSocketTransport", "Start - WebSocket already created!"); return; } // Skip the Connecting state if we are reconnecting. If the connect succeeds, we will set the Started state directly if (this.State != TransportStates.Reconnecting) this.State = TransportStates.Connecting; RequestTypes requestType = this.State == TransportStates.Reconnecting ? RequestTypes.Reconnect : RequestTypes.Connect; Uri uri = Connection.BuildUri(requestType, this); // Create the WebSocket instance wSocket = new WebSocket.WebSocket(uri); // SaveLocal up eventhandlers wSocket.OnOpen += WSocket_OnOpen; wSocket.OnMessage += WSocket_OnMessage; wSocket.OnClosed += WSocket_OnClosed; wSocket.OnErrorDesc += WSocket_OnError; #if !UNITY_WEBGL || UNITY_EDITOR // prepare the internal http request Connection.PrepareRequest(wSocket.InternalRequest, requestType); #endif // start opening the websocket protocol wSocket.Open(); } protected override void SendImpl(string json) { if (wSocket != null && wSocket.IsOpen) wSocket.Send(json); } public override void Stop() { if (wSocket != null) { wSocket.OnOpen = null; wSocket.OnMessage = null; wSocket.OnClosed = null; wSocket.OnErrorDesc = null; wSocket.Close(); wSocket = null; } } protected override void Started() { // Nothing to be done here for this transport } /// /// The /abort request successfully finished /// protected override void Aborted() { // if the websocket is still open, close it if (wSocket != null && wSocket.IsOpen) { wSocket.Close(); wSocket = null; } } #endregion #region WebSocket Events void WSocket_OnOpen(WebSocket.WebSocket webSocket) { if (webSocket != wSocket) return; HTTPManager.Logger.Information("WebSocketTransport", "WSocket_OnOpen"); OnConnected(); } void WSocket_OnMessage(WebSocket.WebSocket webSocket, string message) { if (webSocket != wSocket) return; IServerMessage msg = TransportBase.Parse(Connection.JsonEncoder, message); if (msg != null) Connection.OnMessage(msg); } void WSocket_OnClosed(WebSocket.WebSocket webSocket, ushort code, string message) { if (webSocket != wSocket) return; string reason = code.ToString() + " : " + message; HTTPManager.Logger.Information("WebSocketTransport", "WSocket_OnClosed " + reason); if (this.State == TransportStates.Closing) this.State = TransportStates.Closed; else Connection.Error(reason); } void WSocket_OnError(WebSocket.WebSocket webSocket, string reason) { if (webSocket != wSocket) return; // On WP8.1, somehow we receive an exception that the remote server forcibly closed the connection instead of the // WebSocket closed packet... Also, even the /abort request didn't finished. if (this.State == TransportStates.Closing || this.State == TransportStates.Closed) { base.AbortFinished(); } else { HTTPManager.Logger.Error("WebSocketTransport", "WSocket_OnError " + reason); this.State = TransportStates.Closed; Connection.Error(reason); } } #endregion } } #endif #endif