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.
354 lines
12 KiB
354 lines
12 KiB
1 year ago
|
#if !BESTHTTP_DISABLE_SIGNALR
|
||
|
|
||
|
#if BESTHTTP_SIGNALR_WITH_JSONDOTNET
|
||
|
using Newtonsoft.Json.Linq;
|
||
|
#endif
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
|
||
|
namespace BestHTTP.SignalR.Messages
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Keep-alive message sent by the server. No data sent with it.
|
||
|
/// </summary>
|
||
|
public sealed class KeepAliveMessage : IServerMessage
|
||
|
{
|
||
|
MessageTypes IServerMessage.Type { get { return MessageTypes.KeepAlive; } }
|
||
|
void IServerMessage.Parse(object data) { }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// A message that may contains multiple sub-messages and additional informations.
|
||
|
/// </summary>
|
||
|
public sealed class MultiMessage : IServerMessage
|
||
|
{
|
||
|
MessageTypes IServerMessage.Type { get { return MessageTypes.Multiple; } }
|
||
|
|
||
|
/// <summary>
|
||
|
/// Id of the sent message
|
||
|
/// </summary>
|
||
|
public string MessageId { get; private set; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// True if it's an initialization message, false otherwise.
|
||
|
/// </summary>
|
||
|
public bool IsInitialization { get; private set; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// Group token may be sent, if the group changed that the client belongs to.
|
||
|
/// </summary>
|
||
|
public string GroupsToken { get; private set; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// The server suggests that the client should do a reconnect turn.
|
||
|
/// </summary>
|
||
|
public bool ShouldReconnect { get; private set; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// Additional poll delay sent by the server.
|
||
|
/// </summary>
|
||
|
public TimeSpan? PollDelay { get; private set; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// List of server messages sent inside this message.
|
||
|
/// </summary>
|
||
|
public List<IServerMessage> Data { get; private set; }
|
||
|
|
||
|
void IServerMessage.Parse(object data)
|
||
|
{
|
||
|
IDictionary<string, object> dic = data as IDictionary<string, object>;
|
||
|
object value;
|
||
|
|
||
|
this.MessageId = dic["C"].ToString();
|
||
|
|
||
|
if (dic.TryGetValue("S", out value))
|
||
|
IsInitialization = int.Parse(value.ToString()) == 1 ? true : false;
|
||
|
else
|
||
|
IsInitialization = false;
|
||
|
|
||
|
if (dic.TryGetValue("G", out value))
|
||
|
GroupsToken = value.ToString();
|
||
|
|
||
|
if (dic.TryGetValue("T", out value))
|
||
|
ShouldReconnect = int.Parse(value.ToString()) == 1 ? true : false;
|
||
|
else
|
||
|
ShouldReconnect = false;
|
||
|
|
||
|
if (dic.TryGetValue("L", out value))
|
||
|
PollDelay = TimeSpan.FromMilliseconds(double.Parse(value.ToString()));
|
||
|
|
||
|
IEnumerable enumerable = dic["M"] as IEnumerable;
|
||
|
|
||
|
if (enumerable != null)
|
||
|
{
|
||
|
Data = new List<IServerMessage>();
|
||
|
|
||
|
foreach (object subData in enumerable)
|
||
|
{
|
||
|
#if BESTHTTP_SIGNALR_WITH_JSONDOTNET
|
||
|
IDictionary<string, JToken> subObj = subData as IDictionary<string, JToken>;
|
||
|
#else
|
||
|
IDictionary<string, object> subObj = subData as IDictionary<string, object>;
|
||
|
#endif
|
||
|
|
||
|
IServerMessage subMsg = null;
|
||
|
|
||
|
if (subObj != null)
|
||
|
{
|
||
|
if (subObj.ContainsKey("H"))
|
||
|
subMsg = new MethodCallMessage();
|
||
|
else if (subObj.ContainsKey("I"))
|
||
|
subMsg = new ProgressMessage();
|
||
|
else
|
||
|
subMsg = new DataMessage();
|
||
|
}
|
||
|
else
|
||
|
subMsg = new DataMessage();
|
||
|
|
||
|
subMsg.Parse(subData);
|
||
|
|
||
|
Data.Add(subMsg);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// A simple non-hub data message. It holds only one Data property.
|
||
|
/// </summary>
|
||
|
public sealed class DataMessage : IServerMessage
|
||
|
{
|
||
|
MessageTypes IServerMessage.Type { get { return MessageTypes.Data; } }
|
||
|
|
||
|
public object Data { get; private set; }
|
||
|
|
||
|
void IServerMessage.Parse(object data)
|
||
|
{
|
||
|
this.Data = data;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// A Hub message that orders the client to call a method.
|
||
|
/// </summary>
|
||
|
public sealed class MethodCallMessage : IServerMessage
|
||
|
{
|
||
|
MessageTypes IServerMessage.Type { get { return MessageTypes.MethodCall; } }
|
||
|
|
||
|
/// <summary>
|
||
|
/// The name of the Hub that the method is called on.
|
||
|
/// </summary>
|
||
|
public string Hub { get; private set; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// Name of the Method.
|
||
|
/// </summary>
|
||
|
public string Method { get; private set; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// Arguments of the method call.
|
||
|
/// </summary>
|
||
|
public object[] Arguments { get; private set; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// State changes of the hub. It's handled automatically by the Hub.
|
||
|
/// </summary>
|
||
|
#if BESTHTTP_SIGNALR_WITH_JSONDOTNET
|
||
|
public IDictionary<string, JToken> State { get; private set; }
|
||
|
#else
|
||
|
public IDictionary<string, object> State { get; private set; }
|
||
|
#endif
|
||
|
|
||
|
void IServerMessage.Parse(object data)
|
||
|
{
|
||
|
#if BESTHTTP_SIGNALR_WITH_JSONDOTNET
|
||
|
IDictionary<string, JToken> dic = data as IDictionary<string, JToken>;
|
||
|
#else
|
||
|
IDictionary<string, object> dic = data as IDictionary<string, object>;
|
||
|
#endif
|
||
|
|
||
|
Hub = dic["H"].ToString();
|
||
|
Method = dic["M"].ToString();
|
||
|
|
||
|
List<object> args = new List<object>();
|
||
|
foreach (object arg in dic["A"] as IEnumerable)
|
||
|
args.Add(arg);
|
||
|
Arguments = args.ToArray();
|
||
|
|
||
|
#if BESTHTTP_SIGNALR_WITH_JSONDOTNET
|
||
|
JToken value;
|
||
|
if (dic.TryGetValue("S", out value))
|
||
|
State = value as IDictionary<string, JToken>;
|
||
|
#else
|
||
|
object value;
|
||
|
if (dic.TryGetValue("S", out value))
|
||
|
State = value as IDictionary<string, object>;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Message of a server side method invocation result.
|
||
|
/// </summary>
|
||
|
public sealed class ResultMessage : IServerMessage, IHubMessage
|
||
|
{
|
||
|
MessageTypes IServerMessage.Type { get { return MessageTypes.Result; } }
|
||
|
|
||
|
/// <summary>
|
||
|
/// The unique id that the client set when called the server side method. Used by the plugin to deliver this message to the good Hub.
|
||
|
/// </summary>
|
||
|
public UInt64 InvocationId { get; private set; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// The return value of the server side method call, or null if the method's return type is void.
|
||
|
/// </summary>
|
||
|
public object ReturnValue { get; private set; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// State changes of the hub. It's handled automatically by the Hub.
|
||
|
/// </summary>
|
||
|
#if BESTHTTP_SIGNALR_WITH_JSONDOTNET
|
||
|
public IDictionary<string, JToken> State { get; private set; }
|
||
|
#else
|
||
|
public IDictionary<string, object> State { get; private set; }
|
||
|
#endif
|
||
|
|
||
|
void IServerMessage.Parse(object data)
|
||
|
{
|
||
|
IDictionary<string, object> dic = data as IDictionary<string, object>;
|
||
|
|
||
|
InvocationId = UInt64.Parse(dic["I"].ToString());
|
||
|
|
||
|
object value;
|
||
|
if (dic.TryGetValue("R", out value))
|
||
|
ReturnValue = value;
|
||
|
|
||
|
if (dic.TryGetValue("S", out value))
|
||
|
{
|
||
|
#if BESTHTTP_SIGNALR_WITH_JSONDOTNET
|
||
|
State = value as IDictionary<string, JToken>;
|
||
|
#else
|
||
|
State = value as IDictionary<string, object>;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public sealed class FailureMessage : IServerMessage, IHubMessage
|
||
|
{
|
||
|
MessageTypes IServerMessage.Type { get { return MessageTypes.Failure; } }
|
||
|
|
||
|
/// <summary>
|
||
|
/// The unique id that the client set when called the server side method. Used by the plugin to deliver this message to the good Hub.
|
||
|
/// </summary>
|
||
|
public UInt64 InvocationId { get; private set; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// True if it's a hub error.
|
||
|
/// </summary>
|
||
|
public bool IsHubError { get; private set; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// If the method call failed, it contains the error message to detail what happened.
|
||
|
/// </summary>
|
||
|
public string ErrorMessage { get; private set; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// A dictionary that may contain additional error data (can only be present for hub errors). It can be null.
|
||
|
/// </summary>
|
||
|
#if BESTHTTP_SIGNALR_WITH_JSONDOTNET
|
||
|
public IDictionary<string, JToken> AdditionalData { get; private set; }
|
||
|
#else
|
||
|
public IDictionary<string, object> AdditionalData { get; private set; }
|
||
|
#endif
|
||
|
|
||
|
/// <summary>
|
||
|
/// Stack trace of the error. It present only if detailed error reporting is turned on on the server (https://msdn.microsoft.com/en-us/library/microsoft.aspnet.signalr.hubconfiguration.enabledetailederrors%28v=vs.118%29.aspx).
|
||
|
/// </summary>
|
||
|
public string StackTrace { get; private set; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// State changes of the hub. It's handled automatically by the Hub.
|
||
|
/// </summary>
|
||
|
#if BESTHTTP_SIGNALR_WITH_JSONDOTNET
|
||
|
public IDictionary<string, JToken> State { get; private set; }
|
||
|
#else
|
||
|
public IDictionary<string, object> State { get; private set; }
|
||
|
#endif
|
||
|
|
||
|
void IServerMessage.Parse(object data)
|
||
|
{
|
||
|
IDictionary<string, object> dic = data as IDictionary<string, object>;
|
||
|
|
||
|
InvocationId = UInt64.Parse(dic["I"].ToString());
|
||
|
|
||
|
object value;
|
||
|
|
||
|
if (dic.TryGetValue("E", out value))
|
||
|
ErrorMessage = value.ToString();
|
||
|
|
||
|
if (dic.TryGetValue("H", out value))
|
||
|
IsHubError = int.Parse(value.ToString()) == 1 ? true : false;
|
||
|
|
||
|
if (dic.TryGetValue("D", out value))
|
||
|
{
|
||
|
#if BESTHTTP_SIGNALR_WITH_JSONDOTNET
|
||
|
AdditionalData = value as IDictionary<string, JToken>;
|
||
|
#else
|
||
|
AdditionalData = value as IDictionary<string, object>;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
if (dic.TryGetValue("T", out value))
|
||
|
StackTrace = value.ToString();
|
||
|
|
||
|
if (dic.TryGetValue("S", out value))
|
||
|
{
|
||
|
#if BESTHTTP_SIGNALR_WITH_JSONDOTNET
|
||
|
State = value as IDictionary<string, JToken>;
|
||
|
#else
|
||
|
State = value as IDictionary<string, object>;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// When a server method is a long running method the server can send the information about the progress of execution of the method to the client.
|
||
|
/// </summary>
|
||
|
public sealed class ProgressMessage : IServerMessage, IHubMessage
|
||
|
{
|
||
|
MessageTypes IServerMessage.Type { get { return MessageTypes.Progress; } }
|
||
|
|
||
|
/// <summary>
|
||
|
/// The unique id that the client set when called the server side method. Used by the plugin to deliver this message to the good Hub.
|
||
|
/// </summary>
|
||
|
public UInt64 InvocationId { get; private set; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// Current progress of the long running method.
|
||
|
/// </summary>
|
||
|
public double Progress { get; private set; }
|
||
|
|
||
|
void IServerMessage.Parse(object data)
|
||
|
{
|
||
|
#if BESTHTTP_SIGNALR_WITH_JSONDOTNET
|
||
|
IDictionary<string, JToken> dic = data as IDictionary<string, JToken>;
|
||
|
#else
|
||
|
IDictionary<string, object> dic = data as IDictionary<string, object>;
|
||
|
#endif
|
||
|
|
||
|
#if BESTHTTP_SIGNALR_WITH_JSONDOTNET
|
||
|
IDictionary<string, JToken> P = dic["P"] as IDictionary<string, JToken>;
|
||
|
#else
|
||
|
IDictionary<string, object> P = dic["P"] as IDictionary<string, object>;
|
||
|
#endif
|
||
|
|
||
|
InvocationId = UInt64.Parse(P["I"].ToString());
|
||
|
Progress = double.Parse(P["D"].ToString());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|