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.
171 lines
4.9 KiB
171 lines
4.9 KiB
11 months ago
|
#if !BESTHTTP_DISABLE_SIGNALR
|
||
|
#if !BESTHTTP_DISABLE_SERVERSENT_EVENTS
|
||
|
|
||
|
using System;
|
||
|
|
||
|
using BestHTTP.ServerSentEvents;
|
||
|
using BestHTTP.SignalR.Messages;
|
||
|
|
||
|
namespace BestHTTP.SignalR.Transports
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// A SignalR transport implementation that uses the Server-Sent Events protocol.
|
||
|
/// </summary>
|
||
|
public sealed class ServerSentEventsTransport : PostSendTransportBase
|
||
|
{
|
||
|
#region Overridden Properties
|
||
|
|
||
|
/// <summary>
|
||
|
/// It's a persistent connection. We support the keep-alive mechanism.
|
||
|
/// </summary>
|
||
|
public override bool SupportsKeepAlive { get { return true; } }
|
||
|
|
||
|
/// <summary>
|
||
|
/// Type of the transport.
|
||
|
/// </summary>
|
||
|
public override TransportTypes Type { get { return TransportTypes.ServerSentEvents; } }
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
#region Privates
|
||
|
|
||
|
/// <summary>
|
||
|
/// The EventSource object.
|
||
|
/// </summary>
|
||
|
private EventSource EventSource;
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
public ServerSentEventsTransport(Connection con)
|
||
|
: base("serverSentEvents", con)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
#region Overrides from TransportBase
|
||
|
|
||
|
public override void Connect()
|
||
|
{
|
||
|
if (EventSource != null)
|
||
|
{
|
||
|
HTTPManager.Logger.Warning("ServerSentEventsTransport", "Start - EventSource 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);
|
||
|
|
||
|
EventSource = new EventSource(uri);
|
||
|
|
||
|
EventSource.OnOpen += OnEventSourceOpen;
|
||
|
EventSource.OnMessage += OnEventSourceMessage;
|
||
|
EventSource.OnError += OnEventSourceError;
|
||
|
EventSource.OnClosed += OnEventSourceClosed;
|
||
|
|
||
|
#if !UNITY_WEBGL || UNITY_EDITOR
|
||
|
// Disable internal retry
|
||
|
EventSource.OnRetry += (es) => false;
|
||
|
#endif
|
||
|
|
||
|
// Start connecting to the server.
|
||
|
EventSource.Open();
|
||
|
}
|
||
|
|
||
|
public override void Stop()
|
||
|
{
|
||
|
EventSource.OnOpen -= OnEventSourceOpen;
|
||
|
EventSource.OnMessage -= OnEventSourceMessage;
|
||
|
EventSource.OnError -= OnEventSourceError;
|
||
|
EventSource.OnClosed -= OnEventSourceClosed;
|
||
|
|
||
|
EventSource.Close();
|
||
|
|
||
|
EventSource = null;
|
||
|
}
|
||
|
|
||
|
protected override void Started()
|
||
|
{
|
||
|
// Nothing to do here for this transport
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// A custom Abort function where we will start to close the EventSource object.
|
||
|
/// </summary>
|
||
|
public override void Abort()
|
||
|
{
|
||
|
base.Abort();
|
||
|
|
||
|
EventSource.Close();
|
||
|
}
|
||
|
|
||
|
protected override void Aborted()
|
||
|
{
|
||
|
if (this.State == TransportStates.Closing)
|
||
|
this.State = TransportStates.Closed;
|
||
|
}
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
#region EventSource Event Handlers
|
||
|
|
||
|
private void OnEventSourceOpen(EventSource eventSource)
|
||
|
{
|
||
|
HTTPManager.Logger.Information("Transport - " + this.Name, "OnEventSourceOpen");
|
||
|
}
|
||
|
|
||
|
private void OnEventSourceMessage(EventSource eventSource, BestHTTP.ServerSentEvents.Message message)
|
||
|
{
|
||
|
if (message.Data.Equals("initialized"))
|
||
|
{
|
||
|
base.OnConnected();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
IServerMessage msg = TransportBase.Parse(Connection.JsonEncoder, message.Data);
|
||
|
|
||
|
if (msg != null)
|
||
|
Connection.OnMessage(msg);
|
||
|
|
||
|
}
|
||
|
|
||
|
private void OnEventSourceError(EventSource eventSource, string error)
|
||
|
{
|
||
|
HTTPManager.Logger.Information("Transport - " + this.Name, "OnEventSourceError");
|
||
|
|
||
|
// We are in a reconnecting phase, we have to connect now.
|
||
|
if (this.State == TransportStates.Reconnecting)
|
||
|
{
|
||
|
Connect();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Already closed?
|
||
|
if (this.State == TransportStates.Closed)
|
||
|
return;
|
||
|
|
||
|
// Closing? Then we are closed now.
|
||
|
if (this.State == TransportStates.Closing)
|
||
|
this.State = TransportStates.Closed;
|
||
|
else // Errored when we didn't expected it.
|
||
|
Connection.Error(error);
|
||
|
}
|
||
|
|
||
|
private void OnEventSourceClosed(ServerSentEvents.EventSource eventSource)
|
||
|
{
|
||
|
HTTPManager.Logger.Information("Transport - " + this.Name, "OnEventSourceClosed");
|
||
|
|
||
|
OnEventSourceError(eventSource, "EventSource Closed!");
|
||
|
}
|
||
|
|
||
|
#endregion
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
#endif
|