This is a fork of EngineIOSharp:master with additional support for socket connection pre-processing!
using (EngineIOServer server = new EngineIOServer(new EngineIOServerOption(1009, AllowEIO3: true, VerificationTimeout: 1001)))
{
Console.WriteLine("Listening on " + server.Option.Port);
server.OnConnecting((obj) =>
{
var token = obj.Item1["token2"];
if (string.IsNullOrWhiteSpace(token))
{
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff} The authentication fails and the connection is denied");
}
server.VerificationResult.TryAdd(obj.Item2, string.IsNullOrWhiteSpace(token));
});
server.OnConnection((socket) =>
{
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff} Client connected!");
});
server.Start();
}
1.EngineIOSharp/Server/EngineIOServer.Exceptions.cs
public static readonly EngineIOException CONNECTIONREFUSED = new EngineIOException("ConnectionRefused");//401/403
private static readonly EngineIOException[] VALUES = new EngineIOException[] { CONNECTIONREFUSED }
2.EngineIOSharp/Server/EngineIOServer.Event.cs
public EngineIOServer OnConnecting(Action<Tuple<System.Collections.Specialized.NameValueCollection, string>> Callback)
{
return On(Event.CONNECTING, (Client) => Callback(Client as Tuple<System.Collections.Specialized.NameValueCollection, string>));
}
public static class Event
{
public static readonly string CONNECTING = "connecting";
}
3.EngineIOSharp/Common/Static/EngineIOHttpManager.cs
public static void SendErrorMessage(HttpListenerRequest Request, HttpListenerResponse Response, EngineIOException Exception)
{
using (Response)
{
......
if (EngineIOServer.Exceptions.Contains(Exception))
{
......
Response.StatusCode = 400;
Response.Headers["ServerResponse"] = Message;
Response.StatusCode = Exception == EngineIOServer.Exceptions.CONNECTIONREFUSED ? 401 : 400;
}
else
{
......
}
......
}
}
4.EngineIOSharp/Server/EngineIOServerOption.cs
public ulong VerificationTimeout { get; private set; }
public EngineIOServerOption(ulong VerificationTimeout = 1000)
{
this.VerificationTimeout = VerificationTimeout;
}
5.EngineIOSharp/Server/EngineIOServer.cs
/// <summary>
/// Verification result: If no entry is made within 1000ms, it is regarded as passed
/// </summary>
public readonly ConcurrentDictionary<string, bool> VerificationResult = new ConcurrentDictionary<string, bool>();
private EngineIOException Verify(NameValueCollection QueryString, NameValueCollection Headers, EngineIOTransportType ExpectedTransportType)
{
......
else if (EngineIOHttpManager.GetTransport(QueryString).Equals(ExpectedTransportType.ToString()))
{
......
if (IsPolling || IsWebSocket)
{
if (EngineIOHttpManager.IsValidHeader(EngineIOHttpManager.GetOrigin(Headers)))
{
Exception = null;
#region connection verification
if (string.IsNullOrWhiteSpace(EngineIOHttpManager.GetSID(QueryString)))
{
var abortId = $"{QueryString}&k={DateTime.Now.Ticks}";
Emit(Event.CONNECTING, new Tuple<NameValueCollection, string>(Headers, abortId));
#if NET45_OR_GREATER
//var task = System.Threading.Tasks.Task.Run(() => { while (!VerificationResult.ContainsKey(abortId)) { continue; } });
//System.Threading.Tasks.Task.WaitAny(new System.Threading.Tasks.Task[] { task }, TimeSpan.FromMilliseconds(Option.VerificationTimeout));
var cts = new System.Threading.CancellationTokenSource(TimeSpan.FromMilliseconds(Option.VerificationTimeout));
while (!VerificationResult.ContainsKey(abortId) && !cts.IsCancellationRequested) { continue; }
#else
var cts = new System.Threading.CancellationTokenSource();
var waitTimer = new System.Timers.Timer(Option.VerificationTimeout) { AutoReset = false };
waitTimer.Elapsed += (aa, bb) => cts.Cancel();
waitTimer.Start();
while (!VerificationResult.ContainsKey(abortId) && !cts.IsCancellationRequested) { continue; }
#endif
if (VerificationResult.TryGetValue(abortId, out var result))
{
VerificationResult.TryRemove(abortId, out _);
if (result) Exception = Exceptions.CONNECTIONREFUSED;
}
}
#endregion
}
else
{
Exception = Exceptions.BAD_REQUEST;
}
}
}
return Exception;
}
EngineIOSharp
is a Engine.IO Protocol revision 4
client and server library based on WebSocket
or Long-Polling
transport. It depends on WebSocketSharp to use WebSocket
transport. Long-Polling
transport is implemented by itself.
-
Command
Install-Package EngineIOIOSharp2
in nuget package manager console.
using EngineIOSharp.Client;
using EngineIOSharp.Common.Enum;
EngineIOClient client = new EngineIOClient(new EngineIOClientOption(EngineIOScheme.http, "localhost", 1009)));
-
Essential Parameters
-
Scheme
: Scheme to connect to. It can beEngineIOScheme.http
orEngineIOScheme.https
. Internally, it supportsws
andwss
. -
Host
: Host to connect to. -
Port
: Port to connect to.
-
-
Optional Parameters
-
PolicyPort
: Port the policy server listens on. Defaults to843
. -
Path
: Path to connect to. Defaults to"/engine.io"
. -
Query
: Parameters that will be passed for each request to the server. Defaults tonull
. -
Upgrade
: Whether the client should try to upgrade the transport. Defaults totrue
. -
RemeberUpgrade
: Whether the client should bypass normal upgrade process when previous websocket connection is succeeded. Defaults tofalse
. -
ForceBase64
: Forces base 64 encoding for transport. Defaults tofalse
. -
WithCredentials
: Whether to include credentials such as cookies, authorization headers, TLS client certificates, etc. with polling requests. Defaults tofalse
. -
TimestampRequests
: Whether to add the timestamp with each transport request. Polling requests are always stamped. Defaults tonull
. -
TimestampParam
: Timestamp parameter. Defaults to"t"
. -
Polling
: Whether to include polling transport. Defaults totrue
. -
PollingTimeout
: Timeout for polling requests in milliseconds. Defaults to0
, which waits indefinitely. -
WebSocket
: Whether to include websocket transport. Defaults totrue
. -
WebSocketSubprotocols
: List of websocket subprotocols. Defaults tonull
. -
ExtraHeaders
: Headers that will be passed for each request to the server. Defaults tonull
. -
ClientCertificates
: The collection of security certificates that are associated with each request. Defaults tonull
. -
ClientCertificateSelectionCallback
: Callback used to select the certificate to supply to the server. Defaults tonull
. -
ServerCertificateValidationCallback
: Callback method to validate the server certificate. Defaults tonull
and server certificate will be always validated.
-
client.Connect();
client.Close();
or
client.Dispose();
Since EngineIOClient
implements IDisposable
interface, it will be automatically disconnected when EngineIOClient.Dispose
is called.
For convenient usage, it is implemented to can be used as Javascript
style.
client.OnOpen(() =>
{
Console.WriteLine("Conencted!");
});
client.OnMessage((Packet) =>
{
Console.WriteLine("Server : " + Packet.Data);
});
client.OnClose((Exception Description) =>
{
Console.WriteLine("Disconnected!");
if (Description != null)
{
Console.WriteLine(Description);
}
});
client.On(EngineIOClient.Event.FLUSH, () =>
{
Console.WriteLine("Flushed!");
});
public static class Event
{
public static readonly string OPEN = "open";
public static readonly string HANDSHAKE = "handshake";
public static readonly string ERROR = "error";
public static readonly string CLOSE = "close";
public static readonly string PACKET = "packet";
public static readonly string MESSAGE = "message";
public static readonly string PACKET_CREATE = "packetCreate";
public static readonly string FLUSH = "flush";
public static readonly string DRAIN = "drain";
public static readonly string UPGRADE = "upgrade";
public static readonly string UPGRADING = "upgrading";
public static readonly string UPGRADE_ERROR = "upgradeError";
}
These are the common basic Engine.IO
events.
client.Send("This is string value.");
client.Send("String value with callback.", () => Console.WriteLine("Flushed!"));
client.send(new byte[] { 1, 2, 3, 4, 5 });
client.send(new byte[] { 6, 7, 8, 9, 0 }, () => Console.WriteLine("Bytes flushed!"));
using EngineIOSharp.Server;
EngineIOServer server = new EngineIOServer(new EngineIOServerOption(1009));
-
Essential Parameters
Port
: Port to listen.
-
Optional Parameters
-
Path
: Path to listen. Defaults to"/engine.io"
. -
Secure
: Whether to secure connections. Defatuls tofalse
. -
PingTimeout
: How many ms without a pong packet to consider the connection closed. Defatuls to5000
. -
PingInterval
: How many ms before sending a new ping packet. Defatuls to25000
. -
UpgradeTimeout
: How many ms before an uncompleted transport upgrade is cancelled. Defatuls to10000
. -
Polling
: Whether to accept polling transport. Defatuls totrue
. -
WebSocket
: Whether to accept websocket transport. Defatuls totrue
. -
AllowUpgrade
: Whether to allow transport upgrade. Defatuls totrue
. -
SetCookie
: Whether to use cookie. Defatuls totrue
. -
SIDCookieName
: Name of sid cookie. Defatuls to"io"
. -
Cookies
: Configuration of the cookie that contains the client sid to send as part of handshake response headers. This cookie might be used for sticky-session. Defatuls tonull
. -
AllowHttpRequest
: A function that receives a given handshake or upgrade http request as its first parameter, and can decide whether to continue or not. Defatuls tonull
. -
AllowWebSocket
: A function that receives a given handshake or upgrade websocket connection as its first parameter, and can decide whether to continue or not. Defatuls tonull
. -
InitialData
: An optional packet which will be concatenated to the handshake packet emitted by Engine.IO. Defatuls tonull
. -
ServerCertificate
: The certificate used to authenticate the server. Defatuls tonull
. -
ClientCertificateValidationCallback
: Callback used to validate the certificate supplied by the client. Defatuls tonull
and client certificate will be always validated.
-
server.Start();
server.Stop();
or
server.Dispose();
Since EngineIOServer
implements IDisposable
interface, it will be automatically stoped when EngineIOServer.Dispose
is called.
For convenient usage, it is implemented to can be used as Javascript
style.
server.OnConnection((EngineIOSocket socket) =>
{
Console.WriteLine("Client connected!");
socket.OnMessage((Packet) =>
{
Console.WriteLine(Packet.Data);
if (Packet.IsText)
{
socket.Send(Packet.Data);
}
else
{
socket.Send(Packet.RawData);
}
});
socket.OnClose(() =>
{
Console.WriteLine("Client disconnected!");
});
socket.Send("Hello client!");
socket.Send(new byte[] { 0, 1, 2, 3, 4, 5, 6 });
});
EngineIOSocket
is a type of parameter inEngineIOServer.OnConnection
event callback. It can be used similarly asEngineIOClient
.
socket.Close();
or
socket.Dispose();
Since EngineIOSocket
implements IDisposable
interface, it will be automatically disconnected when EngineIOSocket.Dispose
is called.
For convenient usage, it is implemented to can be used as Javascript
style.
socket.OnMessage((Packet) =>
{
Console.WriteLine("Server : " + Packet.Data);
});
socket.OnClose((string Messsage, Exception Description) =>
{
Console.WriteLine("Disconnected!");
if (Message != null)
{
Console.WriteLine(Message);
}
if (Description != null)
{
Console.WriteLine(Description);
}
});
socket.On(EngineIOSocket.Event.FLUSH, () =>
{
Console.WriteLine("Flushed!");
});
- There is no
EngineIOSocket.OnOpen
event since it is already opened whenEngineIOServer.OnConnection
event callback is called.
public static class Event
{
public static readonly string OPEN = "open";
public static readonly string HEARTBEAT = "heartbeat";
public static readonly string ERROR = "error";
public static readonly string CLOSE = "close";
public static readonly string PACKET = "packet";
public static readonly string MESSAGE = "message";
public static readonly string PACKET_CREATE = "packetCreate";
public static readonly string FLUSH = "flush";
public static readonly string DRAIN = "drain";
public static readonly string UPGRADE = "upgrade";
public static readonly string UPGRADING = "upgrading";
public static readonly string UPGRADE_ERROR = "upgradeError";
}
socket.Send("This is string value.");
socket.Send("String value with callback.", () => Console.WriteLine("Flushed!"));
socket.send(new byte[] { 1, 2, 3, 4, 5 });
socket.send(new byte[] { 6, 7, 8, 9, 0 }, () => Console.WriteLine("Bytes flushed!"));
server.Braodcast("This is string value.");
server.Braodcast("String value with callback.", () => Console.WriteLine("Braodcasted!"));
server.Braodcast(new byte[] { 1, 2, 3, 4, 5 });
server.Braodcast(new byte[] { 6, 7, 8, 9, 0 }, () => Console.WriteLine("Bytes braodcasted!"));
Welcome to report issue or create pull request. I will check it happily.
- WebSocketSharp.CustomHeaders.CustomHttpServer v1.0.2.3
- SimpleThreadMonitor v1.0.2.1
- Newtonsoft.Json v9.0.1
- EmitterSharp v1.1.1.1
EngineIOSharp
is under The MIT License.