Added NightAlert project for travel kit

This commit is contained in:
2021-06-10 14:39:06 -04:00
commit d38d9e3b7e
308 changed files with 35922 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
using System;
namespace Quobject.EngineIoClientDotNet.Client
{
public class EngineIOException : Exception
{
public string Transport;
public object code;
public EngineIOException(string message)
: base(message)
{
}
public EngineIOException(Exception cause)
: base("", cause)
{
}
public EngineIOException(string message, Exception cause)
: base(message, cause)
{
}
}
}

View File

@@ -0,0 +1,33 @@
using Newtonsoft.Json.Linq;
using System.Collections.Immutable;
namespace Quobject.EngineIoClientDotNet.Client
{
public class HandshakeData
{
public string Sid;
public ImmutableList<string> Upgrades = ImmutableList<string>.Empty;
public long PingInterval;
public long PingTimeout;
public HandshakeData(string data)
: this(JObject.Parse(data))
{
}
public HandshakeData(JObject data)
{
var upgrades = data.GetValue("upgrades");
foreach (var e in upgrades)
{
Upgrades = Upgrades.Add(e.ToString());
}
Sid = data.GetValue("sid").Value<string>();
PingInterval = data.GetValue("pingInterval").Value<long>();
PingTimeout = data.GetValue("pingTimeout").Value<long>();
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
namespace Quobject.EngineIoClientDotNet.Client
{
public class HandshakeData
{
public string Sid;
public List<string> Upgrades = new List<string>();
public long PingInterval;
public long PingTimeout;
public HandshakeData(string data)
: this(JObject.Parse(data))
{
}
public HandshakeData(JObject data)
{
var upgrades = data.GetValue("upgrades");
foreach (var e in upgrades)
{
Upgrades.Add(e.ToString());
}
Sid = data.GetValue("sid").Value<string>();
PingInterval = data.GetValue("pingInterval").Value<long>();
PingTimeout = data.GetValue("pingTimeout").Value<long>();
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,212 @@

using System.Text;
using System.Collections.Immutable;
using Quobject.EngineIoClientDotNet.ComponentEmitter;
using Quobject.EngineIoClientDotNet.Modules;
using Quobject.EngineIoClientDotNet.Parser;
using System;
using System.Collections.Generic;
namespace Quobject.EngineIoClientDotNet.Client
{
public abstract class Transport : Emitter
{
protected enum ReadyStateEnum
{
OPENING,
OPEN,
CLOSED,
PAUSED
}
public static readonly string EVENT_OPEN = "open";
public static readonly string EVENT_CLOSE = "close";
public static readonly string EVENT_PACKET = "packet";
public static readonly string EVENT_DRAIN = "drain";
public static readonly string EVENT_ERROR = "error";
public static readonly string EVENT_SUCCESS = "success";
public static readonly string EVENT_DATA = "data";
public static readonly string EVENT_REQUEST_HEADERS = "requestHeaders";
public static readonly string EVENT_RESPONSE_HEADERS = "responseHeaders";
protected static int Timestamps = 0;
private bool _writeable ;
public bool Writable {
get { return _writeable; }
set
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info(string.Format("Writable: {0} sid={1}", value, this.Socket.Id));
_writeable = value;
}
}
private int myVar;
public int MyProperty
{
get { return myVar; }
set { myVar = value; }
}
public string Name;
public Dictionary<string, string> Query;
protected bool Secure;
protected bool TimestampRequests;
protected int Port;
protected string Path;
protected string Hostname;
protected string TimestampParam;
protected Socket Socket;
protected bool Agent = false;
protected bool ForceBase64 = false;
protected bool ForceJsonp = false;
protected string Cookie;
protected Dictionary<string, string> ExtraHeaders;
protected ReadyStateEnum ReadyState = ReadyStateEnum.CLOSED;
protected Transport(Options options)
{
this.Path = options.Path;
this.Hostname = options.Hostname;
this.Port = options.Port;
this.Secure = options.Secure;
this.Query = options.Query;
this.TimestampParam = options.TimestampParam;
this.TimestampRequests = options.TimestampRequests;
this.Socket = options.Socket;
this.Agent = options.Agent;
this.ForceBase64 = options.ForceBase64;
this.ForceJsonp = options.ForceJsonp;
this.Cookie = options.GetCookiesAsString();
this.ExtraHeaders = options.ExtraHeaders;
}
protected Transport OnError(string message, Exception exception)
{
Exception err = new EngineIOException(message, exception);
this.Emit(EVENT_ERROR, err);
return this;
}
protected void OnOpen()
{
ReadyState = ReadyStateEnum.OPEN;
Writable = true;
Emit(EVENT_OPEN);
}
protected void OnClose()
{
ReadyState = ReadyStateEnum.CLOSED;
Emit(EVENT_CLOSE);
}
protected virtual void OnData(string data)
{
this.OnPacket(Parser.Parser.DecodePacket(data));
}
protected virtual void OnData(byte[] data)
{
this.OnPacket(Parser.Parser.DecodePacket(data));
}
protected void OnPacket(Packet packet)
{
this.Emit(EVENT_PACKET, packet);
}
public Transport Open()
{
if (ReadyState == ReadyStateEnum.CLOSED)
{
ReadyState = ReadyStateEnum.OPENING;
DoOpen();
}
return this;
}
public Transport Close()
{
if (ReadyState == ReadyStateEnum.OPENING || ReadyState == ReadyStateEnum.OPEN)
{
DoClose();
OnClose();
}
return this;
}
public Transport Send(ImmutableList<Packet> packets)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("Send called with packets.Count: " + packets.Count);
var count = packets.Count;
if (ReadyState == ReadyStateEnum.OPEN)
{
//PollTasks.Exec((n) =>
//{
Write(packets);
//});
}
else
{
throw new EngineIOException("Transport not open");
//log.Info("Transport not open");
}
return this;
}
protected abstract void DoOpen();
protected abstract void DoClose();
protected abstract void Write(ImmutableList<Packet> packets);
public class Options
{
public bool Agent = false;
public bool ForceBase64 = false;
public bool ForceJsonp = false;
public string Hostname;
public string Path;
public string TimestampParam;
public bool Secure = false;
public bool TimestampRequests = true;
public int Port;
public int PolicyPort;
public Dictionary<string, string> Query;
public bool IgnoreServerCertificateValidation = false;
internal Socket Socket;
public Dictionary<string, string> Cookies = new Dictionary<string, string>();
public Dictionary<string, string> ExtraHeaders = new Dictionary<string, string>();
public string GetCookiesAsString()
{
var result = new StringBuilder();
var first = true;
foreach (var item in Cookies)
{
if (!first)
{
result.Append("; ");
}
result.Append(string.Format("{0}={1}", item.Key, item.Value));
first = false;
}
return result.ToString();
}
}
}
}

View File

@@ -0,0 +1,209 @@

using System.Collections.Concurrent;
using System.Text;
using Quobject.EngineIoClientDotNet.ComponentEmitter;
using Quobject.EngineIoClientDotNet.Modules;
using Quobject.EngineIoClientDotNet.Parser;
using System;
using System.Collections.Generic;
namespace Quobject.EngineIoClientDotNet.Client
{
public abstract class Transport : Emitter
{
protected enum ReadyStateEnum
{
OPENING,
OPEN,
CLOSED,
PAUSED
}
public static readonly string EVENT_OPEN = "open";
public static readonly string EVENT_CLOSE = "close";
public static readonly string EVENT_PACKET = "packet";
public static readonly string EVENT_DRAIN = "drain";
public static readonly string EVENT_ERROR = "error";
public static readonly string EVENT_SUCCESS = "success";
public static readonly string EVENT_DATA = "data";
public static readonly string EVENT_REQUEST_HEADERS = "requestHeaders";
public static readonly string EVENT_RESPONSE_HEADERS = "responseHeaders";
protected static int Timestamps = 0;
private bool _writeable ;
public bool Writable {
get { return _writeable; }
set
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info(string.Format("Writable: {0} sid={1}", value, this.Socket.Id));
_writeable = value;
}
}
private int myVar;
public int MyProperty
{
get { return myVar; }
set { myVar = value; }
}
public string Name;
public Dictionary<string, string> Query;
protected bool Secure;
protected bool TimestampRequests;
protected int Port;
protected string Path;
protected string Hostname;
protected string TimestampParam;
protected Socket Socket;
protected bool Agent = false;
protected bool ForceBase64 = false;
protected bool ForceJsonp = false;
protected string Cookie;
protected ReadyStateEnum ReadyState = ReadyStateEnum.CLOSED;
protected Transport(Options options)
{
this.Path = options.Path;
this.Hostname = options.Hostname;
this.Port = options.Port;
this.Secure = options.Secure;
this.Query = options.Query;
this.TimestampParam = options.TimestampParam;
this.TimestampRequests = options.TimestampRequests;
this.Socket = options.Socket;
this.Agent = options.Agent;
this.ForceBase64 = options.ForceBase64;
this.ForceJsonp = options.ForceJsonp;
this.Cookie = options.GetCookiesAsString();
}
protected Transport OnError(string message, Exception exception)
{
Exception err = new EngineIOException(message, exception);
this.Emit(EVENT_ERROR, err);
return this;
}
protected void OnOpen()
{
ReadyState = ReadyStateEnum.OPEN;
Writable = true;
Emit(EVENT_OPEN);
}
protected void OnClose()
{
ReadyState = ReadyStateEnum.CLOSED;
Emit(EVENT_CLOSE);
}
protected virtual void OnData(string data)
{
this.OnPacket(Parser.Parser.DecodePacket(data));
}
protected virtual void OnData(byte[] data)
{
this.OnPacket(Parser.Parser.DecodePacket(data));
}
protected void OnPacket(Packet packet)
{
this.Emit(EVENT_PACKET, packet);
}
public Transport Open()
{
if (ReadyState == ReadyStateEnum.CLOSED)
{
ReadyState = ReadyStateEnum.OPENING;
DoOpen();
}
return this;
}
public Transport Close()
{
if (ReadyState == ReadyStateEnum.OPENING || ReadyState == ReadyStateEnum.OPEN)
{
DoClose();
OnClose();
}
return this;
}
public Transport Send(List<Packet> packets)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("Send called with packets.Count: " + packets.Count);
var count = packets.Count;
if (ReadyState == ReadyStateEnum.OPEN)
{
//PollTasks.Exec((n) =>
//{
Write(packets);
//});
}
else
{
throw new EngineIOException("Transport not open");
//log.Info("Transport not open");
}
return this;
}
protected abstract void DoOpen();
protected abstract void DoClose();
protected abstract void Write(List<Packet> packets);
public class Options
{
public bool Agent = false;
public bool ForceBase64 = false;
public bool ForceJsonp = false;
public string Hostname;
public string Path;
public string TimestampParam;
public bool Secure = false;
public bool TimestampRequests = true;
public int Port;
public int PolicyPort;
public Dictionary<string, string> Query;
public bool IgnoreServerCertificateValidation = false;
internal Socket Socket;
public Dictionary<string, string> Cookies = new Dictionary<string, string>();
public string GetCookiesAsString()
{
var result = new StringBuilder();
var first = true;
foreach (var item in Cookies)
{
if (!first)
{
result.Append("; ");
}
result.Append(string.Format("{0}={1}", item.Key, item.Value));
first = false;
}
return result.ToString();
}
}
}
}

View File

@@ -0,0 +1,380 @@

using System.Collections.Immutable;
using Quobject.EngineIoClientDotNet.ComponentEmitter;
using Quobject.EngineIoClientDotNet.Modules;
using Quobject.EngineIoClientDotNet.Parser;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Quobject.EngineIoClientDotNet.Client.Transports
{
public class Polling : Transport
{
public static readonly string NAME = "polling";
public static readonly string EVENT_POLL = "poll";
public static readonly string EVENT_POLL_COMPLETE = "pollComplete";
private bool IsPolling = false;
public Polling(Options opts) : base(opts)
{
Name = NAME;
}
private bool FirstTimePoll = true;
private bool OnDataReceived = false;
protected override void DoOpen()
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("DoOpen: Entry");
do
{
if (FirstTimePoll)
{
log.Info("DoOpen: Initial Poll - ReadyState=" + ReadyState.ToString());
FirstTimePoll = false;
Poll();
IsPolling = false;
Emit(EVENT_POLL_COMPLETE);
}
else if (OnDataReceived && ReadyState == ReadyStateEnum.OPEN)
{
log.Info("DoOpen: General Poll - ReadyState=" + ReadyState.ToString());
OnDataReceived = false;// Don't poll again, unless signaled by _onData
Poll();
IsPolling = false;
Emit(EVENT_POLL_COMPLETE);
}
else
{
log.Info(string.Format("DoOpen: ignoring poll - transport state {0}", ReadyState));
}
System.Threading.Thread.Sleep(100);
}
while (ReadyState != ReadyStateEnum.CLOSED);
}
public void Pause(Action onPause)
{
//var log = LogManager.GetLogger(Global.CallerName());
ReadyState = ReadyStateEnum.PAUSED;
Action pause = () =>
{
//log.Info("paused");
ReadyState = ReadyStateEnum.PAUSED;
onPause();
};
if (IsPolling || !Writable)
{
var total = new[] {0};
if (IsPolling)
{
//log.Info("we are currently polling - waiting to pause");
total[0]++;
Once(EVENT_POLL_COMPLETE, new PauseEventPollCompleteListener(total, pause));
}
if (!Writable)
{
//log.Info("we are currently writing - waiting to pause");
total[0]++;
Once(EVENT_DRAIN, new PauseEventDrainListener(total, pause));
}
}
else
{
pause();
}
}
public void Resume()
{
if (ReadyState == ReadyStateEnum.PAUSED)
ReadyState = ReadyStateEnum.OPEN;
}
private class PauseEventDrainListener : IListener
{
private int[] total;
private Action pause;
public PauseEventDrainListener(int[] total, Action pause)
{
this.total = total;
this.pause = pause;
}
public void Call(params object[] args)
{
//var log = LogManager.GetLogger(Global.CallerName());
//log.Info("pre-pause writing complete");
if (--total[0] == 0)
{
pause();
}
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
class PauseEventPollCompleteListener : IListener
{
private int[] total;
private Action pause;
public PauseEventPollCompleteListener(int[] total, Action pause)
{
this.total = total;
this.pause = pause;
}
public void Call(params object[] args)
{
//var log = LogManager.GetLogger(Global.CallerName());
//log.Info("pre-pause polling complete");
if (--total[0] == 0)
{
pause();
}
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
private void Poll()
{
//var log = LogManager.GetLogger(Global.CallerName());
//log.Info("polling");
IsPolling = true;
DoPoll();
Emit(EVENT_POLL);
}
protected override void OnData(string data)
{
_onData(data);
}
protected override void OnData(byte[] data)
{
_onData(data);
}
private class DecodePayloadCallback : IDecodePayloadCallback
{
private Polling polling;
public DecodePayloadCallback(Polling polling)
{
this.polling = polling;
}
public bool Call(Packet packet, int index, int total)
{
if (polling.ReadyState == ReadyStateEnum.OPENING)
{
polling.OnOpen();
}
if (packet.Type == Packet.CLOSE)
{
polling.OnClose();
return false;
}
polling.OnPacket(packet);
return true;
}
}
private void _onData(object data)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info(string.Format("polling got data {0}",data));
var callback = new DecodePayloadCallback(this);
if (data is string)
{
Parser.Parser.DecodePayload((string)data, callback);
}
else if (data is byte[])
{
Parser.Parser.DecodePayload((byte[])data, callback);
}
// Signal that data was received
OnDataReceived = true;
}
private class CloseListener : IListener
{
private Polling polling;
public CloseListener(Polling polling)
{
this.polling = polling;
}
public void Call(params object[] args)
{
//var log = LogManager.GetLogger(Global.CallerName());
//log.Info("writing close packet");
ImmutableList<Packet> packets = ImmutableList<Packet>.Empty;
packets = packets.Add(new Packet(Packet.CLOSE));
polling.Write(packets);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
protected override void DoClose()
{
var log = LogManager.GetLogger(Global.CallerName());
var closeListener = new CloseListener(this);
if (ReadyState == ReadyStateEnum.OPEN)
{
log.Info("transport open - closing");
closeListener.Call();
}
else
{
// in case we're trying to close while
// handshaking is in progress (engine.io-client GH-164)
log.Info("transport not open - deferring close");
this.Once(EVENT_OPEN, closeListener);
}
}
public class SendEncodeCallback : IEncodeCallback
{
private Polling polling;
public SendEncodeCallback(Polling polling)
{
this.polling = polling;
}
public void Call(object data)
{
//var log = LogManager.GetLogger(Global.CallerName());
//log.Info("SendEncodeCallback data = " + data);
var byteData = (byte[]) data;
polling.DoWrite(byteData, () =>
{
polling.Writable = true;
polling.Emit(EVENT_DRAIN);
});
}
}
protected override void Write(ImmutableList<Packet> packets)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("Write packets.Count = " + packets.Count);
Writable = false;
var callback = new SendEncodeCallback(this);
Parser.Parser.EncodePayload(packets.ToArray(), callback);
}
public string Uri()
{
//var query = this.Query;
var query = new Dictionary<string, string>(Query);
//if (Query == null)
//{
// query = new Dictionary<string, string>();
//}
string schema = this.Secure ? "https" : "http";
string portString = "";
if (this.TimestampRequests)
{
query.Add(this.TimestampParam, DateTime.Now.Ticks + "-" + Transport.Timestamps++);
}
query.Add("b64", "1");
string _query = ParseQS.Encode(query);
if (this.Port > 0 && (("https" == schema && this.Port != 443)
|| ("http" == schema && this.Port != 80)))
{
portString = ":" + this.Port;
}
if (_query.Length > 0)
{
_query = "?" + _query;
}
return schema + "://" + this.Hostname + portString + this.Path + _query;
}
protected virtual void DoWrite(byte[] data, Action action)
{
}
protected virtual void DoPoll()
{
}
}
}

View File

@@ -0,0 +1,434 @@

using Quobject.EngineIoClientDotNet.ComponentEmitter;
using Quobject.EngineIoClientDotNet.Modules;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Threading.Tasks;
namespace Quobject.EngineIoClientDotNet.Client.Transports
{
public class PollingXHR : Polling
{
private XHRRequest sendXhr;
public PollingXHR(Options options) : base(options)
{
}
protected XHRRequest Request()
{
return Request(null);
}
protected XHRRequest Request(XHRRequest.RequestOptions opts)
{
if (opts == null)
{
opts = new XHRRequest.RequestOptions();
}
opts.Uri = Uri();
opts.ExtraHeaders = this.ExtraHeaders;
XHRRequest req = new XHRRequest(opts);
req.On(EVENT_REQUEST_HEADERS, new EventRequestHeadersListener(this)).
On(EVENT_RESPONSE_HEADERS, new EventResponseHeadersListener(this));
return req;
}
class EventRequestHeadersListener : IListener
{
private PollingXHR pollingXHR;
public EventRequestHeadersListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
// Never execute asynchronously for support to modify headers.
pollingXHR.Emit(EVENT_REQUEST_HEADERS, args[0]);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
class EventResponseHeadersListener : IListener
{
private PollingXHR pollingXHR;
public EventResponseHeadersListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
pollingXHR.Emit(EVENT_RESPONSE_HEADERS, args[0]);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
protected override void DoWrite(byte[] data, Action action)
{
var opts = new XHRRequest.RequestOptions {Method = "POST", Data = data, CookieHeaderValue = Cookie};
var log = LogManager.GetLogger(Global.CallerName());
log.Info("DoWrite data = " + data);
Console.WriteLine("DoWrite data = " + data);
//try
//{
// var dataString = BitConverter.ToString(data);
// log.Info(string.Format("DoWrite data {0}", dataString));
//}
//catch (Exception e)
//{
// log.Error(e);
//}
sendXhr = Request(opts);
sendXhr.On(EVENT_SUCCESS, new SendEventSuccessListener(action));
sendXhr.On(EVENT_ERROR, new SendEventErrorListener(this));
sendXhr.Create();
}
class SendEventErrorListener : IListener
{
private PollingXHR pollingXHR;
public SendEventErrorListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
Exception err = args.Length > 0 && args[0] is Exception ? (Exception) args[0] : null;
pollingXHR.OnError("xhr post error", err);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
class SendEventSuccessListener : IListener
{
private Action action;
public SendEventSuccessListener(Action action)
{
this.action = action;
}
public void Call(params object[] args)
{
action();
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
protected override void DoPoll()
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("xhr DoPoll");
var opts = new XHRRequest.RequestOptions { CookieHeaderValue = Cookie };
sendXhr = Request(opts);
sendXhr.On(EVENT_DATA, new DoPollEventDataListener(this));
sendXhr.On(EVENT_ERROR, new DoPollEventErrorListener(this));
sendXhr.Create();
}
class DoPollEventDataListener : IListener
{
private PollingXHR pollingXHR;
public DoPollEventDataListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
object arg = args.Length > 0 ? args[0] : null;
if (arg is string)
{
pollingXHR.OnData((string)arg);
}
else if (arg is byte[])
{
pollingXHR.OnData((byte[])arg);
}
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
class DoPollEventErrorListener : IListener
{
private PollingXHR pollingXHR;
public DoPollEventErrorListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
Exception err = args.Length > 0 && args[0] is Exception ? (Exception)args[0] : null;
pollingXHR.OnError("xhr poll error", err);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
public class XHRRequest : Emitter
{
private string Method;
private string Uri;
private byte[] Data;
private string CookieHeaderValue;
private HttpWebRequest Xhr;
private Dictionary<string, string> ExtraHeaders;
public XHRRequest(RequestOptions options)
{
Method = options.Method ?? "GET";
Uri = options.Uri;
Data = options.Data;
CookieHeaderValue = options.CookieHeaderValue;
ExtraHeaders = options.ExtraHeaders;
}
public void Create()
{
var log = LogManager.GetLogger(Global.CallerName());
try
{
log.Info(string.Format("xhr open {0}: {1}", Method, Uri));
Xhr = (HttpWebRequest) WebRequest.Create(Uri);
Xhr.Method = Method;
if (CookieHeaderValue != null)
{
Xhr.Headers.Add("Cookie", CookieHeaderValue);
}
if (ExtraHeaders != null)
{
foreach (var header in ExtraHeaders)
{
Xhr.Headers.Add(header.Key, header.Value);
}
}
}
catch (Exception e)
{
log.Error(e);
OnError(e);
return;
}
if (Method == "POST")
{
Xhr.ContentType = "application/octet-stream";
}
try
{
if (Data != null)
{
Xhr.ContentLength = Data.Length;
using (var requestStream = Xhr.GetRequestStream())
{
requestStream.WriteAsync(Data, 0, Data.Length).Wait();
}
}
Task.Run(() =>
{
var log2 = LogManager.GetLogger(Global.CallerName());
log2.Info("Task.Run Create start");
using (var res = Xhr.GetResponse())
{
log.Info("Xhr.GetResponse ");
var responseHeaders = new Dictionary<string, string>();
for (int i = 0; i < res.Headers.Count; i++)
{
responseHeaders.Add(res.Headers.Keys[i], res.Headers[i]);
}
OnResponseHeaders(responseHeaders);
var contentType = res.Headers["Content-Type"];
using (var resStream = res.GetResponseStream())
{
Debug.Assert(resStream != null, "resStream != null");
if (contentType.Equals("application/octet-stream",
StringComparison.OrdinalIgnoreCase))
{
var buffer = new byte[16 * 1024];
using (var ms = new MemoryStream())
{
int read;
while ((read = resStream.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
var a = ms.ToArray();
OnData(a);
}
}
else
{
using (var sr = new StreamReader(resStream))
{
OnData(sr.ReadToEnd());
}
}
}
}
log2.Info("Task.Run Create finish");
}).Wait();
}
catch (System.IO.IOException e)
{
log.Error("Create call failed", e);
OnError(e);
}
catch (System.Net.WebException e)
{
log.Error("Create call failed", e);
OnError(e);
}
catch (Exception e)
{
log.Error("Create call failed", e);
OnError(e);
}
}
private void OnSuccess()
{
this.Emit(EVENT_SUCCESS);
}
private void OnData(string data)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("OnData string = " + data);
this.Emit(EVENT_DATA, data);
this.OnSuccess();
}
private void OnData(byte[] data)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("OnData byte[] =" + System.Text.UTF8Encoding.UTF8.GetString(data));
this.Emit(EVENT_DATA, data);
this.OnSuccess();
}
private void OnError(Exception err)
{
this.Emit(EVENT_ERROR, err);
}
private void OnRequestHeaders(Dictionary<string, string> headers)
{
this.Emit(EVENT_REQUEST_HEADERS, headers);
}
private void OnResponseHeaders(Dictionary<string, string> headers)
{
this.Emit(EVENT_RESPONSE_HEADERS, headers);
}
public class RequestOptions
{
public string Uri;
public string Method;
public byte[] Data;
public string CookieHeaderValue;
public Dictionary<string, string> ExtraHeaders;
}
}
}
}

View File

@@ -0,0 +1,428 @@

using Quobject.EngineIoClientDotNet.ComponentEmitter;
using Quobject.EngineIoClientDotNet.Modules;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Threading.Tasks;
namespace Quobject.EngineIoClientDotNet.Client.Transports
{
public class PollingXHR : Polling
{
private XHRRequest sendXhr;
public PollingXHR(Options options) : base(options)
{
}
protected XHRRequest Request()
{
return Request(null);
}
protected XHRRequest Request(XHRRequest.RequestOptions opts)
{
if (opts == null)
{
opts = new XHRRequest.RequestOptions();
}
opts.Uri = Uri();
XHRRequest req = new XHRRequest(opts);
req.On(EVENT_REQUEST_HEADERS, new EventRequestHeadersListener(this)).
On(EVENT_RESPONSE_HEADERS, new EventResponseHeadersListener(this));
return req;
}
class EventRequestHeadersListener : IListener
{
private PollingXHR pollingXHR;
public EventRequestHeadersListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
// Never execute asynchronously for support to modify headers.
pollingXHR.Emit(EVENT_RESPONSE_HEADERS, args[0]);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
class EventResponseHeadersListener : IListener
{
private PollingXHR pollingXHR;
public EventResponseHeadersListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
pollingXHR.Emit(EVENT_REQUEST_HEADERS, args[0]);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
protected override void DoWrite(byte[] data, Action action)
{
var opts = new XHRRequest.RequestOptions { Method = "POST", Data = data, CookieHeaderValue = Cookie };
var log = LogManager.GetLogger(Global.CallerName());
log.Info("DoWrite data = " + data);
//try
//{
// var dataString = BitConverter.ToString(data);
// log.Info(string.Format("DoWrite data {0}", dataString));
//}
//catch (Exception e)
//{
// log.Error(e);
//}
sendXhr = Request(opts);
sendXhr.On(EVENT_SUCCESS, new SendEventSuccessListener(action));
sendXhr.On(EVENT_ERROR, new SendEventErrorListener(this));
sendXhr.Create();
}
class SendEventErrorListener : IListener
{
private PollingXHR pollingXHR;
public SendEventErrorListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
Exception err = args.Length > 0 && args[0] is Exception ? (Exception) args[0] : null;
pollingXHR.OnError("xhr post error", err);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
class SendEventSuccessListener : IListener
{
private Action action;
public SendEventSuccessListener(Action action)
{
this.action = action;
}
public void Call(params object[] args)
{
action();
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
protected override void DoPoll()
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("xhr DoPoll");
var opts = new XHRRequest.RequestOptions { CookieHeaderValue = Cookie };
sendXhr = Request(opts);
sendXhr.On(EVENT_DATA, new DoPollEventDataListener(this));
sendXhr.On(EVENT_ERROR, new DoPollEventErrorListener(this));
sendXhr.Create();
}
class DoPollEventDataListener : IListener
{
private PollingXHR pollingXHR;
public DoPollEventDataListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
object arg = args.Length > 0 ? args[0] : null;
if (arg is string)
{
pollingXHR.OnData((string)arg);
}
else if (arg is byte[])
{
pollingXHR.OnData((byte[])arg);
}
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
class DoPollEventErrorListener : IListener
{
private PollingXHR pollingXHR;
public DoPollEventErrorListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
Exception err = args.Length > 0 && args[0] is Exception ? (Exception)args[0] : null;
pollingXHR.OnError("xhr poll error", err);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
public class XHRRequest : Emitter
{
private string Method;
private string Uri;
private byte[] Data;
private string CookieHeaderValue;
private HttpWebRequest Xhr;
public XHRRequest(RequestOptions options)
{
Method = options.Method ?? "GET";
Uri = options.Uri;
Data = options.Data;
CookieHeaderValue = options.CookieHeaderValue;
}
public void Create()
{
var log = LogManager.GetLogger(Global.CallerName());
try
{
log.Info(string.Format("xhr open {0}: {1}", Method, Uri));
Xhr = (HttpWebRequest) WebRequest.Create(Uri);
Xhr.Method = Method;
if (CookieHeaderValue != null)
{
Xhr.Headers.Add("Cookie", CookieHeaderValue);
log.Info("added header " + CookieHeaderValue);
}
else
{
log.Info("not added header " + CookieHeaderValue);
}
}
catch (Exception e)
{
log.Error(e);
OnError(e);
return;
}
if (Method == "POST")
{
Xhr.ContentType = "application/octet-stream";
}
try
{
if (Data != null)
{
Xhr.ContentLength = Data.Length;
using (var requestStream = Xhr.GetRequestStream())
{
requestStream.Write(Data, 0, Data.Length);
}
}
Task.Run(() =>
{
var log2 = LogManager.GetLogger(Global.CallerName());
log2.Info("Task.Run Create start");
using (var res = Xhr.GetResponse())
{
log.Info("Xhr.GetResponse ");
var responseHeaders = new Dictionary<string, string>();
for (int i = 0; i < res.Headers.Count; i++)
{
responseHeaders.Add(res.Headers.Keys[i], res.Headers[i]);
}
OnResponseHeaders(responseHeaders);
var contentType = res.Headers["Content-Type"];
using (var resStream = res.GetResponseStream())
{
Debug.Assert(resStream != null, "resStream != null");
if (contentType.Equals("application/octet-stream",
StringComparison.OrdinalIgnoreCase))
{
var buffer = new byte[16 * 1024];
using (var ms = new MemoryStream())
{
int read;
while ((read = resStream.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
var a = ms.ToArray();
OnData(a);
}
}
else
{
using (var sr = new StreamReader(resStream))
{
OnData(sr.ReadToEnd());
}
}
}
}
log2.Info("Task.Run Create finish");
}).Wait();
}
catch (System.IO.IOException e)
{
log.Error("Create call failed", e);
OnError(e);
}
catch (System.Net.WebException e)
{
log.Error("Create call failed", e);
OnError(e);
}
catch (Exception e)
{
log.Error("Create call failed", e);
OnError(e);
}
}
private void OnSuccess()
{
this.Emit(EVENT_SUCCESS);
}
private void OnData(string data)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("OnData string = " + data);
this.Emit(EVENT_DATA, data);
this.OnSuccess();
}
private void OnData(byte[] data)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("OnData byte[] =" + System.Text.UTF8Encoding.UTF8.GetString(data));
this.Emit(EVENT_DATA, data);
this.OnSuccess();
}
private void OnError(Exception err)
{
this.Emit(EVENT_ERROR, err);
}
private void OnRequestHeaders(Dictionary<string, string> headers)
{
this.Emit(EVENT_REQUEST_HEADERS, headers);
}
private void OnResponseHeaders(Dictionary<string, string> headers)
{
this.Emit(EVENT_RESPONSE_HEADERS, headers);
}
public class RequestOptions
{
public string Uri;
public string Method;
public byte[] Data;
public string CookieHeaderValue;
}
}
}
}

View File

@@ -0,0 +1,432 @@

using Quobject.EngineIoClientDotNet.ComponentEmitter;
using Quobject.EngineIoClientDotNet.Modules;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Quobject.EngineIoClientDotNet.Thread;
namespace Quobject.EngineIoClientDotNet.Client.Transports
{
public class PollingXHR : Polling
{
private XHRRequest sendXhr;
public PollingXHR(Options options) : base(options)
{
}
protected XHRRequest Request()
{
return Request(null);
}
protected XHRRequest Request(XHRRequest.RequestOptions opts)
{
if (opts == null)
{
opts = new XHRRequest.RequestOptions();
}
opts.Uri = Uri();
XHRRequest req = new XHRRequest(opts);
req.On(EVENT_REQUEST_HEADERS, new EventRequestHeadersListener(this)).
On(EVENT_RESPONSE_HEADERS, new EventResponseHeadersListener(this));
return req;
}
class EventRequestHeadersListener : IListener
{
private PollingXHR pollingXHR;
public EventRequestHeadersListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
// Never execute asynchronously for support to modify headers.
pollingXHR.Emit(EVENT_RESPONSE_HEADERS, args[0]);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
class EventResponseHeadersListener : IListener
{
private PollingXHR pollingXHR;
public EventResponseHeadersListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
pollingXHR.Emit(EVENT_REQUEST_HEADERS, args[0]);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
protected override void DoWrite(byte[] data, Action action)
{
var opts = new XHRRequest.RequestOptions { Method = "POST", Data = data, CookieHeaderValue = Cookie };
var log = LogManager.GetLogger(Global.CallerName());
log.Info("DoWrite data = " + data);
//try
//{
// var dataString = BitConverter.ToString(data);
// log.Info(string.Format("DoWrite data {0}", dataString));
//}
//catch (Exception e)
//{
// log.Error(e);
//}
sendXhr = Request(opts);
sendXhr.On(EVENT_SUCCESS, new SendEventSuccessListener(action));
sendXhr.On(EVENT_ERROR, new SendEventErrorListener(this));
sendXhr.Create();
}
class SendEventErrorListener : IListener
{
private PollingXHR pollingXHR;
public SendEventErrorListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
Exception err = args.Length > 0 && args[0] is Exception ? (Exception) args[0] : null;
pollingXHR.OnError("xhr post error", err);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
class SendEventSuccessListener : IListener
{
private Action action;
public SendEventSuccessListener(Action action)
{
this.action = action;
}
public void Call(params object[] args)
{
action();
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
protected override void DoPoll()
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("xhr DoPoll");
var opts = new XHRRequest.RequestOptions { CookieHeaderValue = Cookie };
sendXhr = Request(opts);
sendXhr.On(EVENT_DATA, new DoPollEventDataListener(this));
sendXhr.On(EVENT_ERROR, new DoPollEventErrorListener(this));
sendXhr.Create();
}
class DoPollEventDataListener : IListener
{
private PollingXHR pollingXHR;
public DoPollEventDataListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
object arg = args.Length > 0 ? args[0] : null;
if (arg is string)
{
pollingXHR.OnData((string)arg);
}
else if (arg is byte[])
{
pollingXHR.OnData((byte[])arg);
}
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
class DoPollEventErrorListener : IListener
{
private PollingXHR pollingXHR;
public DoPollEventErrorListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
Exception err = args.Length > 0 && args[0] is Exception ? (Exception)args[0] : null;
pollingXHR.OnError("xhr poll error", err);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
public class XHRRequest : Emitter
{
private string Method;
private string Uri;
private byte[] Data;
private string CookieHeaderValue;
private HttpWebRequest Xhr;
public XHRRequest(RequestOptions options)
{
Method = options.Method ?? "GET";
Uri = options.Uri;
Data = options.Data;
CookieHeaderValue = options.CookieHeaderValue;
}
public void Create()
{
var log = LogManager.GetLogger(Global.CallerName());
try
{
log.Info(string.Format("xhr open {0}: {1}", Method, Uri));
Xhr = (HttpWebRequest) WebRequest.Create(Uri);
Xhr.Method = Method;
Xhr.Timeout = 10*60*1000;
Xhr.ReadWriteTimeout = 10*60*1000;
if (CookieHeaderValue != null)
{
Xhr.Headers.Add("Cookie", CookieHeaderValue);
log.Info("added header " + CookieHeaderValue);
}
else
{
log.Info("not added header " + CookieHeaderValue);
}
}
catch (Exception e)
{
log.Error(e);
OnError(e);
return;
}
if (Method == "POST")
{
Xhr.ContentType = "application/octet-stream";
}
try
{
if (Data != null)
{
Xhr.ContentLength = Data.Length;
using (var requestStream = Xhr.GetRequestStream())
{
requestStream.Write(Data, 0, Data.Length);
}
}
EasyTimer.TaskRun(() =>
{
var log2 = LogManager.GetLogger(Global.CallerName());
log2.Info("Task.Run Create start");
using (var res = Xhr.GetResponse())
{
log.Info("Xhr.GetResponse ");
var responseHeaders = new Dictionary<string, string>();
for (int i = 0; i < res.Headers.Count; i++)
{
responseHeaders.Add(res.Headers.Keys[i], res.Headers[i]);
}
OnResponseHeaders(responseHeaders);
var contentType = res.Headers["Content-Type"];
using (var resStream = res.GetResponseStream())
{
Debug.Assert(resStream != null, "resStream != null");
if (contentType.Equals("application/octet-stream",
StringComparison.OrdinalIgnoreCase))
{
var buffer = new byte[16*1024];
using (var ms = new MemoryStream())
{
int read;
while ((read = resStream.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
var a = ms.ToArray();
OnData(a);
}
}
else
{
using (var sr = new StreamReader(resStream))
{
OnData(sr.ReadToEnd());
}
}
}
}
log2.Info("Task.Run Create finish");
});
}
catch (System.IO.IOException e)
{
log.Error("Create call failed", e);
OnError(e);
}
catch (System.Net.WebException e)
{
log.Error("Create call failed", e);
OnError(e);
}
catch (Exception e)
{
log.Error("Create call failed", e);
OnError(e);
}
}
private void OnSuccess()
{
this.Emit(EVENT_SUCCESS);
}
private void OnData(string data)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("OnData string = " + data);
this.Emit(EVENT_DATA, data);
this.OnSuccess();
}
private void OnData(byte[] data)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("OnData byte[] =" + System.Text.UTF8Encoding.UTF8.GetString(data));
this.Emit(EVENT_DATA, data);
this.OnSuccess();
}
private void OnError(Exception err)
{
this.Emit(EVENT_ERROR, err);
}
private void OnRequestHeaders(Dictionary<string, string> headers)
{
this.Emit(EVENT_REQUEST_HEADERS, headers);
}
private void OnResponseHeaders(Dictionary<string, string> headers)
{
this.Emit(EVENT_RESPONSE_HEADERS, headers);
}
public class RequestOptions
{
public string Uri;
public string Method;
public byte[] Data;
public string CookieHeaderValue;
}
}
}
}

View File

@@ -0,0 +1,387 @@
using Quobject.EngineIoClientDotNet.ComponentEmitter;
using Quobject.EngineIoClientDotNet.Modules;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using System.Text;
namespace Quobject.EngineIoClientDotNet.Client.Transports
{
public class PollingXHR : Polling
{
private XHRRequest sendXhr;
public PollingXHR(Options options)
: base(options)
{
}
protected XHRRequest Request()
{
return Request(null);
}
protected XHRRequest Request(XHRRequest.RequestOptions opts)
{
if (opts == null)
{
opts = new XHRRequest.RequestOptions();
}
opts.Uri = Uri();
var req = new XHRRequest(opts);
req.On(EVENT_REQUEST_HEADERS, new EventRequestHeadersListener(this)).
On(EVENT_RESPONSE_HEADERS, new EventResponseHeadersListener(this));
return req;
}
private class EventRequestHeadersListener : IListener
{
private PollingXHR pollingXHR;
public EventRequestHeadersListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
// Never execute asynchronously for support to modify headers.
pollingXHR.Emit(EVENT_RESPONSE_HEADERS, args[0]);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
private class EventResponseHeadersListener : IListener
{
private PollingXHR pollingXHR;
public EventResponseHeadersListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
pollingXHR.Emit(EVENT_REQUEST_HEADERS, args[0]);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
protected override void DoWrite(byte[] data, Action action)
{
var opts = new XHRRequest.RequestOptions { Method = "POST", Data = data, CookieHeaderValue = Cookie };
var log = LogManager.GetLogger(Global.CallerName());
log.Info("DoWrite data = " + data);
//try
//{
// var dataString = BitConverter.ToString(data);
// log.Info(string.Format("DoWrite data {0}", dataString));
//}
//catch (Exception e)
//{
// log.Error(e);
//}
sendXhr = Request(opts);
sendXhr.On(EVENT_SUCCESS, new SendEventSuccessListener(action));
sendXhr.On(EVENT_ERROR, new SendEventErrorListener(this));
sendXhr.Create();
}
private class SendEventErrorListener : IListener
{
private PollingXHR pollingXHR;
public SendEventErrorListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
var err = args.Length > 0 && args[0] is Exception ? (Exception)args[0] : null;
pollingXHR.OnError("xhr post error", err);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
private class SendEventSuccessListener : IListener
{
private Action action;
public SendEventSuccessListener(Action action)
{
this.action = action;
}
public void Call(params object[] args)
{
action?.Invoke();
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
protected override void DoPoll()
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("xhr poll");
var opts = new XHRRequest.RequestOptions { CookieHeaderValue = Cookie };
sendXhr = Request(opts);
sendXhr.On(EVENT_DATA, new DoPollEventDataListener(this));
sendXhr.On(EVENT_ERROR, new DoPollEventErrorListener(this));
//sendXhr.Create();
sendXhr.Create();
}
private class DoPollEventDataListener : IListener
{
private PollingXHR pollingXHR;
public DoPollEventDataListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
var arg = args.Length > 0 ? args[0] : null;
if (arg is string)
{
pollingXHR.OnData((string)arg);
}
else if (arg is byte[])
{
pollingXHR.OnData((byte[])arg);
}
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
private class DoPollEventErrorListener : IListener
{
private PollingXHR pollingXHR;
public DoPollEventErrorListener(PollingXHR pollingXHR)
{
this.pollingXHR = pollingXHR;
}
public void Call(params object[] args)
{
var err = args.Length > 0 && args[0] is Exception ? (Exception)args[0] : null;
pollingXHR.OnError("xhr poll error", err);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
public class XHRRequest : Emitter
{
private string Method;
private string Uri;
private byte[] Data;
private string CookieHeaderValue;
private Dictionary<string, string> ExtraHeaders;
public XHRRequest(RequestOptions options)
{
Method = options.Method ?? "GET";
Uri = options.Uri;
Data = options.Data;
CookieHeaderValue = options.CookieHeaderValue;
ExtraHeaders = options.ExtraHeaders;
}
public void Create()
{
var httpMethod = Method == "POST" ? HttpMethod.Post : HttpMethod.Get;
var dataToSend = Data == null ? Encoding.UTF8.GetBytes("") : Data;
Task.Run(async() =>
{
try
{
using (var httpClientHandler = new HttpClientHandler())
{
if (ServerCertificate.Ignore)
{
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
}
using (var client = new HttpClient(httpClientHandler))
{
using (var httpContent = new ByteArrayContent(dataToSend))
{
if (Method == "POST")
{
httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
}
var request = new HttpRequestMessage(httpMethod, Uri)
{
Content = httpContent
};
if (!string.IsNullOrEmpty(CookieHeaderValue))
{
httpContent.Headers.Add(@"Cookie", CookieHeaderValue);
}
if (ExtraHeaders != null)
{
foreach (var header in ExtraHeaders)
{
httpContent.Headers.Add(header.Key, header.Value);
}
}
if (Method == "GET")
{
using (HttpResponseMessage response = await client.GetAsync(request.RequestUri))
{
var responseContent = await response.Content.ReadAsStringAsync();
OnData(responseContent);
}
}
else
{
using (HttpResponseMessage response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var contentType = response.Content.Headers.GetValues("Content-Type").Aggregate("", (acc, x) => acc + x).Trim();
if (contentType.Equals("application/octet-stream", StringComparison.OrdinalIgnoreCase))
{
var responseContent = await response.Content.ReadAsByteArrayAsync();
OnData(responseContent);
}
else
{
var responseContent = await response.Content.ReadAsStringAsync();
OnData(responseContent);
}
}
}
}
}
}
}
catch (Exception e)
{
OnError(e);
}
}).Wait();
}
private void OnSuccess()
{
this.Emit(EVENT_SUCCESS);
}
private void OnData(string data)
{
//var log = LogManager.GetLogger(Global.CallerName());
//log.Info("OnData string = " + data);
this.Emit(EVENT_DATA, data);
this.OnSuccess();
}
private void OnData(byte[] data)
{
//var log = LogManager.GetLogger(Global.CallerName());
//log.Info(string.Format("OnData byte[] ={0}", System.Text.Encoding.UTF8.GetString(data, 0, data.Length)));
this.Emit(EVENT_DATA, data);
this.OnSuccess();
}
private void OnError(Exception err)
{
this.Emit(EVENT_ERROR, err);
}
private void OnRequestHeaders(Dictionary<string, string> headers)
{
this.Emit(EVENT_REQUEST_HEADERS, headers);
}
private void OnResponseHeaders(Dictionary<string, string> headers)
{
this.Emit(EVENT_RESPONSE_HEADERS, headers);
}
public class RequestOptions
{
public string Uri;
public string Method;
public byte[] Data;
public string CookieHeaderValue;
public Dictionary<string, string> ExtraHeaders;
}
}
}
}

View File

@@ -0,0 +1,362 @@

using System.Collections.Concurrent;
using Quobject.EngineIoClientDotNet.ComponentEmitter;
using Quobject.EngineIoClientDotNet.Modules;
using Quobject.EngineIoClientDotNet.Parser;
using System;
using System.Collections.Generic;
using System.Linq;
using Quobject.EngineIoClientDotNet.Thread;
namespace Quobject.EngineIoClientDotNet.Client.Transports
{
public class Polling : Transport
{
public static readonly string NAME = "polling";
public static readonly string EVENT_POLL = "poll";
public static readonly string EVENT_POLL_COMPLETE = "pollComplete";
private bool IsPolling = false;
public Polling(Options opts) : base(opts)
{
Name = NAME;
}
protected override void DoOpen()
{
Poll();
}
public void Pause(Action onPause)
{
//var log = LogManager.GetLogger(Global.CallerName());
ReadyState = ReadyStateEnum.PAUSED;
Action pause = () =>
{
//log.Info("paused");
ReadyState = ReadyStateEnum.PAUSED;
onPause();
};
if (IsPolling || !Writable)
{
var total = new[] {0};
if (IsPolling)
{
//log.Info("we are currently polling - waiting to pause");
total[0]++;
Once(EVENT_POLL_COMPLETE, new PauseEventPollCompleteListener(total, pause));
}
if (!Writable)
{
//log.Info("we are currently writing - waiting to pause");
total[0]++;
Once(EVENT_DRAIN, new PauseEventDrainListener(total, pause));
}
}
else
{
pause();
}
}
private class PauseEventDrainListener : IListener
{
private int[] total;
private Action pause;
public PauseEventDrainListener(int[] total, Action pause)
{
this.total = total;
this.pause = pause;
}
public void Call(params object[] args)
{
//var log = LogManager.GetLogger(Global.CallerName());
//log.Info("pre-pause writing complete");
if (--total[0] == 0)
{
pause();
}
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
class PauseEventPollCompleteListener : IListener
{
private int[] total;
private Action pause;
public PauseEventPollCompleteListener(int[] total, Action pause)
{
this.total = total;
this.pause = pause;
}
public void Call(params object[] args)
{
//var log = LogManager.GetLogger(Global.CallerName());
//log.Info("pre-pause polling complete");
if (--total[0] == 0)
{
pause();
}
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
private void Poll()
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("polling");
IsPolling = true;
EasyTimer.TaskRunNoWait(DoPoll);
Emit(EVENT_POLL);
}
protected override void OnData(string data)
{
_onData(data);
}
protected override void OnData(byte[] data)
{
_onData(data);
}
private class DecodePayloadCallback : IDecodePayloadCallback
{
private Polling polling;
public DecodePayloadCallback(Polling polling)
{
this.polling = polling;
}
public bool Call(Packet packet, int index, int total)
{
if (polling.ReadyState == ReadyStateEnum.OPENING)
{
polling.OnOpen();
}
if (packet.Type == Packet.CLOSE)
{
polling.OnClose();
return false;
}
polling.OnPacket(packet);
return true;
}
}
private void _onData(object data)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info(string.Format("polling got data {0}",data));
var callback = new DecodePayloadCallback(this);
if (data is string)
{
Parser.Parser.DecodePayload((string)data, callback);
}
else if (data is byte[])
{
Parser.Parser.DecodePayload((byte[])data, callback);
}
if (ReadyState != ReadyStateEnum.CLOSED)
{
IsPolling = false;
log.Info("ReadyState != ReadyStateEnum.CLOSED");
Emit(EVENT_POLL_COMPLETE);
if (ReadyState == ReadyStateEnum.OPEN)
{
Poll();
}
else
{
log.Info(string.Format("ignoring poll - transport state {0}", ReadyState));
}
}
}
private class CloseListener : IListener
{
private Polling polling;
public CloseListener(Polling polling)
{
this.polling = polling;
}
public void Call(params object[] args)
{
//var log = LogManager.GetLogger(Global.CallerName());
//log.Info("writing close packet");
List<Packet> packets = new List<Packet>();
packets.Add(new Packet(Packet.CLOSE));
polling.Write(packets);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
protected override void DoClose()
{
var log = LogManager.GetLogger(Global.CallerName());
var closeListener = new CloseListener(this);
if (ReadyState == ReadyStateEnum.OPEN)
{
log.Info("transport open - closing");
closeListener.Call();
}
else
{
// in case we're trying to close while
// handshaking is in progress (engine.io-client GH-164)
log.Info("transport not open - deferring close");
this.Once(EVENT_OPEN, closeListener);
}
}
public class SendEncodeCallback : IEncodeCallback
{
private Polling polling;
public SendEncodeCallback(Polling polling)
{
this.polling = polling;
}
public void Call(object data)
{
//var log = LogManager.GetLogger(Global.CallerName());
//log.Info("SendEncodeCallback data = " + data);
var byteData = (byte[]) data;
polling.DoWrite(byteData, () =>
{
polling.Writable = true;
polling.Emit(EVENT_DRAIN);
});
}
}
protected override void Write(List<Packet> packets)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("Write packets.Count = " + packets.Count);
Writable = false;
var callback = new SendEncodeCallback(this);
Parser.Parser.EncodePayload(packets.ToArray(), callback);
}
public string Uri()
{
//var query = this.Query;
var query = new Dictionary<string, string>(Query);
//if (Query == null)
//{
// query = new Dictionary<string, string>();
//}
string schema = this.Secure ? "https" : "http";
string portString = "";
if (this.TimestampRequests)
{
query.Add(this.TimestampParam, DateTime.Now.Ticks + "-" + Transport.Timestamps++);
}
query.Add("b64", "1");
string _query = ParseQS.Encode(query);
if (this.Port > 0 && (("https" == schema && this.Port != 443)
|| ("http" == schema && this.Port != 80)))
{
portString = ":" + this.Port;
}
if (_query.Length > 0)
{
_query = "?" + _query;
}
return schema + "://" + this.Hostname + portString + this.Path + _query;
}
protected virtual void DoWrite(byte[] data, Action action)
{
}
protected virtual void DoPoll()
{
}
}
}

View File

@@ -0,0 +1,215 @@
using Quobject.EngineIoClientDotNet.Modules;
using Quobject.EngineIoClientDotNet.Parser;
using System;
using System.Net;
using System.Collections.Generic;
using WebSocket4Net;
using SuperSocket.ClientEngine.Proxy;
namespace Quobject.EngineIoClientDotNet.Client.Transports
{
public class WebSocket : Transport
{
public static readonly string NAME = "websocket";
private WebSocket4Net.WebSocket ws;
private List<KeyValuePair<string, string>> Cookies;
private List<KeyValuePair<string, string>> MyExtraHeaders;
public WebSocket(Options opts)
: base(opts)
{
Name = NAME;
Cookies = new List<KeyValuePair<string, string>>();
foreach (var cookie in opts.Cookies)
{
Cookies.Add(new KeyValuePair<string, string>(cookie.Key, cookie.Value));
}
MyExtraHeaders = new List<KeyValuePair<string, string>>();
foreach (var header in opts.ExtraHeaders)
{
MyExtraHeaders.Add(new KeyValuePair<string, string>(header.Key, header.Value));
}
}
protected override void DoOpen()
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("DoOpen uri =" + this.Uri());
ws = new WebSocket4Net.WebSocket(this.Uri(), String.Empty, Cookies, MyExtraHeaders)
{
EnableAutoSendPing = false
};
if (ServerCertificate.Ignore)
{
var security = ws.Security;
if (security != null)
{
security.AllowUnstrustedCertificate = true;
security.AllowNameMismatchCertificate = true;
}
}
ws.Opened += ws_Opened;
ws.Closed += ws_Closed;
ws.MessageReceived += ws_MessageReceived;
ws.DataReceived += ws_DataReceived;
ws.Error += ws_Error;
var destUrl = new UriBuilder(this.Uri());
if (this.Secure)
destUrl.Scheme = "https";
else
destUrl.Scheme = "http";
var useProxy = !WebRequest.DefaultWebProxy.IsBypassed(destUrl.Uri);
if (useProxy)
{
var proxyUrl = WebRequest.DefaultWebProxy.GetProxy(destUrl.Uri);
var proxy = new HttpConnectProxy(new DnsEndPoint(proxyUrl.Host, proxyUrl.Port), destUrl.Host);
ws.Proxy = proxy;
}
ws.Open();
}
void ws_DataReceived(object sender, DataReceivedEventArgs e)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("ws_DataReceived " + e.Data);
this.OnData(e.Data);
}
private void ws_Opened(object sender, EventArgs e)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("ws_Opened " + ws.SupportBinary);
this.OnOpen();
}
void ws_Closed(object sender, EventArgs e)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("ws_Closed");
ws.Opened -= ws_Opened;
ws.Closed -= ws_Closed;
ws.MessageReceived -= ws_MessageReceived;
ws.DataReceived -= ws_DataReceived;
ws.Error -= ws_Error;
this.OnClose();
}
void ws_MessageReceived(object sender, MessageReceivedEventArgs e)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("ws_MessageReceived e.Message= " + e.Message);
this.OnData(e.Message);
}
void ws_Error(object sender, SuperSocket.ClientEngine.ErrorEventArgs e)
{
this.OnError("websocket error", e.Exception);
}
protected override void Write(System.Collections.Immutable.ImmutableList<Parser.Packet> packets)
{
Writable = false;
foreach (var packet in packets)
{
Parser.Parser.EncodePacket(packet, new WriteEncodeCallback(this));
}
// fake drain
// defer to next tick to allow Socket to clear writeBuffer
//EasyTimer.SetTimeout(() =>
//{
Writable = true;
Emit(EVENT_DRAIN);
//}, 1);
}
public class WriteEncodeCallback : IEncodeCallback
{
private WebSocket webSocket;
public WriteEncodeCallback(WebSocket webSocket)
{
this.webSocket = webSocket;
}
public void Call(object data)
{
//var log = LogManager.GetLogger(Global.CallerName());
if (data is string)
{
webSocket.ws.Send((string)data);
}
else if (data is byte[])
{
var d = (byte[])data;
//try
//{
// var dataString = BitConverter.ToString(d);
// //log.Info(string.Format("WriteEncodeCallback byte[] data {0}", dataString));
//}
//catch (Exception e)
//{
// log.Error(e);
//}
webSocket.ws.Send(d, 0, d.Length);
}
}
}
protected override void DoClose()
{
if (ws != null)
{
try
{
ws.Close();
}
catch (Exception e)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("DoClose ws.Close() Exception= " + e.Message);
}
}
}
public string Uri()
{
Dictionary<string, string> query = null;
query = this.Query == null ? new Dictionary<string, string>() : new Dictionary<string, string>(this.Query);
var schema = this.Secure ? "wss" : "ws";
var portString = "";
if (this.TimestampRequests)
{
query.Add(this.TimestampParam, DateTime.Now.Ticks.ToString() + "-" + Transport.Timestamps++);
}
var _query = ParseQS.Encode(query);
if (this.Port > 0 && (("wss" == schema && this.Port != 443)
|| ("ws" == schema && this.Port != 80)))
{
portString = ":" + this.Port;
}
if (_query.Length > 0)
{
_query = "?" + _query;
}
return schema + "://" + this.Hostname + portString + this.Path + _query;
}
}
}

View File

@@ -0,0 +1,197 @@
using System.Collections.Concurrent;
using System.Net;
using Quobject.EngineIoClientDotNet.Modules;
using Quobject.EngineIoClientDotNet.Parser;
using System;
using System.Collections.Generic;
using WebSocket4Net;
namespace Quobject.EngineIoClientDotNet.Client.Transports
{
public class WebSocket : Transport
{
public static readonly string NAME = "websocket";
private WebSocket4Net.WebSocket ws;
private List<KeyValuePair<string, string>> Cookies;
public WebSocket(Options opts)
: base(opts)
{
Name = NAME;
Cookies = new List<KeyValuePair<string, string>>();
foreach (var cookie in opts.Cookies)
{
Cookies.Add(new KeyValuePair<string, string>(cookie.Key,cookie.Value));
}
}
protected override void DoOpen()
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("DoOpen uri =" + this.Uri());
ws = new WebSocket4Net.WebSocket(this.Uri(),"",Cookies);
ws.EnableAutoSendPing = false;
if (ServerCertificate.Ignore)
{
var security = ws.Security;
if (security != null)
{
security.AllowUnstrustedCertificate = true;
security.AllowNameMismatchCertificate = true;
}
}
ws.Opened += ws_Opened;
ws.Closed += ws_Closed;
ws.MessageReceived += ws_MessageReceived;
ws.DataReceived += ws_DataReceived;
ws.Error += ws_Error;
ws.Open();
}
void ws_DataReceived(object sender, DataReceivedEventArgs e)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("ws_DataReceived " + e.Data);
this.OnData(e.Data);
}
private void ws_Opened(object sender, EventArgs e)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("ws_Opened " + ws.SupportBinary);
this.OnOpen();
}
void ws_Closed(object sender, EventArgs e)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("ws_Closed");
ws.Opened -= ws_Opened;
ws.Closed -= ws_Closed;
ws.MessageReceived -= ws_MessageReceived;
ws.DataReceived -= ws_DataReceived;
ws.Error -= ws_Error;
this.OnClose();
}
void ws_MessageReceived(object sender, MessageReceivedEventArgs e)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("ws_MessageReceived e.Message= " + e.Message);
this.OnData(e.Message);
}
void ws_Error(object sender, SuperSocket.ClientEngine.ErrorEventArgs e)
{
this.OnError("websocket error", e.Exception);
}
protected override void Write(List<Parser.Packet> packets)
{
Writable = false;
lock (packets)
{
foreach (var packet in packets)
{
Parser.Parser.EncodePacket(packet, new WriteEncodeCallback(this));
}
}
// fake drain
// defer to next tick to allow Socket to clear writeBuffer
//EasyTimer.SetTimeout(() =>
//{
Writable = true;
Emit(EVENT_DRAIN);
//}, 1);
}
public class WriteEncodeCallback : IEncodeCallback
{
private WebSocket webSocket;
public WriteEncodeCallback(WebSocket webSocket)
{
this.webSocket = webSocket;
}
public void Call(object data)
{
//var log = LogManager.GetLogger(Global.CallerName());
if (data is string)
{
webSocket.ws.Send((string)data);
}
else if (data is byte[])
{
var d = (byte[])data;
//try
//{
// var dataString = BitConverter.ToString(d);
// //log.Info(string.Format("WriteEncodeCallback byte[] data {0}", dataString));
//}
//catch (Exception e)
//{
// log.Error(e);
//}
webSocket.ws.Send(d, 0, d.Length);
}
}
}
protected override void DoClose()
{
if (ws != null)
{
try
{
ws.Close();
}
catch (Exception e)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("DoClose ws.Close() Exception= " + e.Message);
}
}
}
public string Uri()
{
Dictionary<string, string> query = null;
query = this.Query == null ? new Dictionary<string, string>() : new Dictionary<string, string>(this.Query);
string schema = this.Secure ? "wss" : "ws";
string portString = "";
if (this.TimestampRequests)
{
query.Add(this.TimestampParam, DateTime.Now.Ticks.ToString() + "-" + Transport.Timestamps++);
}
string _query = ParseQS.Encode(query);
if (this.Port > 0 && (("wss" == schema && this.Port != 443)
|| ("ws" == schema && this.Port != 80)))
{
portString = ":" + this.Port;
}
if (_query.Length > 0)
{
_query = "?" + _query;
}
return schema + "://" + this.Hostname + portString + this.Path + _query;
}
}
}

View File

@@ -0,0 +1,215 @@
using Quobject.EngineIoClientDotNet.Modules;
using Quobject.EngineIoClientDotNet.Parser;
using System;
using System.Net;
using System.Collections.Generic;
using WebSocket4Net;
using SuperSocket.ClientEngine.Proxy;
namespace Quobject.EngineIoClientDotNet.Client.Transports
{
public class WebSocket : Transport
{
public static readonly string NAME = "websocket";
private WebSocket4Net.WebSocket ws;
private List<KeyValuePair<string, string>> Cookies;
private List<KeyValuePair<string, string>> MyExtraHeaders;
public WebSocket(Options opts)
: base(opts)
{
Name = NAME;
Cookies = new List<KeyValuePair<string, string>>();
foreach (var cookie in opts.Cookies)
{
Cookies.Add(new KeyValuePair<string, string>(cookie.Key, cookie.Value));
}
MyExtraHeaders = new List<KeyValuePair<string, string>>();
foreach (var header in opts.ExtraHeaders)
{
MyExtraHeaders.Add(new KeyValuePair<string, string>(header.Key, header.Value));
}
}
protected override void DoOpen()
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("DoOpen uri =" + this.Uri());
ws = new WebSocket4Net.WebSocket(this.Uri(), String.Empty, Cookies, MyExtraHeaders)
{
EnableAutoSendPing = false
};
if (ServerCertificate.Ignore)
{
var security = ws.Security;
if (security != null)
{
security.AllowUnstrustedCertificate = true;
security.AllowNameMismatchCertificate = true;
}
}
ws.Opened += ws_Opened;
ws.Closed += ws_Closed;
ws.MessageReceived += ws_MessageReceived;
ws.DataReceived += ws_DataReceived;
ws.Error += ws_Error;
var destUrl = new UriBuilder(this.Uri());
if (this.Secure)
destUrl.Scheme = "https";
else
destUrl.Scheme = "http";
var useProxy = !WebRequest.DefaultWebProxy.IsBypassed(destUrl.Uri);
if (useProxy)
{
var proxyUrl = WebRequest.DefaultWebProxy.GetProxy(destUrl.Uri);
var proxy = new HttpConnectProxy(new DnsEndPoint(proxyUrl.Host, proxyUrl.Port), destUrl.Host);
ws.Proxy = proxy;
}
ws.Open();
}
void ws_DataReceived(object sender, DataReceivedEventArgs e)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("ws_DataReceived " + e.Data);
this.OnData(e.Data);
}
private void ws_Opened(object sender, EventArgs e)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("ws_Opened " + ws.SupportBinary);
this.OnOpen();
}
void ws_Closed(object sender, EventArgs e)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("ws_Closed");
ws.Opened -= ws_Opened;
ws.Closed -= ws_Closed;
ws.MessageReceived -= ws_MessageReceived;
ws.DataReceived -= ws_DataReceived;
ws.Error -= ws_Error;
this.OnClose();
}
void ws_MessageReceived(object sender, MessageReceivedEventArgs e)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("ws_MessageReceived e.Message= " + e.Message);
this.OnData(e.Message);
}
void ws_Error(object sender, SuperSocket.ClientEngine.ErrorEventArgs e)
{
this.OnError("websocket error", e.Exception);
}
protected override void Write(System.Collections.Immutable.ImmutableList<Parser.Packet> packets)
{
Writable = false;
foreach (var packet in packets)
{
Parser.Parser.EncodePacket(packet, new WriteEncodeCallback(this));
}
// fake drain
// defer to next tick to allow Socket to clear writeBuffer
//EasyTimer.SetTimeout(() =>
//{
Writable = true;
Emit(EVENT_DRAIN);
//}, 1);
}
public class WriteEncodeCallback : IEncodeCallback
{
private WebSocket webSocket;
public WriteEncodeCallback(WebSocket webSocket)
{
this.webSocket = webSocket;
}
public void Call(object data)
{
//var log = LogManager.GetLogger(Global.CallerName());
if (data is string)
{
webSocket.ws.Send((string)data);
}
else if (data is byte[])
{
var d = (byte[])data;
//try
//{
// var dataString = BitConverter.ToString(d);
// //log.Info(string.Format("WriteEncodeCallback byte[] data {0}", dataString));
//}
//catch (Exception e)
//{
// log.Error(e);
//}
webSocket.ws.Send(d, 0, d.Length);
}
}
}
protected override void DoClose()
{
if (ws != null)
{
try
{
ws.Close();
}
catch (Exception e)
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("DoClose ws.Close() Exception= " + e.Message);
}
}
}
public string Uri()
{
Dictionary<string, string> query = null;
query = this.Query == null ? new Dictionary<string, string>() : new Dictionary<string, string>(this.Query);
var schema = this.Secure ? "wss" : "ws";
var portString = "";
if (this.TimestampRequests)
{
query.Add(this.TimestampParam, DateTime.Now.Ticks.ToString() + "-" + Transport.Timestamps++);
}
var _query = ParseQS.Encode(query);
if (this.Port > 0 && (("wss" == schema && this.Port != 443)
|| ("ws" == schema && this.Port != 80)))
{
portString = ":" + this.Port;
}
if (_query.Length > 0)
{
_query = "?" + _query;
}
return schema + "://" + this.Hostname + portString + this.Path + _query;
}
}
}

View File

@@ -0,0 +1,317 @@

using System.Collections.Immutable;
using Quobject.EngineIoClientDotNet.Modules;
using System;
namespace Quobject.EngineIoClientDotNet.ComponentEmitter
{
/// <remarks>
/// The event emitter which is ported from the JavaScript module.
/// <see href="https://github.com/component/emitter">https://github.com/component/emitter</see>
/// </remarks>
public class Emitter
{
private ImmutableDictionary<string, ImmutableList<IListener>> callbacks;
private ImmutableDictionary<IListener, IListener> _onceCallbacks;
public Emitter()
{
this.Off();
}
/// <summary>
/// Executes each of listeners with the given args.
/// </summary>
/// <param name="eventString">an event name.</param>
/// <param name="args"></param>
/// <returns>a reference to this object.</returns>
public virtual Emitter Emit(string eventString, params object[] args)
{
//var log = LogManager.GetLogger(Global.CallerName());
//log.Info("Emitter emit event = " + eventString);
if (this.callbacks.ContainsKey(eventString))
{
try
{
//handle in try/catch the emit
ImmutableList<IListener> callbacksLocal = this.callbacks[eventString];
foreach (var fn in callbacksLocal)
{
fn.Call(args);
}
}
catch { }
}
return this;
}
/// <summary>
/// Listens on the event.
/// </summary>
/// <param name="eventString">event name</param>
/// <param name="fn"></param>
/// <returns>a reference to this object</returns>
public Emitter On(string eventString, IListener fn)
{
if (!this.callbacks.ContainsKey(eventString))
{
//this.callbacks[eventString] = ImmutableList<IListener>.Empty;
this.callbacks = this.callbacks.Add(eventString, ImmutableList<IListener>.Empty);
}
ImmutableList<IListener> callbacksLocal = this.callbacks[eventString];
callbacksLocal = callbacksLocal.Add(fn);
//this.callbacks[eventString] = callbacksLocal;
this.callbacks = this.callbacks.Remove(eventString).Add(eventString, callbacksLocal);
return this;
}
/// <summary>
/// Listens on the event.
/// </summary>
/// <param name="eventString">event name</param>
/// <param name="fn"></param>
/// <returns>a reference to this object</returns>
public Emitter On(string eventString, Action fn)
{
var listener = new ListenerImpl(fn);
return this.On(eventString, listener);
}
/// <summary>
/// Listens on the event.
/// </summary>
/// <param name="eventString">event name</param>
/// <param name="fn"></param>
/// <returns>a reference to this object</returns>
public Emitter On(string eventString, Action<object> fn)
{
var listener = new ListenerImpl(fn);
return this.On(eventString, listener);
}
/// <summary>
/// Adds a one time listener for the event.
/// </summary>
/// <param name="eventString">an event name.</param>
/// <param name="fn"></param>
/// <returns>a reference to this object</returns>
public Emitter Once(string eventString, IListener fn)
{
var on = new OnceListener(eventString, fn, this);
_onceCallbacks = _onceCallbacks.Add(fn, on);
this.On(eventString, on);
return this;
}
/// <summary>
/// Adds a one time listener for the event.
/// </summary>
/// <param name="eventString">an event name.</param>
/// <param name="fn"></param>
/// <returns>a reference to this object</returns>
public Emitter Once(string eventString, Action fn)
{
var listener = new ListenerImpl(fn);
return this.Once(eventString, listener);
}
/// <summary>
/// Removes all registered listeners.
/// </summary>
/// <returns>a reference to this object.</returns>
public Emitter Off()
{
callbacks = ImmutableDictionary.Create<string, ImmutableList<IListener>>();
_onceCallbacks = ImmutableDictionary.Create<IListener, IListener>();
return this;
}
/// <summary>
/// Removes all listeners of the specified event.
/// </summary>
/// <param name="eventString">an event name</param>
/// <returns>a reference to this object.</returns>
public Emitter Off(string eventString)
{
try
{
ImmutableList<IListener> retrievedValue;
if (!callbacks.TryGetValue(eventString, out retrievedValue))
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info(string.Format("Emitter.Off Could not remove {0}", eventString));
}
if (retrievedValue != null)
{
callbacks = callbacks.Remove(eventString);
foreach (var listener in retrievedValue)
{
_onceCallbacks.Remove(listener);
}
}
}
catch (Exception)
{
this.Off();
}
return this;
}
/// <summary>
/// Removes the listener
/// </summary>
/// <param name="eventString">an event name</param>
/// <param name="fn"></param>
/// <returns>a reference to this object.</returns>
public Emitter Off(string eventString, IListener fn)
{
try
{
if (this.callbacks.ContainsKey(eventString))
{
ImmutableList<IListener> callbacksLocal = this.callbacks[eventString];
IListener offListener;
_onceCallbacks.TryGetValue(fn, out offListener);
_onceCallbacks = _onceCallbacks.Remove(fn);
if (callbacksLocal.Count > 0 && callbacksLocal.Contains(offListener ?? fn))
{
callbacksLocal = callbacksLocal.Remove(offListener ?? fn);
this.callbacks = this.callbacks.Remove(eventString);
this.callbacks = this.callbacks.Add(eventString, callbacksLocal);
}
}
}catch(Exception)
{
this.Off();
}
return this;
}
/// <summary>
/// Returns a list of listeners for the specified event.
/// </summary>
/// <param name="eventString">an event name.</param>
/// <returns>a reference to this object</returns>
public ImmutableList<IListener> Listeners(string eventString)
{
if (this.callbacks.ContainsKey(eventString))
{
ImmutableList<IListener> callbacksLocal = this.callbacks[eventString];
return callbacksLocal ?? ImmutableList<IListener>.Empty;
}
return ImmutableList<IListener>.Empty;
}
/// <summary>
/// Check if this emitter has listeners for the specified event.
/// </summary>
/// <param name="eventString">an event name</param>
/// <returns>bool</returns>
public bool HasListeners(string eventString)
{
return this.Listeners(eventString).Count > 0;
}
}
public interface IListener: System.IComparable<IListener>
{
int GetId();
void Call(params object[] args);
}
public class ListenerImpl : IListener
{
private static int id_counter = 0;
private int Id;
private readonly Action fn1;
private readonly Action<object> fn;
public ListenerImpl(Action<object> fn)
{
this.fn = fn;
this.Id = id_counter++;
}
public ListenerImpl(Action fn)
{
this.fn1 = fn;
this.Id = id_counter++;
}
public void Call(params object[] args)
{
if (fn != null)
{
var arg = args.Length > 0 ? args[0] : null;
fn(arg);
}
else
{
fn1();
}
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return Id;
}
}
public class OnceListener : IListener
{
private static int id_counter = 0;
private int Id;
private readonly string _eventString;
private readonly IListener _fn;
private readonly Emitter _emitter;
public OnceListener(string eventString, IListener fn, Emitter emitter)
{
this._eventString = eventString;
this._fn = fn;
this._emitter = emitter;
Id = id_counter++;
}
void IListener.Call(params object[] args)
{
_emitter.Off(_eventString, this);
_fn.Call(args);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return Id;
}
}
}

View File

@@ -0,0 +1,322 @@

using System.Collections.Concurrent;
using System.Collections.Generic;
using Quobject.EngineIoClientDotNet.Modules;
using System;
namespace Quobject.EngineIoClientDotNet.ComponentEmitter
{
/// <remarks>
/// The event emitter which is ported from the JavaScript module.
/// <see href="https://github.com/component/emitter">https://github.com/component/emitter</see>
/// </remarks>
public class Emitter
{
private ConcurrentDictionary<string, List<IListener>> callbacks;
private ConcurrentDictionary<IListener, IListener> _onceCallbacks;
public Emitter()
{
this.Off();
}
/// <summary>
/// Executes each of listeners with the given args.
/// </summary>
/// <param name="eventString">an event name.</param>
/// <param name="args"></param>
/// <returns>a reference to this object.</returns>
public virtual Emitter Emit(string eventString, params object[] args)
{
//var log = LogManager.GetLogger(Global.CallerName());
//log.Info("Emitter emit event = " + eventString);
if (this.callbacks.ContainsKey(eventString))
{
List<IListener> callbacksLocal = this.callbacks[eventString];
var listCopy = new List<IListener>();
listCopy.AddRange(callbacksLocal);
foreach (var fn in listCopy)
{
fn.Call(args);
}
}
return this;
}
/// <summary>
/// Listens on the event.
/// </summary>
/// <param name="eventString">event name</param>
/// <param name="fn"></param>
/// <returns>a reference to this object</returns>
public Emitter On(string eventString, IListener fn)
{
if (!this.callbacks.ContainsKey(eventString))
{
//this.callbacks[eventString] = List<IListener>();
this.callbacks.TryAdd(eventString,new List<IListener>());
}
List<IListener> callbacksLocal = this.callbacks[eventString];
callbacksLocal.Add(fn);
//this.callbacks[eventString] = callbacksLocal;
List<IListener> outref;
this.callbacks.TryRemove(eventString, out outref);
this.callbacks.TryAdd(eventString, callbacksLocal);
return this;
}
/// <summary>
/// Listens on the event.
/// </summary>
/// <param name="eventString">event name</param>
/// <param name="fn"></param>
/// <returns>a reference to this object</returns>
public Emitter On(string eventString, Action fn)
{
var listener = new ListenerImpl(fn);
return this.On(eventString, listener);
}
/// <summary>
/// Listens on the event.
/// </summary>
/// <param name="eventString">event name</param>
/// <param name="fn"></param>
/// <returns>a reference to this object</returns>
public Emitter On(string eventString, Action<object> fn)
{
var listener = new ListenerImpl(fn);
return this.On(eventString, listener);
}
/// <summary>
/// Adds a one time listener for the event.
/// </summary>
/// <param name="eventString">an event name.</param>
/// <param name="fn"></param>
/// <returns>a reference to this object</returns>
public Emitter Once(string eventString, IListener fn)
{
var on = new OnceListener(eventString, fn, this);
_onceCallbacks.TryAdd(fn, on);
this.On(eventString, on);
return this;
}
/// <summary>
/// Adds a one time listener for the event.
/// </summary>
/// <param name="eventString">an event name.</param>
/// <param name="fn"></param>
/// <returns>a reference to this object</returns>
public Emitter Once(string eventString, Action fn)
{
var listener = new ListenerImpl(fn);
return this.Once(eventString, listener);
}
/// <summary>
/// Removes all registered listeners.
/// </summary>
/// <returns>a reference to this object.</returns>
public Emitter Off()
{
callbacks = new ConcurrentDictionary<string, List<IListener>>();
_onceCallbacks = new ConcurrentDictionary<IListener, IListener>();
return this;
}
/// <summary>
/// Removes all listeners of the specified event.
/// </summary>
/// <param name="eventString">an event name</param>
/// <returns>a reference to this object.</returns>
public Emitter Off(string eventString)
{
try
{
List<IListener> retrievedValue;
if (!callbacks.TryGetValue(eventString, out retrievedValue))
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info(string.Format("Emitter.Off Could not remove {0}", eventString));
}
if (retrievedValue != null)
{
List<IListener> outref;
IListener ilistenerOutRef;
callbacks.TryRemove(eventString, out outref);
foreach (var listener in retrievedValue)
{
_onceCallbacks.TryRemove(listener, out ilistenerOutRef);
}
}
}
catch (Exception)
{
this.Off();
}
return this;
}
/// <summary>
/// Removes the listener
/// </summary>
/// <param name="eventString">an event name</param>
/// <param name="fn"></param>
/// <returns>a reference to this object.</returns>
public Emitter Off(string eventString, IListener fn)
{
try
{
if (this.callbacks.ContainsKey(eventString))
{
List<IListener> callbacksLocal = this.callbacks[eventString];
IListener offListener;
//_onceCallbacks.TryGetValue(fn,out offListener);
_onceCallbacks.TryRemove(fn, out offListener);
if (callbacksLocal.Count > 0 && callbacksLocal.Contains(offListener ?? fn))
{
callbacksLocal.Remove(offListener ?? fn);
List<IListener> outref;
this.callbacks.TryRemove(eventString, out outref);
this.callbacks.TryAdd(eventString, callbacksLocal);
}
}
}
catch (Exception)
{
this.Off();
}
return this;
}
/// <summary>
/// Returns a list of listeners for the specified event.
/// </summary>
/// <param name="eventString">an event name.</param>
/// <returns>a reference to this object</returns>
public List<IListener> Listeners(string eventString)
{
if (this.callbacks.ContainsKey(eventString))
{
List<IListener> callbacksLocal = this.callbacks[eventString];
return callbacksLocal ?? new List<IListener>();
}
return new List<IListener>();
}
/// <summary>
/// Check if this emitter has listeners for the specified event.
/// </summary>
/// <param name="eventString">an event name</param>
/// <returns>bool</returns>
public bool HasListeners(string eventString)
{
return this.Listeners(eventString).Count > 0;
}
}
public interface IListener: System.IComparable<IListener>
{
int GetId();
void Call(params object[] args);
}
public class ListenerImpl : IListener
{
private static int id_counter = 0;
private int Id;
private readonly Action fn1;
private readonly Action<object> fn;
public ListenerImpl(Action<object> fn)
{
this.fn = fn;
this.Id = id_counter++;
}
public ListenerImpl(Action fn)
{
this.fn1 = fn;
this.Id = id_counter++;
}
public void Call(params object[] args)
{
if (fn != null)
{
var arg = args.Length > 0 ? args[0] : null;
fn(arg);
}
else
{
fn1();
}
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return Id;
}
}
public class OnceListener : IListener
{
private static int id_counter = 0;
private int Id;
private readonly string _eventString;
private readonly IListener _fn;
private readonly Emitter _emitter;
public OnceListener(string eventString, IListener fn, Emitter emitter)
{
this._eventString = eventString;
this._fn = fn;
this._emitter = emitter;
Id = id_counter++;
}
void IListener.Call(params object[] args)
{
_emitter.Off(_eventString, this);
_fn.Call(args);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return Id;
}
}
}

View File

@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B6731266-B247-4A63-B10B-F938288248B6}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>EngineIoClientDotNet</RootNamespace>
<AssemblyName>EngineIoClientDotNet</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>packages\Newtonsoft.Json.10.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SuperSocket.ClientEngine, Version=0.8.0.8, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\SuperSocket.ClientEngine.Core.0.8.0.8\lib\net45\SuperSocket.ClientEngine.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="WebSocket4Net, Version=0.15.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\WebSocket4Net.0.15.0-beta6\lib\net45\WebSocket4Net.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Quobject.Collections.Immutable\AvlNode.cs">
<Link>Quobject.Collections.Immutable\AvlNode.cs</Link>
</Compile>
<Compile Include="..\Quobject.Collections.Immutable\IImmutableDictionary.cs">
<Link>Quobject.Collections.Immutable\IImmutableDictionary.cs</Link>
</Compile>
<Compile Include="..\Quobject.Collections.Immutable\IImmutableList.cs">
<Link>Quobject.Collections.Immutable\IImmutableList.cs</Link>
</Compile>
<Compile Include="..\Quobject.Collections.Immutable\IImmutableQueue.cs">
<Link>Quobject.Collections.Immutable\IImmutableQueue.cs</Link>
</Compile>
<Compile Include="..\Quobject.Collections.Immutable\IImmutableSet.cs">
<Link>Quobject.Collections.Immutable\IImmutableSet.cs</Link>
</Compile>
<Compile Include="..\Quobject.Collections.Immutable\IImmutableStack.cs">
<Link>Quobject.Collections.Immutable\IImmutableStack.cs</Link>
</Compile>
<Compile Include="..\Quobject.Collections.Immutable\ImmutableDictionary.cs">
<Link>Quobject.Collections.Immutable\ImmutableDictionary.cs</Link>
</Compile>
<Compile Include="..\Quobject.Collections.Immutable\ImmutableList.cs">
<Link>Quobject.Collections.Immutable\ImmutableList.cs</Link>
</Compile>
<Compile Include="..\Quobject.Collections.Immutable\ImmutableQueue.cs">
<Link>Quobject.Collections.Immutable\ImmutableQueue.cs</Link>
</Compile>
<Compile Include="..\Quobject.Collections.Immutable\ImmutableStack.cs">
<Link>Quobject.Collections.Immutable\ImmutableStack.cs</Link>
</Compile>
<Compile Include="Client\EngineIOException.cs" />
<Compile Include="Client\HandshakeData.cs" />
<Compile Include="Client\Socket.cs" />
<Compile Include="Client\Transport.cs" />
<Compile Include="Client\Transports\Polling.cs" />
<Compile Include="Client\Transports\PollingXHR.cs" />
<Compile Include="Client\Transports\WebSocket.cs" />
<Compile Include="ComponentEmitter\Emitter.cs" />
<Compile Include="Modules\Global.cs" />
<Compile Include="Modules\LogManager.cs" />
<Compile Include="Modules\ParseQS.cs" />
<Compile Include="Modules\ServerCertificate.cs" />
<Compile Include="Modules\UTF8.cs" />
<Compile Include="Modules\UTF8Exception.cs" />
<Compile Include="Parser\Buffer.cs" />
<Compile Include="Parser\ByteBuffer.cs" />
<Compile Include="Parser\IDecodePayloadCallback.cs" />
<Compile Include="Parser\IEncodeCallback.cs" />
<Compile Include="Parser\Packet.cs" />
<Compile Include="Parser\Parser.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Thread\EasyTimer.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,32 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EngineIoClientDotNet.mono", "EngineIoClientDotNet.mono.csproj", "{B6731266-B247-4A63-B10B-F938288248B6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EngineIoClientDotNet.Tests.mono", "..\EngineIoClientDotNet.Tests.mono\EngineIoClientDotNet.Tests.mono.csproj", "{382C2A10-8043-49C6-9DE5-39CA25C2418C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quobject.Collections.Immutable", "..\Quobject.Collections.Immutable\Quobject.Collections.Immutable.csproj", "{024A2111-4B19-44D7-917E-8514CF632469}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B6731266-B247-4A63-B10B-F938288248B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6731266-B247-4A63-B10B-F938288248B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6731266-B247-4A63-B10B-F938288248B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6731266-B247-4A63-B10B-F938288248B6}.Release|Any CPU.Build.0 = Release|Any CPU
{382C2A10-8043-49C6-9DE5-39CA25C2418C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{382C2A10-8043-49C6-9DE5-39CA25C2418C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{382C2A10-8043-49C6-9DE5-39CA25C2418C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{382C2A10-8043-49C6-9DE5-39CA25C2418C}.Release|Any CPU.Build.0 = Release|Any CPU
{024A2111-4B19-44D7-917E-8514CF632469}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{024A2111-4B19-44D7-917E-8514CF632469}.Debug|Any CPU.Build.0 = Debug|Any CPU
{024A2111-4B19-44D7-917E-8514CF632469}.Release|Any CPU.ActiveCfg = Release|Any CPU
{024A2111-4B19-44D7-917E-8514CF632469}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,48 @@
using System;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
namespace Quobject.EngineIoClientDotNet.Modules
{
public static class Global
{
public static string EncodeURIComponent(string str)
{
//http://stackoverflow.com/a/4550600/1109316
return Uri.EscapeDataString(str);
}
public static string DecodeURIComponent(string str)
{
return Uri.UnescapeDataString(str);
}
public static string CallerName([CallerMemberName]string caller = "", [CallerLineNumber]int number = 0, [CallerFilePath]string path = "")
{
var s = path.Split('\\');
var fileName = s.LastOrDefault();
if (path.Contains("SocketIoClientDotNet.Tests"))
{
path = "SocketIoClientDotNet.Tests";
}
else if (path.Contains("SocketIoClientDotNet"))
{
path = "SocketIoClientDotNet";
}
else if (path.Contains("EngineIoClientDotNet"))
{
path = "EngineIoClientDotNet";
}
return string.Format("{0}-{1}:{2}#{3}",path, fileName, caller, number);
}
//from http://stackoverflow.com/questions/8767103/how-to-remove-invalid-code-points-from-a-string
public static string StripInvalidUnicodeCharacters(string str)
{
var invalidCharactersRegex = new Regex("([\ud800-\udbff](?![\udc00-\udfff]))|((?<![\ud800-\udbff])[\udc00-\udfff])");
return invalidCharactersRegex.Replace(str, "");
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using System.Web;
namespace Quobject.EngineIoClientDotNet.Modules
{
public static class Global
{
public static string EncodeURIComponent(string str)
{
//http://stackoverflow.com/a/4550600/1109316
return Uri.EscapeDataString(str);
}
public static string DecodeURIComponent(string str)
{
return Uri.UnescapeDataString(str);
}
public static string CallerName(string caller = "", int number = 0, string path = "")
{
var s = path.Split('\\');
var fileName = s.LastOrDefault();
if (path.Contains("SocketIoClientDotNet.Tests"))
{
path = "SocketIoClientDotNet.Tests";
}
else if (path.Contains("SocketIoClientDotNet"))
{
path = "SocketIoClientDotNet";
}
else if (path.Contains("EngineIoClientDotNet"))
{
path = "EngineIoClientDotNet";
}
return string.Format("{0}-{1}:{2}#{3}",path, fileName, caller, number);
}
//from http://stackoverflow.com/questions/8767103/how-to-remove-invalid-code-points-from-a-string
public static string StripInvalidUnicodeCharacters(string str)
{
var invalidCharactersRegex = new Regex("([\ud800-\udbff](?![\udc00-\udfff]))|((?<![\ud800-\udbff])[\udc00-\udfff])");
return invalidCharactersRegex.Replace(str, "");
}
}
}

View File

@@ -0,0 +1,177 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace Quobject.EngineIoClientDotNet.Modules
{
public static class Global
{
public static string EncodeURIComponent(string str)
{
//http://stackoverflow.com/a/4550600/1109316
return Uri.EscapeDataString(str);
}
public static string DecodeURIComponent(string str)
{
return Uri.UnescapeDataString(str);
}
public static string CallerName([CallerMemberName]string caller = "", [CallerLineNumber]int number = 0, [CallerFilePath]string path = "")
{
var s = path.Split('\\');
var fileName = s.LastOrDefault();
if (path.Contains("SocketIoClientDotNet.Tests"))
{
path = "SocketIoClientDotNet.Tests";
}
else if (path.Contains("SocketIoClientDotNet"))
{
path = "SocketIoClientDotNet";
}
else if (path.Contains("EngineIoClientDotNet"))
{
path = "EngineIoClientDotNet";
}
return string.Format("{0}-{1}:{2}#{3}", path, fileName, caller, number);
}
//from http://stackoverflow.com/questions/8767103/how-to-remove-invalid-code-points-from-a-string
public static string StripInvalidUnicodeCharacters(string str)
{
var invalidCharactersRegex = new Regex("([\ud800-\udbff](?![\udc00-\udfff]))|((?<![\ud800-\udbff])[\udc00-\udfff])");
return invalidCharactersRegex.Replace(str, "");
}
}
// from http://social.msdn.microsoft.com/Forums/en-US/163ef755-ff7b-4ea5-b226-bbe8ef5f4796/is-there-a-pattern-for-calling-an-async-method-synchronously?forum=async
public static class AsyncInline
{
public static void Run(Func<Task> item)
{
var oldContext = SynchronizationContext.Current;
var synch = new ExclusiveSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(synch);
synch.Post(async _ =>
{
try
{
await item();
}
catch (Exception e)
{
synch.InnerException = e;
throw;
}
finally
{
synch.EndMessageLoop();
}
}, null);
synch.BeginMessageLoop();
SynchronizationContext.SetSynchronizationContext(oldContext);
}
public static T Run<T>(Func<Task<T>> item)
{
var oldContext = SynchronizationContext.Current;
var synch = new ExclusiveSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(synch);
T ret = default(T);
synch.Post(async _ =>
{
try
{
ret = await
item();
}
catch (Exception e)
{
synch.InnerException = e;
throw;
}
finally
{
synch.EndMessageLoop();
}
}, null);
synch.BeginMessageLoop();
SynchronizationContext.SetSynchronizationContext(oldContext);
return ret;
}
private class ExclusiveSynchronizationContext : SynchronizationContext
{
private bool done;
public Exception InnerException { get; set; }
readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false);
readonly Queue<Tuple<SendOrPostCallback, object>> items =
new Queue<Tuple<SendOrPostCallback, object>>();
public override void Send(SendOrPostCallback d, object state)
{
throw new NotSupportedException("We cannot send to our same thread");
}
public override void Post(SendOrPostCallback d, object state)
{
lock (items)
{
items.Enqueue(Tuple.Create(d, state));
}
workItemsWaiting.Set();
}
public void EndMessageLoop()
{
Post(_ => done = true, null);
}
public void BeginMessageLoop()
{
while (!done)
{
Tuple<SendOrPostCallback, object> task = null;
lock (items)
{
if (items.Count > 0)
{
task = items.Dequeue();
}
}
if (task != null)
{
task.Item1(task.Item2);
if (InnerException != null) // the method threw an exeption
{
throw new AggregateException("AsyncInline.Run method threw an exception.",
InnerException);
}
}
else
{
workItemsWaiting.WaitOne();
}
}
}
public override SynchronizationContext CreateCopy()
{
return this;
}
}
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Linq;
using System.Net;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
namespace Quobject.EngineIoClientDotNet.Modules
{
public static class Global
{
public static string EncodeURIComponent(string str)
{
//http://stackoverflow.com/a/4550600/1109316
return Uri.EscapeDataString(str);
}
public static string DecodeURIComponent(string str)
{
return Uri.UnescapeDataString(str);
}
public static string CallerName([CallerMemberName]string caller = "", [CallerLineNumber]int number = 0, [CallerFilePath]string path = "")
{
var s = path.Split('\\');
var fileName = s.LastOrDefault();
if (path.Contains("SocketIoClientDotNet.Tests"))
{
path = "SocketIoClientDotNet.Tests";
}
else if (path.Contains("SocketIoClientDotNet"))
{
path = "SocketIoClientDotNet";
}
else if (path.Contains("EngineIoClientDotNet"))
{
path = "EngineIoClientDotNet";
}
return string.Format("{0}-{1}:{2}#{3}", path, fileName, caller, number);
}
//from http://stackoverflow.com/questions/8767103/how-to-remove-invalid-code-points-from-a-string
public static string StripInvalidUnicodeCharacters(string str)
{
var invalidCharactersRegex = new Regex("([\ud800-\udbff](?![\udc00-\udfff]))|((?<![\ud800-\udbff])[\udc00-\udfff])");
return invalidCharactersRegex.Replace(str, "");
}
}
}

View File

@@ -0,0 +1,109 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
namespace Quobject.EngineIoClientDotNet.Modules
{
public class LogManager
{
private const string LogFilePath = "XunitTrace.log";
private static readonly LogManager EmptyLogger = new LogManager(null);
private static StreamWriter writer;
private readonly string type;
#region Statics
public static void SetupLogManager()
{}
public static LogManager GetLogger(string type)
{
return new LogManager(type);
}
public static LogManager GetLogger(Type type)
{
return GetLogger(type.ToString());
}
public static LogManager GetLogger(MethodBase methodBase)
{
#if DEBUG
string declaringType = methodBase.DeclaringType != null
? methodBase.DeclaringType.ToString()
: string.Empty;
string fullType = string.Format("{0}#{1}", declaringType, methodBase.Name);
return GetLogger(fullType);
#else
return EmptyLogger;
#endif
}
#endregion
public LogManager(string type)
{
this.type = type;
}
public static bool Enabled { get; set; }
private static StreamWriter Writer
{
get
{
if (writer == null)
{
FileStream fs = new FileStream(
LogFilePath, FileMode.Append, FileAccess.Write, FileShare.Read);
writer = new StreamWriter(fs, Encoding.UTF8)
{
AutoFlush = true
};
}
return writer;
}
}
[Conditional("DEBUG")]
public void Info(string msg)
{
if (!Enabled)
{
return;
}
Writer.WriteLine(
"{0:yyyy-MM-dd HH:mm:ss fff} [] {1} {2}",
DateTime.Now,
this.type,
Global.StripInvalidUnicodeCharacters(msg));
}
[Conditional("DEBUG")]
public void Error(string p, Exception exception)
{
//this.Info($"ERROR {p} {exception.Message} {exception.StackTrace}");
this.Info(String.Format("ERROR {0} {1} {2}", p, exception.Message, exception.StackTrace));
if (exception.InnerException != null)
{
//this.Info($"ERROR exception.InnerException {p} {exception.InnerException.Message} {exception.InnerException.StackTrace}");
this.Info(String.Format("ERROR {0} {1} {2} {3}", exception.InnerException, p,
exception.InnerException.Message, exception.InnerException.StackTrace));
}
}
[Conditional("DEBUG")]
internal void Error(Exception e)
{
this.Error("", e);
}
}
}

View File

@@ -0,0 +1,79 @@
using System.Collections.Immutable;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Quobject.EngineIoClientDotNet.Modules
{
/// <remarks>
/// Provides methods for parsing a query string into an object, and vice versa.
/// Ported from the JavaScript module.
/// <see href="https://www.npmjs.org/package/parseqs">https://www.npmjs.org/package/parseqs</see>
/// </remarks>
public class ParseQS
{
/// <summary>
/// Compiles a querystring
/// Returns string representation of the object
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static string Encode(ImmutableDictionary<string, string> obj)
{
var sb = new StringBuilder();
foreach (var key in obj.Keys.OrderBy(x=>x))
{
if (sb.Length > 0)
{
sb.Append("&");
}
sb.Append(Global.EncodeURIComponent(key));
sb.Append("=");
sb.Append(Global.EncodeURIComponent(obj[key]));
}
return sb.ToString();
}
/// <summary>
/// Compiles a querystring
/// Returns string representation of the object
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
internal static string Encode(System.Collections.Generic.Dictionary<string, string> obj)
{
var sb = new StringBuilder();
foreach (var key in obj.Keys)
{
if (sb.Length > 0)
{
sb.Append("&");
}
sb.Append(Global.EncodeURIComponent(key));
sb.Append("=");
sb.Append(Global.EncodeURIComponent(obj[key]));
}
return sb.ToString();
}
/// <summary>
/// Parses a simple querystring into an object
/// </summary>
/// <param name="qs"></param>
/// <returns></returns>
public static Dictionary<string, string> Decode(string qs)
{
var qry = new Dictionary<string, string>();
var pairs = qs.Split('&');
for (int i = 0; i < pairs.Length; i++)
{
var pair = pairs[i].Split('=');
qry.Add(Global.DecodeURIComponent(pair[0]), Global.DecodeURIComponent(pair[1]));
}
return qry;
}
}
}

View File

@@ -0,0 +1,82 @@

using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Quobject.EngineIoClientDotNet.Modules
{
/// <remarks>
/// Provides methods for parsing a query string into an object, and vice versa.
/// Ported from the JavaScript module.
/// <see href="https://www.npmjs.org/package/parseqs">https://www.npmjs.org/package/parseqs</see>
/// </remarks>
public class ParseQS
{
/// <summary>
/// Compiles a querystring
/// Returns string representation of the object
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static string Encode(ConcurrentDictionary<string, string> obj)
{
var sb = new StringBuilder();
foreach (var key in obj.Keys.OrderBy(x=>x))
{
if (sb.Length > 0)
{
sb.Append("&");
}
sb.Append(Global.EncodeURIComponent(key));
sb.Append("=");
sb.Append(Global.EncodeURIComponent(obj[key]));
}
return sb.ToString();
}
/// <summary>
/// Compiles a querystring
/// Returns string representation of the object
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
internal static string Encode(System.Collections.Generic.Dictionary<string, string> obj)
{
var sb = new StringBuilder();
foreach (var key in obj.Keys)
{
if (sb.Length > 0)
{
sb.Append("&");
}
sb.Append(Global.EncodeURIComponent(key));
sb.Append("=");
sb.Append(Global.EncodeURIComponent(obj[key]));
}
return sb.ToString();
}
/// <summary>
/// Parses a simple querystring into an object
/// </summary>
/// <param name="qs"></param>
/// <returns></returns>
public static Dictionary<string, string> Decode(string qs)
{
var qry = new Dictionary<string, string>();
var pairs = qs.Split('&');
for (int i = 0; i < pairs.Length; i++)
{
var pair = pairs[i].Split('=');
qry.Add(Global.DecodeURIComponent(pair[0]), Global.DecodeURIComponent(pair[1]));
}
return qry;
}
}
}

View File

@@ -0,0 +1,20 @@
using System.Net;
namespace Quobject.EngineIoClientDotNet.Modules
{
public class ServerCertificate
{
public static bool Ignore { get; set; }
static ServerCertificate()
{
Ignore = false;
}
public static void IgnoreServerCertificateValidation()
{
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
Ignore = true;
}
}
}

View File

@@ -0,0 +1,19 @@

namespace Quobject.EngineIoClientDotNet.Modules
{
public class ServerCertificate
{
public static bool Ignore { get; set; }
static ServerCertificate()
{
Ignore = false;
}
public static void IgnoreServerCertificateValidation()
{
//ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
Ignore = true;
}
}
}

View File

@@ -0,0 +1,17 @@
namespace Quobject.EngineIoClientDotNet.Modules
{
public class ServerCertificate
{
public static bool Ignore { get; set; }
static ServerCertificate()
{
Ignore = false;
}
public static void IgnoreServerCertificateValidation()
{
Ignore = true;
}
}
}

View File

@@ -0,0 +1,19 @@

namespace Quobject.EngineIoClientDotNet.Modules
{
public class ServerCertificate
{
public static bool Ignore { get; set; }
static ServerCertificate()
{
Ignore = false;
}
public static void IgnoreServerCertificateValidation()
{
//ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
Ignore = true;
}
}
}

View File

@@ -0,0 +1,228 @@
using System.Collections.Generic;
using System.Text;
namespace Quobject.EngineIoClientDotNet.Modules
{
/// <remarks>
/// UTF-8 encoder/decoder ported from utf8.js.
/// Ported from the JavaScript module.
/// <see href="https://github.com/mathiasbynens/utf8.js">https://github.com/mathiasbynens/utf8.js</see>
/// </remarks>
public class UTF8
{
private static List<int> byteArray;
private static int byteCount;
private static int byteIndex;
public static string Encode(string str)
{
List<int> codePoints = Ucs2Decode(str);
var length = codePoints.Count;
var index = -1;
var byteString = new StringBuilder();
while (++index < length)
{
var codePoint = codePoints[index];
byteString.Append(EncodeCodePoint(codePoint));
}
return byteString.ToString();
}
public static string Decode(string byteString)
{
byteArray = Ucs2Decode(byteString);
byteCount = byteArray.Count;
byteIndex = 0;
var codePoints = new List<int>();
int tmp;
while ((tmp = DecodeSymbol()) != -1)
{
codePoints.Add(tmp);
}
return Ucs2Encode(codePoints);
}
private static int DecodeSymbol()
{
int byte1;
int byte2;
int byte3;
int byte4;
int codePoint;
if (byteIndex > byteCount)
{
throw new UTF8Exception("Invalid byte index");
}
if (byteIndex == byteCount)
{
return -1;
}
byte1 = byteArray[byteIndex] & 0xFF;
byteIndex++;
if ((byte1 & 0x80) == 0)
{
return byte1;
}
if ((byte1 & 0xE0) == 0xC0)
{
byte2 = ReadContinuationByte();
codePoint = ((byte1 & 0x1F) << 6) | byte2;
if (codePoint >= 0x80)
{
return codePoint;
}
else
{
throw new UTF8Exception("Invalid continuation byte");
}
}
if ((byte1 & 0xF0) == 0xE0)
{
byte2 = ReadContinuationByte();
byte3 = ReadContinuationByte();
codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
if (codePoint >= 0x0800)
{
return codePoint;
}
else
{
throw new UTF8Exception("Invalid continuation byte");
}
}
if ((byte1 & 0xF8) == 0xF0)
{
byte2 = ReadContinuationByte();
byte3 = ReadContinuationByte();
byte4 = ReadContinuationByte();
codePoint = ((byte1 & 0x0F) << 0x12) | (byte2 << 0x0C) | (byte3 << 0x06) | byte4;
if (codePoint >= 0x010000 && codePoint <= 0x10FFFF)
{
return codePoint;
}
}
throw new UTF8Exception("Invalid continuation byte");
}
private static int ReadContinuationByte()
{
if (byteIndex >= byteCount)
{
throw new UTF8Exception("Invalid byte index");
}
int continuationByte = byteArray[byteIndex] & 0xFF;
byteIndex++;
if ((continuationByte & 0xC0) == 0x80)
{
return continuationByte & 0x3F;
}
throw new UTF8Exception("Invalid continuation byte");
}
private static string EncodeCodePoint(int codePoint)
{
var sb = new StringBuilder();
if ((codePoint & 0xFFFFFF80) == 0)
{
// 1-byte sequence
sb.Append((char) codePoint);
return sb.ToString();
}
if ((codePoint & 0xFFFFF800) == 0)
{
// 2-byte sequence
sb.Append((char) (((codePoint >> 6) & 0x1F) | 0xC0));
}
else if ((codePoint & 0xFFFF0000) == 0)
{
// 3-byte sequence
sb.Append((char) (((codePoint >> 12) & 0x0F) | 0xE0));
sb.Append( CreateByte(codePoint, 6));
}
else if ((codePoint & 0xFFE00000) == 0)
{
// 4-byte sequence
sb.Append((char) (((codePoint >> 18) & 0x07) | 0xF0));
sb.Append( CreateByte(codePoint, 12));
sb.Append( CreateByte(codePoint, 6));
}
sb.Append((char) ((codePoint & 0x3F) | 0x80));
return sb.ToString();
}
private static char CreateByte(int codePoint, int shift)
{
return (char)(((codePoint >> shift) & 0x3F) | 0x80);
}
private static List<int> Ucs2Decode(string str)
{
var output = new List<int>();
var counter = 0;
var length = str.Length;
while (counter < length)
{
var value = (int)str[counter++];
if (value >= 0xD800 && value <= 0xDBFF && counter < length)
{
// high surrogate, and there is a next character
var extra = (int)str[counter++];
if ((extra & 0xFC00) == 0xDC00)
{
// low surrogate
output.Add(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
}
else
{
// unmatched surrogate; only append this code unit, in case the next
// code unit is the high surrogate of a surrogate pair
output.Add(value);
counter--;
}
}
else
{
output.Add(value);
}
}
return output;
}
private static string Ucs2Encode(List<int> array)
{
var sb = new StringBuilder();
var index = -1;
while (++index < array.Count)
{
var value = array[index];
if (value > 0xFFFF)
{
value -= 0x10000;
sb.Append((char)(((int)((uint)value >> 10)) & 0x3FF | 0xD800));
value = 0xDC00 | value & 0x3FF;
}
sb.Append((char)value);
}
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,10 @@
using System;
namespace Quobject.EngineIoClientDotNet.Modules
{
public class UTF8Exception : Exception
{
public UTF8Exception(string message) : base(message)
{}
}
}

View File

@@ -0,0 +1,41 @@
namespace Quobject.EngineIoClientDotNet.Parser
{
internal class Buffer
{
private Buffer()
{
}
public static byte[] Concat(byte[][] list)
{
int length = 0;
foreach (var buf in list)
{
length += buf.Length;
}
return Concat(list, length);
}
public static byte[] Concat(byte[][] list, int length)
{
if (list.Length == 0)
{
return new byte[0];
}
if (list.Length == 1)
{
return list[0];
}
ByteBuffer buffer = ByteBuffer.Allocate(length);
foreach (var buf in list)
{
buffer.Put(buf);
}
return buffer.Array();
}
}
}

View File

@@ -0,0 +1,162 @@
using System;
using System.IO;
namespace Quobject.EngineIoClientDotNet.Parser
{
public class ByteBuffer
{
private readonly MemoryStream _memoryStream;
private long _limit = 0;
public ByteBuffer(int length)
{
this._memoryStream = new MemoryStream();
_memoryStream.SetLength(length);
_memoryStream.Capacity = length;
_limit = length;
}
public static ByteBuffer Allocate(int length)
{
return new ByteBuffer(length);
}
internal void Put(byte[] buf)
{
_memoryStream.Write(buf,0,buf.Length);
}
internal byte[] Array()
{
return _memoryStream.ToArray();
}
internal static ByteBuffer Wrap(byte[] data)
{
var result = new ByteBuffer(data.Length);
result.Put(data);
return result;
}
/// <summary>
/// A buffer's capacity is the number of elements it contains. The capacity of a
/// buffer is never negative and never changes.
/// </summary>
public int Capacity
{
get { return _memoryStream.Capacity; }
}
/// <summary>
/// Absolute get method. Reads the byte at the given index.
/// </summary>
/// <param name="index">The index from which the byte will be read</param>
/// <returns>The byte at the given index</returns>
internal byte Get(long index)
{
if (index > Capacity)
{
throw new IndexOutOfRangeException();
}
_memoryStream.Position = index;
return (byte) _memoryStream.ReadByte();
}
/// <summary>
/// Relative bulk get method.
///
/// This method transfers bytes from this buffer into the given destination array. If there are fewer bytes
/// remaining in the buffer than are required to satisfy the request, that is, if length > remaining(), then
/// no bytes are transferred and a BufferUnderflowException is thrown.
///
/// Otherwise, this method copies length bytes from this buffer into the given array, starting at the current
/// position of this buffer and at the given offset in the array. The position of this buffer is then
/// incremented by length.
///
/// In other words, an invocation of this method of the form src.get(dst, off, len) has exactly the same effect as the loop
/// <code>
/// for (int i = off; i &lt; off + len; i++)
/// dst[i] = src.get();
/// </code>
/// except that it first checks that there are sufficient bytes in this buffer and it is potentially much more efficient.
/// </summary>
/// <param name="dst"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <returns>This buffer</returns>
internal ByteBuffer Get(byte[] dst, int offset, int length)
{
_memoryStream.Read(dst, offset, length);
return this;
}
/// <summary>
/// Relative bulk get method.
///
/// This method transfers bytes from this buffer into the given destination array.
/// An invocation of this method of the form src.get(a) behaves in exactly the same
/// way as the invocation src.get(a, 0, a.length)
/// </summary>
/// <param name="dst"></param>
/// <returns>This buffer</returns>
internal ByteBuffer Get(byte[] dst)
{
return Get(dst, 0, dst.Length);
}
/// <summary>
/// Sets this buffer's position. If the mark is defined and larger than the new
/// position then it is discarded.
/// </summary>
/// <param name="newPosition">The new position value; must be non-negative and no larger than the current limit</param>
internal void Position(long newPosition)
{
_memoryStream.Position = newPosition;
}
/// <summary>
/// Sets this buffer's limit. If the position is larger than the new limit then it is set to the new limit.
/// If the mark is defined and larger than the new limit then it is discarded.
///
/// A buffer's limit is the index of the first element that should not be read or written. A buffer's limit is never negative and is never greater than its capacity.
/// </summary>
/// <param name="newLimit">The new limit value; must be non-negative and no larger than this buffer's capacity</param>
internal void Limit(long newLimit)
{
_limit = newLimit;
if (_memoryStream.Position > newLimit)
{
_memoryStream.Position = newLimit;
}
}
/// <summary>
/// Returns the number of elements between the current position and the limit.
/// </summary>
/// <returns>The number of elements remaining in this buffer</returns>
internal long Remaining()
{
return (_limit - _memoryStream.Position);
}
/// <summary>
/// Clears this buffer. The position is set to zero, the limit is set to the capacity, and the mark is discarded.
///
/// This method does not actually erase the data in the buffer, but it is named as if
/// it did because it will most often be used in situations in which that might as well be the case.
/// </summary>
internal void Clear()
{
Position(0);
Limit(Capacity);
}
}
}

View File

@@ -0,0 +1,9 @@

namespace Quobject.EngineIoClientDotNet.Parser
{
public interface IDecodePayloadCallback
{
bool Call(Packet packet, int index, int total);
}
}

View File

@@ -0,0 +1,9 @@

namespace Quobject.EngineIoClientDotNet.Parser
{
public interface IEncodeCallback
{
void Call(object data);
}
}

View File

@@ -0,0 +1,408 @@
using Quobject.EngineIoClientDotNet.Modules;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Quobject.EngineIoClientDotNet.Parser
{
/// <remarks>
/// Packet type which is ported from the JavaScript module.
/// This is the JavaScript parser for the engine.io protocol encoding,
/// shared by both engine.io-client and engine.io.
/// <see href="https://github.com/Automattic/engine.io-parser">https://github.com/Automattic/engine.io-parser</see>
/// </remarks>
public class Packet
{
public static readonly string OPEN = "open";
public static readonly string CLOSE = "close";
public static readonly string PING = "ping";
public static readonly string PONG = "pong";
public static readonly string UPGRADE = "upgrade";
public static readonly string MESSAGE = "message";
public static readonly string NOOP = "noop";
public static readonly string ERROR = "error";
private static readonly int MAX_INT_CHAR_LENGTH = int.MaxValue.ToString().Length;
//TODO: suport binary?
private bool SupportsBinary = false;
private static readonly Dictionary<string, byte> _packets = new Dictionary<string, byte>()
{
{Packet.OPEN, 0},
{Packet.CLOSE, 1},
{Packet.PING, 2},
{Packet.PONG, 3},
{Packet.MESSAGE, 4},
{Packet.UPGRADE, 5},
{Packet.NOOP, 6}
};
private static readonly Dictionary<byte, string> _packetsList = new Dictionary<byte, string>();
static Packet()
{
foreach (var entry in _packets)
{
_packetsList.Add(entry.Value,entry.Key);
}
}
private static readonly Packet _err = new Packet(Packet.ERROR,"parser error");
public string Type { get; set; }
public object Data { get; set; }
public Packet(string type, object data)
{
this.Type = type;
this.Data = data;
}
public Packet(string type)
{
this.Type = type;
this.Data = null;
}
internal void Encode(IEncodeCallback callback,bool utf8encode = false)
{
if ( Data is byte[])
{
if (!SupportsBinary)
{
EncodeBase64Packet(callback);
return;
}
EncodeByteArray(callback);
return;
}
var encodedStringBuilder = new StringBuilder();
encodedStringBuilder.Append(_packets[Type]);
if (Data != null)
{
encodedStringBuilder.Append( utf8encode ? UTF8.Encode((string) Data): (string)Data);
}
callback.Call(encodedStringBuilder.ToString());
}
private void EncodeBase64Packet(IEncodeCallback callback)
{
var byteData = Data as byte[];
if (byteData != null)
{
var result = new StringBuilder();
result.Append("b");
result.Append(_packets[Type]);
result.Append(Convert.ToBase64String(byteData));
callback.Call(result.ToString());
return;
}
throw new Exception("byteData == null");
}
private void EncodeByteArray(IEncodeCallback callback)
{
var byteData = Data as byte[];
if (byteData != null)
{
var resultArray = new byte[1 + byteData.Length];
resultArray[0] = _packets[Type];
Array.Copy(byteData, 0, resultArray, 1, byteData.Length);
callback.Call(resultArray);
return;
}
throw new Exception("byteData == null");
}
internal static Packet DecodePacket(string data, bool utf8decode = false)
{
if (data.StartsWith("b"))
{
return DecodeBase64Packet(data.Substring(1));
}
int type;
var s = data.Substring(0, 1);
if (!int.TryParse(s, out type))
{
type = -1;
}
if (utf8decode)
{
try
{
data = UTF8.Decode(data);
}
catch (Exception)
{
return _err;
}
}
if (type < 0 || type >= _packetsList.Count)
{
return _err;
}
if (data.Length > 1)
{
return new Packet(_packetsList[(byte) type], data.Substring(1));
}
return new Packet(_packetsList[(byte) type], null);
}
private static Packet DecodeBase64Packet(string msg)
{
int type;
var s = msg.Substring(0, 1);
if (!int.TryParse(s, out type))
{
type = -1;
}
if (type < 0 || type >= _packetsList.Count)
{
return _err;
}
msg = msg.Substring(1);
byte[] decodedFromBase64 = Convert.FromBase64String(msg);
return new Packet(_packetsList[(byte)type], decodedFromBase64);
}
internal static Packet DecodePacket(byte[] data)
{
int type = data[0];
var byteArray = new byte[data.Length - 1];
Array.Copy(data,1,byteArray,0, byteArray.Length);
return new Packet(_packetsList[(byte)type], byteArray);
}
internal static void EncodePayload(Packet[] packets, IEncodeCallback callback)
{
if (packets.Length == 0)
{
callback.Call(new byte[0]);
return;
}
var results = new List<byte[]>(packets.Length);
var encodePayloadCallback = new EncodePayloadCallback(results);
foreach (var packet in packets)
{
packet.Encode(encodePayloadCallback, true);
}
callback.Call(Buffer.Concat(results.ToArray()));//new byte[results.Count][]
}
/// <summary>
/// Decodes data when a payload is maybe expected.
/// </summary>
/// <param name="data"></param>
/// <param name="callback"></param>
public static void DecodePayload(string data, IDecodePayloadCallback callback)
{
if (String.IsNullOrEmpty(data))
{
callback.Call(_err, 0, 1);
return;
}
var length = new StringBuilder();
for (int i = 0, l = data.Length; i < l; i++)
{
var chr = Convert.ToChar(data.Substring(i, 1));
if (chr != ':')
{
length.Append(chr);
}
else
{
int n;
if (!int.TryParse(length.ToString(), out n))
{
callback.Call(_err, 0, 1);
return;
}
string msg;
try
{
msg = data.Substring(i + 1, n);
}
catch (ArgumentOutOfRangeException)
{
callback.Call(_err, 0, 1);
return;
}
if (msg.Length != 0)
{
Packet packet = DecodePacket(msg, true);
if (_err.Type == packet.Type && _err.Data == packet.Data)
{
callback.Call(_err, 0, 1);
return;
}
bool ret = callback.Call(packet, i + n, l);
if (!ret)
{
return;
}
}
i += n;
length = new StringBuilder();
}
}
if (length.Length > 0)
{
callback.Call(_err, 0, 1);
}
}
/// <summary>
/// Decodes data when a payload is maybe expected.
/// </summary>
/// <param name="data"></param>
/// <param name="callback"></param>
public static void DecodePayload(byte[] data, IDecodePayloadCallback callback)
{
var bufferTail = ByteBuffer.Wrap(data);
var buffers = new List<object>();
int bufferTail_offset = 0;
while (bufferTail.Capacity - bufferTail_offset > 0)
{
var strLen = new StringBuilder();
var isString = (bufferTail.Get(0 + bufferTail_offset) & 0xFF) == 0;
var numberTooLong = false;
for (int i = 1;; i++)
{
int b = bufferTail.Get(i + bufferTail_offset) & 0xFF;
if (b == 255)
{
break;
}
// support only integer
if (strLen.Length > MAX_INT_CHAR_LENGTH)
{
numberTooLong = true;
break;
}
strLen.Append(b);
}
if (numberTooLong)
{
callback.Call(_err, 0, 1);
return;
}
bufferTail_offset += strLen.Length + 1;
int msgLength = int.Parse(strLen.ToString());
bufferTail.Position(1 + bufferTail_offset);
bufferTail.Limit(msgLength + 1 + bufferTail_offset);
var msg = new byte[bufferTail.Remaining()];
bufferTail.Get(msg, 0, msg.Length);
if (isString)
{
buffers.Add(ByteArrayToString(msg));
}
else
{
buffers.Add(msg);
}
bufferTail.Clear();
bufferTail.Position(msgLength + 1 + bufferTail_offset);
bufferTail_offset += msgLength + 1;
}
var total = buffers.Count;
for (int i = 0; i < total; i++)
{
var buffer = buffers[i];
if (buffer is string)
{
callback.Call(DecodePacket((string) buffer, true), i, total);
}
else if (buffer is byte[])
{
callback.Call(DecodePacket((byte[])buffer), i, total);
}
}
}
internal static byte[] StringToByteArray(string str)
{
int len = str.Length;
var bytes = new byte[len];
for (int i = 0; i < len; i++)
{
bytes[i] = (byte)str[i];
}
return bytes;
}
internal static string ByteArrayToString(byte[] bytes)
{
//return Encoding.ASCII.GetString(bytes);
//http://stackoverflow.com/questions/7750850/encoding-ascii-getstring-in-windows-phone-platform
return string.Concat(bytes.Select(b => b <= 0x7f ? (char)b : '?'));
}
private class EncodePayloadCallback : IEncodeCallback
{
private readonly List<byte[]> _results;
public EncodePayloadCallback(List<byte[]> results)
{
this._results = results;
}
public void Call(object data)
{
if (data is string)
{
var packet = (string) data;
var encodingLength = packet.Length.ToString();
var sizeBuffer = new byte[encodingLength.Length + 2];
sizeBuffer[0] = (byte) 0; // is a string
for (var i = 0; i < encodingLength.Length; i++)
{
sizeBuffer[i + 1] = byte.Parse(encodingLength.Substring(i,1));
}
sizeBuffer[sizeBuffer.Length - 1] = (byte) 255;
_results.Add(Buffer.Concat(new byte[][] { sizeBuffer, StringToByteArray(packet) }));
return;
}
var packet1 = (byte[]) data;
var encodingLength1 = packet1.Length.ToString();
var sizeBuffer1 = new byte[encodingLength1.Length + 2];
sizeBuffer1[0] = (byte)1; // is binary
for (var i = 0; i < encodingLength1.Length; i++)
{
sizeBuffer1[i + 1] = byte.Parse(encodingLength1.Substring(i, 1));
}
sizeBuffer1[sizeBuffer1.Length - 1] = (byte)255;
_results.Add(Buffer.Concat(new byte[][] { sizeBuffer1, packet1 }));
}
}
}
}

View File

@@ -0,0 +1,412 @@
using Quobject.EngineIoClientDotNet.Modules;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Quobject.EngineIoClientDotNet.Parser
{
/// <remarks>
/// Packet type which is ported from the JavaScript module.
/// This is the JavaScript parser for the engine.io protocol encoding,
/// shared by both engine.io-client and engine.io.
/// <see href="https://github.com/Automattic/engine.io-parser">https://github.com/Automattic/engine.io-parser</see>
/// </remarks>
public class Packet
{
public static readonly string OPEN = "open";
public static readonly string CLOSE = "close";
public static readonly string PING = "ping";
public static readonly string PONG = "pong";
public static readonly string UPGRADE = "upgrade";
public static readonly string MESSAGE = "message";
public static readonly string NOOP = "noop";
public static readonly string ERROR = "error";
private static readonly int MAX_INT_CHAR_LENGTH = int.MaxValue.ToString().Length;
//TODO: suport binary?
private bool SupportsBinary = false;
private static readonly Dictionary<string, byte> _packets = new Dictionary<string, byte>()
{
{Packet.OPEN, 0},
{Packet.CLOSE, 1},
{Packet.PING, 2},
{Packet.PONG, 3},
{Packet.MESSAGE, 4},
{Packet.UPGRADE, 5},
{Packet.NOOP, 6}
};
private static readonly Dictionary<byte, string> _packetsList = new Dictionary<byte, string>();
static Packet()
{
foreach (var entry in _packets)
{
_packetsList.Add(entry.Value,entry.Key);
}
}
private static readonly Packet _err = new Packet(Packet.ERROR,"parser error");
public string Type { get; set; }
public object Data { get; set; }
public Packet(string type, object data)
{
this.Type = type;
this.Data = data;
}
public Packet(string type)
{
this.Type = type;
this.Data = null;
}
internal void Encode(IEncodeCallback callback,bool utf8encode = false)
{
if ( Data is byte[])
{
if (!SupportsBinary)
{
EncodeBase64Packet(callback);
return;
}
EncodeByteArray(callback);
return;
}
var encodedStringBuilder = new StringBuilder();
encodedStringBuilder.Append(_packets[Type]);
if (Data != null)
{
encodedStringBuilder.Append( utf8encode ? UTF8.Encode((string) Data): (string)Data);
}
callback.Call(encodedStringBuilder.ToString());
}
private void EncodeBase64Packet(IEncodeCallback callback)
{
var byteData = Data as byte[];
if (byteData != null)
{
var result = new StringBuilder();
result.Append("b");
result.Append(_packets[Type]);
result.Append(Convert.ToBase64String(byteData));
callback.Call(result.ToString());
return;
}
throw new Exception("byteData == null");
}
private void EncodeByteArray(IEncodeCallback callback)
{
var byteData = Data as byte[];
if (byteData != null)
{
var resultArray = new byte[1 + byteData.Length];
resultArray[0] = _packets[Type];
Array.Copy(byteData, 0, resultArray, 1, byteData.Length);
callback.Call(resultArray);
return;
}
throw new Exception("byteData == null");
}
internal static Packet DecodePacket(string data, bool utf8decode = false)
{
if (data.StartsWith("b"))
{
return DecodeBase64Packet(data.Substring(1));
}
int type;
var s = data.Substring(0, 1);
if (!int.TryParse(s, out type))
{
type = -1;
}
if (utf8decode)
{
try
{
data = UTF8.Decode(data);
}
catch (Exception)
{
return _err;
}
}
if (type < 0 || type >= _packetsList.Count)
{
return _err;
}
if (data.Length > 1)
{
return new Packet(_packetsList[(byte) type], data.Substring(1));
}
return new Packet(_packetsList[(byte) type], null);
}
private static Packet DecodeBase64Packet(string msg)
{
int type;
var s = msg.Substring(0, 1);
if (!int.TryParse(s, out type))
{
type = -1;
}
if (type < 0 || type >= _packetsList.Count)
{
return _err;
}
msg = msg.Substring(1);
byte[] decodedFromBase64 = Convert.FromBase64String(msg);
return new Packet(_packetsList[(byte)type], decodedFromBase64);
}
internal static Packet DecodePacket(byte[] data)
{
int type = data[0];
var byteArray = new byte[data.Length - 1];
Array.Copy(data,1,byteArray,0, byteArray.Length);
return new Packet(_packetsList[(byte)type], byteArray);
}
internal static void EncodePayload(Packet[] packets, IEncodeCallback callback)
{
if (packets.Length == 0)
{
callback.Call(new byte[0]);
return;
}
var results = new List<byte[]>(packets.Length);
var encodePayloadCallback = new EncodePayloadCallback(results);
foreach (var packet in packets)
{
packet.Encode(encodePayloadCallback, true);
}
callback.Call(Buffer.Concat(results.ToArray()));//new byte[results.Count][]
}
/// <summary>
/// Decodes data when a payload is maybe expected.
/// </summary>
/// <param name="data"></param>
/// <param name="callback"></param>
public static void DecodePayload(string data, IDecodePayloadCallback callback)
{
if (String.IsNullOrEmpty(data))
{
callback.Call(_err, 0, 1);
return;
}
var length = new StringBuilder();
for (int i = 0, l = data.Length; i < l; i++)
{
var chr = Convert.ToChar(data.Substring(i, 1));
if (chr != ':')
{
length.Append(chr);
}
else
{
int n;
if (!int.TryParse(length.ToString(), out n))
{
callback.Call(_err, 0, 1);
return;
}
string msg;
try
{
msg = data.Substring(i + 1, n);
}
catch (ArgumentOutOfRangeException)
{
callback.Call(_err, 0, 1);
return;
}
if (msg.Length != 0)
{
Packet packet = DecodePacket(msg, true);
if (_err.Type == packet.Type && _err.Data == packet.Data)
{
callback.Call(_err, 0, 1);
return;
}
bool ret = callback.Call(packet, i + n, l);
if (!ret)
{
return;
}
}
i += n;
length = new StringBuilder();
}
}
if (length.Length > 0)
{
callback.Call(_err, 0, 1);
}
}
/// <summary>
/// Decodes data when a payload is maybe expected.
/// </summary>
/// <param name="data"></param>
/// <param name="callback"></param>
public static void DecodePayload(byte[] data, IDecodePayloadCallback callback)
{
var bufferTail = ByteBuffer.Wrap(data);
var buffers = new List<object>();
int bufferTail_offset = 0;
while (bufferTail.Capacity - bufferTail_offset > 0)
{
var strLen = new StringBuilder();
var isString = (bufferTail.Get(0 + bufferTail_offset) & 0xFF) == 0;
var numberTooLong = false;
for (int i = 1;; i++)
{
int b = bufferTail.Get(i + bufferTail_offset) & 0xFF;
if (b == 255)
{
break;
}
// support only integer
if (strLen.Length > MAX_INT_CHAR_LENGTH)
{
numberTooLong = true;
break;
}
strLen.Append(b);
}
if (numberTooLong)
{
callback.Call(_err, 0, 1);
return;
}
bufferTail_offset += strLen.Length + 1;
int msgLength = int.Parse(strLen.ToString());
bufferTail.Position(1 + bufferTail_offset);
bufferTail.Limit(msgLength + 1 + bufferTail_offset);
var msg = new byte[bufferTail.Remaining()];
bufferTail.Get(msg, 0, msg.Length);
if (isString)
{
buffers.Add(ByteArrayToString(msg));
}
else
{
buffers.Add(msg);
}
bufferTail.Clear();
bufferTail.Position(msgLength + 1 + bufferTail_offset);
bufferTail_offset += msgLength + 1;
}
var total = buffers.Count;
for (int i = 0; i < total; i++)
{
var buffer = buffers[i];
if (buffer is string)
{
callback.Call(DecodePacket((string) buffer, true), i, total);
}
else if (buffer is byte[])
{
callback.Call(DecodePacket((byte[])buffer), i, total);
}
}
}
internal static byte[] StringToByteArray(string str)
{
int len = str.Length;
var bytes = new byte[len];
for (int i = 0; i < len; i++)
{
bytes[i] = (byte)str[i];
}
return bytes;
}
internal static string ByteArrayToString(byte[] bytes)
{
//return Encoding.ASCII.GetString(bytes);
//http://stackoverflow.com/questions/7750850/encoding-ascii-getstring-in-windows-phone-platform
// return string.Concat(bytes.Select(b => b <= 0x7f ? (char)b : '?')); //.net 4.0 only
return string.Concat(
(bytes.Select(b => (b <= 0x7f ? (char) b : '?').ToString()))
.ToArray()
);
}
private class EncodePayloadCallback : IEncodeCallback
{
private readonly List<byte[]> _results;
public EncodePayloadCallback(List<byte[]> results)
{
this._results = results;
}
public void Call(object data)
{
if (data is string)
{
var packet = (string) data;
var encodingLength = packet.Length.ToString();
var sizeBuffer = new byte[encodingLength.Length + 2];
sizeBuffer[0] = (byte) 0; // is a string
for (var i = 0; i < encodingLength.Length; i++)
{
sizeBuffer[i + 1] = byte.Parse(encodingLength.Substring(i,1));
}
sizeBuffer[sizeBuffer.Length - 1] = (byte) 255;
_results.Add(Buffer.Concat(new byte[][] { sizeBuffer, StringToByteArray(packet) }));
return;
}
var packet1 = (byte[]) data;
var encodingLength1 = packet1.Length.ToString();
var sizeBuffer1 = new byte[encodingLength1.Length + 2];
sizeBuffer1[0] = (byte)1; // is binary
for (var i = 0; i < encodingLength1.Length; i++)
{
sizeBuffer1[i + 1] = byte.Parse(encodingLength1.Substring(i, 1));
}
sizeBuffer1[sizeBuffer1.Length - 1] = (byte)255;
_results.Add(Buffer.Concat(new byte[][] { sizeBuffer1, packet1 }));
}
}
}
}

View File

@@ -0,0 +1,51 @@

namespace Quobject.EngineIoClientDotNet.Parser
{
/// <remarks>
/// This is the JavaScript parser for the engine.io protocol encoding,
/// shared by both engine.io-client and engine.io.
/// <see href="https://github.com/Automattic/engine.io-parser">https://github.com/Automattic/engine.io-parser</see>
/// </remarks>
public class Parser
{
public static readonly int Protocol = 3;
private Parser()
{
}
public static void EncodePacket(Packet packet, IEncodeCallback callback)
{
packet.Encode(callback);
}
public static Packet DecodePacket(string data, bool utf8decode = false)
{
return Packet.DecodePacket(data, utf8decode);
}
public static Packet DecodePacket(byte[] data)
{
return Packet.DecodePacket(data);
}
public static void EncodePayload(Packet[] packets, IEncodeCallback callback)
{
Packet.EncodePayload(packets, callback);
}
public static void DecodePayload(string data, IDecodePayloadCallback callback)
{
Packet.DecodePayload(data, callback);
}
public static void DecodePayload(byte[] data, IDecodePayloadCallback callback)
{
Packet.DecodePayload(data, callback);
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("EngineIoClientDotNet")]
[assembly: AssemblyDescription("Engine.IO Client Library for .Net")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Quobject Software")]
[assembly: AssemblyProduct("EngineIoClientDotNet")]
[assembly: AssemblyCopyright("Copyright © 2014")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("a95e75cd-35e6-4e88-9e22-631e3fd01546")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.9.4")]
[assembly: AssemblyFileVersion("0.9.4")]

View File

@@ -0,0 +1,62 @@

using System;
using System.Threading;
using System.Threading.Tasks;
namespace Quobject.EngineIoClientDotNet.Thread
{
public class EasyTimer
{
private CancellationTokenSource ts;
public EasyTimer(CancellationTokenSource ts)
{
this.ts = ts;
}
public static EasyTimer SetTimeout(Action method, int delayInMilliseconds)
{
var ts = new CancellationTokenSource();
CancellationToken ct = ts.Token;
var task = Task.Delay(delayInMilliseconds,ct);
var awaiter = task.GetAwaiter();
awaiter.OnCompleted(
() =>
{
if (!ts.IsCancellationRequested)
{
method();
}
});
// Returns a stop handle which can be used for stopping
// the timer, if required
return new EasyTimer(ts);
}
public void Stop()
{
//var log = LogManager.GetLogger(Global.CallerName());
//log.Info("EasyTimer stop");
if (ts != null)
{
ts.Cancel();
}
}
public static void TaskRun(Action action)
{
Task.Run(action).Wait();
}
public static void TaskRunNoWait(Action action)
{
Task.Run(action);
}
}
}

View File

@@ -0,0 +1,76 @@

using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Quobject.EngineIoClientDotNet.Modules;
using System;
namespace Quobject.EngineIoClientDotNet.Thread
{
public class EasyTimer
{
private CancellationTokenSource ts;
public EasyTimer(CancellationTokenSource ts)
{
this.ts = ts;
}
public static EasyTimer SetTimeout(Action method, int delayInMilliseconds)
{
var ts = new CancellationTokenSource();
var ct = ts.Token;
var worker = new BackgroundWorker();
worker.DoWork += (s, e) => System.Threading.Thread.Sleep(delayInMilliseconds);
worker.RunWorkerCompleted += (s, e) =>
{
if (!ts.IsCancellationRequested)
{
Task.Factory.StartNew(method, ct, TaskCreationOptions.None, TaskScheduler.Default);
}
};
worker.RunWorkerAsync();
// Returns a stop handle which can be used for stopping
// the timer, if required
return new EasyTimer(ts);
}
public void Stop()
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("EasyTimer stop");
if (ts != null)
{
ts.Cancel();
}
}
public static void TaskRun(Action action)
{
Task.Run(action).Wait();
}
public static Task TaskRunNoWait(Action action)
{
return Task.Run(action);
}
}
}

View File

@@ -0,0 +1,88 @@

using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Quobject.EngineIoClientDotNet.Modules;
using System;
namespace Quobject.EngineIoClientDotNet.Thread
{
public class EasyTimer
{
private CancellationTokenSource ts;
public EasyTimer(CancellationTokenSource ts)
{
this.ts = ts;
}
public static EasyTimer SetTimeout(Action method, int delayInMilliseconds)
{
var ts = new CancellationTokenSource();
var ct = ts.Token;
var worker = new BackgroundWorker();
worker.DoWork += (s, e) => System.Threading.Thread.Sleep(delayInMilliseconds);
worker.RunWorkerCompleted += (s, e) =>
{
if (!ts.IsCancellationRequested)
{
Task.Factory.StartNew(method, ct, TaskCreationOptions.None, TaskScheduler.Default);
}
};
worker.RunWorkerAsync();
// Returns a stop handle which can be used for stopping
// the timer, if required
return new EasyTimer(ts);
}
public void Stop()
{
var log = LogManager.GetLogger(Global.CallerName());
log.Info("EasyTimer stop");
if (ts != null)
{
ts.Cancel();
}
}
public static void TaskRun(Action action)
{
var t = new Task(action);
t.RunSynchronously();
if (t.IsFaulted)
{
if (t.Exception != null)
{
throw t.Exception;
}
throw new Exception();
}
//Task.Run(action).Wait();
}
public static Task TaskRunNoWait(Action action)
{
var t = new Task(action);
t.Start();
return t;
}
}
}

View File

@@ -0,0 +1,55 @@
using System;
using System.ComponentModel;
using System.Threading;
namespace Quobject.EngineIoClientDotNet.Thread
{
public class Heartbeat
{
private volatile bool gotHeartbeat = false;
private BackgroundWorker heartBeatTimer;
private CancellationTokenSource ts;
private Heartbeat()
{
ts = new CancellationTokenSource();
}
public static Heartbeat Start(Action onTimeout, int timeout)
{
Heartbeat heartbeat = new Heartbeat();
heartbeat.Run(onTimeout, timeout);
return heartbeat;
}
public void OnHeartbeat()
{
gotHeartbeat = true;
}
private void Run(Action onTimeout, int timeout)
{
heartBeatTimer = new BackgroundWorker();
heartBeatTimer.DoWork += (s, e) =>
{
while (!ts.IsCancellationRequested)
{
System.Threading.Thread.Sleep(timeout);
if (!gotHeartbeat && !ts.IsCancellationRequested)
{
onTimeout();
break;
}
}
};
heartBeatTimer.RunWorkerAsync();
}
public void Stop()
{
ts.Cancel();
}
}
}

View File

@@ -0,0 +1,61 @@
using System;
using System.ComponentModel;
using System.Threading;
namespace Quobject.EngineIoClientDotNet.Thread
{
public class TriggeredLoopTimer
{
private ManualResetEvent trigger;
private CancellationTokenSource ts;
private TriggeredLoopTimer()
{
trigger = new ManualResetEvent(false);
ts = new CancellationTokenSource();
}
public static TriggeredLoopTimer Start (Action method, int delayInMilliseconds)
{
TriggeredLoopTimer ping = new TriggeredLoopTimer();
ping.Run (method, delayInMilliseconds);
return ping;
}
public void Trigger()
{
trigger.Set();
}
private void Run (Action method, int delayInMilliseconds)
{
var worker = new BackgroundWorker();
worker.DoWork += (s, e) =>
{
while (!ts.IsCancellationRequested)
{
System.Threading.Thread.Sleep (delayInMilliseconds);
if (!ts.IsCancellationRequested)
{
method();
trigger.WaitOne();
trigger.Reset();
}
}
};
worker.RunWorkerAsync();
}
public void Stop()
{
if (ts != null)
{
ts.Cancel();
trigger.Set();
}
}
}
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="10.0.1" targetFramework="net45" />
<package id="SuperSocket.ClientEngine.Core" version="0.8.0.8" targetFramework="net45" />
<package id="WebSocket4Net" version="0.15.0-beta6" targetFramework="net45" />
</packages>