You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
5.2 KiB
175 lines
5.2 KiB
11 months ago
|
#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
|
||
|
|
||
|
/// <summary>
|
||
|
/// Websocket transport specific connection logic. It will create a WebSocket instance, and starts to connect to the server.
|
||
|
/// </summary>
|
||
|
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);
|
||
|
|
||
|
// Set up eventhandlers
|
||
|
wSocket.OnOpen += WSocket_OnOpen;
|
||
|
wSocket.OnMessage += WSocket_OnMessage;
|
||
|
wSocket.OnClosed += WSocket_OnClosed;
|
||
|
wSocket.OnError += WSocket_OnError;
|
||
|
|
||
|
#if !UNITY_WEBGL || UNITY_EDITOR
|
||
|
// prepare the internal http request
|
||
|
wSocket.OnInternalRequestCreated = (ws, internalRequest) => Connection.PrepareRequest(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.OnError = null;
|
||
|
wSocket.Close();
|
||
|
wSocket = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override void Started()
|
||
|
{
|
||
|
// Nothing to be done here for this transport
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// The /abort request successfully finished
|
||
|
/// </summary>
|
||
|
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
|
||
|
{
|
||
|
if (HTTPManager.Logger.Level == Logger.Loglevels.All)
|
||
|
HTTPManager.Logger.Error("WebSocketTransport", "WSocket_OnError " + reason);
|
||
|
|
||
|
this.State = TransportStates.Closed;
|
||
|
Connection.Error(reason);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endregion
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
#endif
|