#if !BESTHTTP_DISABLE_SOCKETIO
using System.Collections.Generic;
namespace BestHTTP.SocketIO.Events
{
///
/// This class helps keep track and maintain EventDescriptor instances and dispatching packets to the right delegates.
///
internal sealed class EventTable
{
#region Privates
///
/// The Socket that this EventTable is bound to.
///
private Socket Socket { get; set; }
///
/// The 'EventName -> List of events' mapping.
///
private Dictionary> Table = new Dictionary>();
#endregion
///
/// Constructor to create an instance and bind it to a socket.
///
public EventTable(Socket socket)
{
this.Socket = socket;
}
///
/// Register a callback to a name with the given metadata.
///
public void Register(string eventName, SocketIOCallback callback, bool onlyOnce, bool autoDecodePayload)
{
List events;
if (!Table.TryGetValue(eventName, out events))
Table.Add(eventName, events = new List(1));
// Find a matching desriptor
var desc = events.Find((d) => d.OnlyOnce == onlyOnce && d.AutoDecodePayload == autoDecodePayload);
// If not found, create one
if (desc == null)
events.Add(new EventDescriptor(onlyOnce, autoDecodePayload, callback));
else // if found, add the new callback
desc.Callbacks.Add(callback);
}
///
/// Removes all events that registered for the given name.
///
public void Unregister(string eventName)
{
Table.Remove(eventName);
}
///
///
///
public void Unregister(string eventName, SocketIOCallback callback)
{
List events;
if (Table.TryGetValue(eventName, out events))
for (int i = 0; i < events.Count; ++i)
events[i].Callbacks.Remove(callback);
}
///
/// Will call the delegates that associated to the given eventName.
///
public void Call(string eventName, Packet packet, params object[] args)
{
if (HTTPManager.Logger.Level <= BestHTTP.Logger.Loglevels.All)
HTTPManager.Logger.Verbose("EventTable", "Call - " + eventName);
List events;
if (Table.TryGetValue(eventName, out events))
for (int i = 0; i < events.Count; ++i)
events[i].Call(Socket, packet, args);
}
///
/// This function will get the eventName from the packet's Payload, and optionally will decode it from Json.
///
public void Call(Packet packet)
{
string eventName = packet.DecodeEventName();
string typeName = packet.SocketIOEvent != SocketIOEventTypes.Unknown ? EventNames.GetNameFor(packet.SocketIOEvent) : EventNames.GetNameFor(packet.TransportEvent);
object[] args = null;
if (!HasSubsciber(eventName) && !HasSubsciber(typeName))
return;
// If this is an Event or BinaryEvent message, or we have a subscriber with AutoDecodePayload, then
// we have to decode the packet's Payload.
if (packet.TransportEvent == TransportEventTypes.Message && (packet.SocketIOEvent == SocketIOEventTypes.Event || packet.SocketIOEvent == SocketIOEventTypes.BinaryEvent) && ShouldDecodePayload(eventName))
args = packet.Decode(Socket.Manager.Encoder);
// call event callbacks registered for 'eventName'
if (!string.IsNullOrEmpty(eventName))
Call(eventName, packet, args);
if (!packet.IsDecoded && ShouldDecodePayload(typeName))
args = packet.Decode(Socket.Manager.Encoder);
// call event callbacks registered for 'typeName'
if (!string.IsNullOrEmpty(typeName))
Call(typeName, packet, args);
}
///
/// Remove all event -> delegate association.
///
public void Clear()
{
Table.Clear();
}
#region Private Helpers
///
/// Returns true, if for the given event name there are at least one event that needs a decoded
///
///
///
private bool ShouldDecodePayload(string eventName)
{
List events;
// If we find at least one EventDescriptor with AutoDecodePayload == true, we have to
// decode the whole payload
if (Table.TryGetValue(eventName, out events))
for (int i = 0; i < events.Count; ++i)
if (events[i].AutoDecodePayload && events[i].Callbacks.Count > 0)
return true;
return false;
}
private bool HasSubsciber(string eventName)
{
return Table.ContainsKey(eventName);
}
#endregion
}
}
#endif