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,181 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
Releases
Working
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
x64/
build/
bld/
[Bb]in/
[Oo]bj/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
#NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
*.ncrunch*
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# NuGet Packages Directory
packages/
## TODO: If the tool you use requires repositories.config uncomment the next line
#!packages/repositories.config
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented)
!packages/build/
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
.vs
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
EngineIoClientDotNet_Tests/Resources/test.xml
TestServer/test.xml
TestServer/test.xml
TestServer/test.xml

21
ThirdParty/EngineIoClientDotNet/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Quobject
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,76 @@
# EngineIoClientDotNet
====================
Engine.IO Client Library for .Net
This is the Engine.IO Client Library for C#, which is ported from the [JavaScript client](https://github.com/Automattic/engine.io-client).
## Installation
Nuget install:
```
Install-Package EngineIoClientDotNet
```
* NuGet Package: [![EngineIoClientDotNet](https://img.shields.io/nuget/v/EngineIoClientDotNet.svg?maxAge=2592000)](https://www.nuget.org/packages/EngineIoClientDotNet/)
## Usage
EngineIoClientDotNet has a similar api to those of the [JavaScript client](https://github.com/Automattic/engine.io-client).
You can use `Socket` to connect:
```cs
var socket = new Socket("ws://localhost");
socket.On(Socket.EVENT_OPEN, () =>
{
socket.Send("hi", () =>
{
socket.Close();
});
});
socket.Open();
```
Receiving data
```cs
var socket = new Socket("ws://localhost");
socket.On(Socket.EVENT_OPEN, () =>
{
socket.On(Socket.EVENT_MESSAGE, (data) =>
{
Console.WriteLine((string)data);
});
});
socket.Open();
```
## Features
This library supports all of the features the JS client does, including events, options and upgrading transport.
## Tests
Run tests on windows or linux:
```
git clone https://github.com/Quobject/EngineIoClientDotNet.git
cd EngineIoClientDotNet/grunt
npm install
```
Update `config.json` and add line to hosts file: `127.0.0.1 testme.quobject.com`.
```
grunt
```
This will start test server and xunit tests for windows.
In linux this will stop after starting test server. Start xunit tests within a new linux terminal:
```
grunt testClient
```
## Framework Versions
.NETFramework v3.5, .NETFramework v4.0, .NETFramework v4.4, .NETStandard v1.3,
## License
[MIT](http://opensource.org/licenses/MIT)

View File

@@ -0,0 +1,180 @@
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.Client.Transports;
using System.Collections.Concurrent;
using System.Collections.Immutable;
using System.Threading;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class BinaryPollingTest : Connection
{
//[Fact]
//public void PingTest()
//{
// var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
// log.Info("Start");
// var binaryData = new byte[5];
// for (int i = 0; i < binaryData.Length; i++)
// {
// binaryData[i] = (byte)i;
// }
// var events = new ConcurrentQueue<object>();
// var options = CreateOptions();
// options.Transports = ImmutableList.Create<string>(Polling.NAME);
// var socket = new Socket(options);
// socket.On(Socket.EVENT_OPEN, () =>
// {
// log.Info("EVENT_OPEN");
// socket.Send(binaryData);
// socket.Send("cash money €€€");
// });
// socket.On(Socket.EVENT_MESSAGE, (d) =>
// {
// var data = d as string;
// log.Info(string.Format("EVENT_MESSAGE data ={0} d = {1} ", data, d));
// if (data == "hi")
// {
// return;
// }
// events.Enqueue(d);
// //socket.Close();
// });
// socket.Open();
// Task.Delay(20000).Wait();
// socket.Close();
// log.Info("ReceiveBinaryData end");
// var binaryData2 = new byte[5];
// for (int i = 0; i < binaryData2.Length; i++)
// {
// binaryData2[i] = (byte)(i + 1);
// }
// object result;
// events.TryDequeue(out result);
// Assert.Equal("1", "1");
//}
private ManualResetEvent _manualResetEvent = null;
[Fact]
public void ReceiveBinaryData()
{
_manualResetEvent = new ManualResetEvent(false);
var events = new ConcurrentQueue<object>();
var binaryData = new byte[5];
for (int i = 0; i < binaryData.Length; i++)
{
binaryData[i] = (byte)i;
}
var options = CreateOptions();
options.Transports = ImmutableList.Create<string>(Polling.NAME);
var socket = new Socket(options);
socket.On(Socket.EVENT_OPEN, () =>
{
socket.Send(binaryData);
//socket.Send("cash money €€€");
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = d as string;
//log.Info(string.Format("EVENT_MESSAGE data ={0} d = {1} ", data, d));
if (data == "hi")
{
return;
}
events.Enqueue(d);
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
//log.Info("ReceiveBinaryData end");
var binaryData2 = new byte[5];
for (int i = 0; i < binaryData2.Length; i++)
{
binaryData2[i] = (byte)(i + 1);
}
object result;
events.TryDequeue(out result);
Assert.Equal(binaryData, result);
}
[Fact]
public void ReceiveBinaryDataAndMultibyteUTF8String()
{
_manualResetEvent = new ManualResetEvent(false);
var events = new ConcurrentQueue<object>();
var binaryData = new byte[5];
for (int i = 0; i < binaryData.Length; i++)
{
binaryData[i] = (byte)i;
}
const string stringData = "cash money €€€";
var options = CreateOptions();
options.Transports = ImmutableList.Create<string>(Polling.NAME);
var socket = new Socket(options);
socket.On(Socket.EVENT_OPEN, () =>
{
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = d as string;
//log.Info(string.Format("EVENT_MESSAGE data ={0} d = {1} ", data, d));
if (data == "hi")
{
return;
}
events.Enqueue(d);
if (events.Count > 1)
{
_manualResetEvent.Set();
}
});
socket.Send(binaryData);
socket.Send(stringData);
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
var binaryData2 = new byte[5];
for (int i = 0; i < binaryData2.Length; i++)
{
binaryData2[i] = (byte)(i + 1);
}
object result;
events.TryDequeue(out result);
Assert.Equal(binaryData, result);
events.TryDequeue(out result);
Assert.Equal(stringData, (string)result);
socket.Close();
}
}
}

View File

@@ -0,0 +1,132 @@
using Quobject.EngineIoClientDotNet.Client;
using System.Collections.Concurrent;
using System.Threading;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class BinaryWebSocketTest : Connection
{
private ManualResetEvent _manualResetEvent = null;
[Fact]
public void ReceiveBinaryData()
{
_manualResetEvent = new ManualResetEvent(false);
var events = new ConcurrentQueue<object>();
var binaryData = new byte[5];
for (int i = 0; i < binaryData.Length; i++)
{
binaryData[i] = (byte)(i + 0);
}
var options = CreateOptions();
var socket = new Socket(options);
socket.On(Socket.EVENT_OPEN, () =>
{
//log.Info(Socket.EVENT_OPEN);
});
socket.On(Socket.EVENT_UPGRADE, () =>
{
//log.Info(Socket.EVENT_UPGRADE);
socket.Send(binaryData);
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = d as string;
//log.Info(string.Format("EVENT_MESSAGE data ={0} d = {1} ", data, d));
if (data == "hi")
{
return;
}
events.Enqueue(d);
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
//log.Info("ReceiveBinaryData end");
var binaryData2 = new byte[5];
for (int i = 0; i < binaryData2.Length; i++)
{
binaryData2[i] = (byte)(i + 1);
}
object result;
events.TryDequeue(out result);
Assert.Equal(binaryData, result);
}
[Fact]
public void ReceiveBinaryDataAndMultibyteUTF8String()
{
_manualResetEvent = new ManualResetEvent(false);
var events = new ConcurrentQueue<object>();
var binaryData = new byte[5];
for (int i = 0; i < binaryData.Length; i++)
{
binaryData[i] = (byte)i;
}
const string stringData = "Ä ä Ü ü ß";
var options = CreateOptions();
var socket = new Socket(options);
socket.On(Socket.EVENT_OPEN, () =>
{
});
socket.On(Socket.EVENT_UPGRADE, () =>
{
//log.Info(Socket.EVENT_UPGRADE);
socket.Send(binaryData);
socket.Send(stringData);
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = d as string;
//log.Info(string.Format("EVENT_MESSAGE data ={0} d = {1} ", data, d));
if (data == "hi")
{
return;
}
events.Enqueue(d);
if (events.Count > 1)
{
_manualResetEvent.Set();
}
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
var binaryData2 = new byte[5];
for (int i = 0; i < binaryData2.Length; i++)
{
binaryData2[i] = (byte)(i + 1);
}
object result;
events.TryDequeue(out result);
Assert.Equal(binaryData, result);
events.TryDequeue(out result);
Assert.Equal(stringData, (string)result);
//log.Info("ReceiveBinaryDataAndMultibyteUTF8String end");
}
}
}

View File

@@ -0,0 +1,38 @@
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.Modules;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class Connection
{
static Connection()
{
LogManager.SetupLogManager();
}
protected static Socket.Options CreateOptions()
{
var options = new Socket.Options
{
Port = ConnectionConstants.PORT,
Hostname = ConnectionConstants.HOSTNAME
};
//log.Info("Please add to your hosts file: 127.0.0.1 " + options.Hostname);
return options;
}
protected static Socket.Options CreateOptionsSecure()
{
var options = new Socket.Options
{
Port = ConnectionConstants.SSL_PORT,
Hostname = ConnectionConstants.HOSTNAME,
//log.Info("Please add to your hosts file: 127.0.0.1 " + options.Hostname);
Secure = true,
IgnoreServerCertificateValidation = true
};
return options;
}
}
}

View File

@@ -0,0 +1,10 @@
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public static class ConnectionConstants
{
public static int PORT = 80;
public static string HOSTNAME = "testme.quobject.com";
public static int SSL_PORT = 443;
public static readonly int TIMEOUT = 300000;
}
}

View File

@@ -0,0 +1,211 @@
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.Client.Transports;
using Quobject.EngineIoClientDotNet.ComponentEmitter;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class ConnectionTest : Connection
{
private ManualResetEvent _manualResetEvent = null;
private Socket socket;
public string Message;
[Fact]
public void ConnectToLocalhost()
{
_manualResetEvent = new ManualResetEvent(false);
socket = new Socket(CreateOptions());
socket.On(Socket.EVENT_OPEN, new TestListener());
socket.On(Socket.EVENT_MESSAGE, new MessageListener(socket, this));
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
Assert.Equal("hi", this.Message);
}
public class TestListener : IListener
{
public void Call(params object[] args)
{
//log.Info("open");
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
public class MessageListener : IListener
{
private Socket socket;
private ConnectionTest connectionTest;
public MessageListener(Socket socket)
{
this.socket = socket;
}
public MessageListener(Socket socket, ConnectionTest connectionTest)
{
this.socket = socket;
this.connectionTest = connectionTest;
}
public void Call(params object[] args)
{
//log.Info("message = " + args[0]);
connectionTest.Message = (string)args[0];
connectionTest._manualResetEvent.Set();
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
[Fact]
public void ConnectToLocalhost2()
{
_manualResetEvent = new ManualResetEvent(false);
this.Message = "";
var options = CreateOptions();
options.Transports = ImmutableList.Create<string>(Polling.NAME);
socket = new Socket(options);
//socket = new Socket(CreateOptions());
socket.On(Socket.EVENT_OPEN, () =>
{
//log.Info("open");
//socket.Send("test send");
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = (string)d;
//log.Info("message2 = " + data);
this.Message = data;
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
Assert.Equal("hi", this.Message);
}
[Fact]
public void TestmultibyteUtf8StringsWithPolling()
{
_manualResetEvent = new ManualResetEvent(false);
const string SendMessage = "cash money €€€";
socket = new Socket(CreateOptions());
socket.On(Socket.EVENT_OPEN, () =>
{
//log.Info("open");
socket.Send(SendMessage);
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = (string)d;
//log.Info("TestMessage data = " + data);
if (data == "hi")
{
return;
}
this.Message = data;
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
//log.Info("TestmultibyteUtf8StringsWithPolling this.Message = " + this.Message);
Assert.Equal(SendMessage, this.Message);
}
[Fact]
public void Testemoji()
{
_manualResetEvent = new ManualResetEvent(false);
const string SendMessage = "\uD800-\uDB7F\uDB80-\uDBFF\uDC00-\uDFFF\uE000-\uF8FF";
var options = CreateOptions();
socket = new Socket(options);
socket.On(Socket.EVENT_OPEN, () =>
{
//log.Info("open");
socket.Send(SendMessage);
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = (string)d;
//log.Info(Socket.EVENT_MESSAGE);
if (data == "hi")
{
return;
}
this.Message = data;
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
Assert.True(SendMessage == this.Message);
}
[Fact]
public async Task NotSendPacketsIfSocketCloses()
{
var noPacket = true;
socket = new Socket(CreateOptions());
socket.On(Socket.EVENT_OPEN, () =>
{
noPacket = true;
});
socket.Open();
socket.On(Socket.EVENT_PACKET_CREATE, () =>
{
noPacket = false;
//log.Info("NotSendPacketsIfSocketCloses EVENT_PACKET_CREATE noPacket = " + noPacket);
});
socket.Close();
await Task.Delay(1000);
//log.Info("NotSendPacketsIfSocketCloses end noPacket = " + noPacket);
Assert.True(noPacket);
}
}
}

View File

@@ -0,0 +1,69 @@
using Newtonsoft.Json;
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.Modules;
using System.IO;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class Connection
{
public static readonly int TIMEOUT = 300000;
static Connection()
{
LogManager.SetupLogManager();
}
protected Socket.Options CreateOptions()
{
var config = ConfigBase.Load();
var options = new Socket.Options();
options.Port = config.server.port;
options.Hostname = config.server.hostname;
//log.Info("Please add to your hosts file: 127.0.0.1 " + options.Hostname);
return options;
}
protected Socket.Options CreateOptionsSecure()
{
var config = ConfigBase.Load();
var options = new Socket.Options();
options.Port = config.server.ssl_port;
options.Hostname = config.server.hostname;
//log.Info("Please add to your hosts file: 127.0.0.1 " + options.Hostname);
options.Secure = true;
options.IgnoreServerCertificateValidation = true;
return options;
}
}
public class ConfigBase
{
public string version { get; set; }
public ConfigServer server { get; set; }
public static ConfigBase Load()
{
//var configString = File.ReadAllText("./../../../../grunt/config.json");
var configString = @"{""version"":""0.1.0.0"",""server"":{""port"":80,""ssl_port"":443,""hostname"":""192.168.178.59""},""win"":{""powershell"":""C:/WINDOWS/System32/WindowsPowerShell/v1.0/powershell.exe"",""msbuild"":""C:/Windows/Microsoft.NET/Framework/v4.0.30319/msbuild.exe"",""xunit_path"":""C:/vendors/xunit"",""nuget"":""C:/vendors/nuget/nuget.exe""},""linux"":{""msbuild"":""xbuild"",""xunit_path"":""/home/apollo/vendors/xunit""}}";
var config = JsonConvert.DeserializeObject<ConfigBase>(configString);
return config;
}
}
public class ConfigServer
{
public string hostname { get; set; }
public int port { get; set; }
public int ssl_port { get; set; }
}
}

View File

@@ -0,0 +1,26 @@
using Quobject.EngineIoClientDotNet.Client;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class HandshakeDataTests
{
[Fact]
public void Test()
{
var json = @"{
sid: 'nne323',
upgrades: ['u1','u2'],
pingInterval: 12,
pingTimeout: 23
}";
var handshakeData = new HandshakeData(json);
Assert.Equal("u1", handshakeData.Upgrades[0]);
Assert.Equal("u2", handshakeData.Upgrades[1]);
Assert.Equal(12, handshakeData.PingInterval);
Assert.Equal(23, handshakeData.PingTimeout);
}
}
}

View File

@@ -0,0 +1,267 @@
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.Client.Transports;
using Quobject.EngineIoClientDotNet.ComponentEmitter;
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Threading;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class SSLServerConnectionTest : Connection
{
private ManualResetEvent _manualResetEvent = null;
[Fact]
public void OpenAndClose()
{
_manualResetEvent = new ManualResetEvent(false);
var events = new ConcurrentQueue<string>();
var socket = new Socket(CreateOptionsSecure());
Console.WriteLine(Directory.GetCurrentDirectory());
socket.On(Socket.EVENT_OPEN, () =>
{
Console.WriteLine("EVENT_OPEN");
events.Enqueue(Socket.EVENT_OPEN);
socket.Close();
});
socket.On(Socket.EVENT_CLOSE, () =>
{
Console.WriteLine("EVENT_CLOSE");
events.Enqueue(Socket.EVENT_CLOSE);
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
string result;
events.TryDequeue(out result);
Assert.Equal(Socket.EVENT_OPEN, result);
events.TryDequeue(out result);
Assert.Equal(Socket.EVENT_CLOSE, result);
}
[Fact]
public void Messages()
{
_manualResetEvent = new ManualResetEvent(false);
var events = new ConcurrentQueue<string>();
var socket = new Socket(CreateOptionsSecure());
socket.On(Socket.EVENT_OPEN, () =>
{
socket.Send("hello");
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = (string)d;
//log.Info("EVENT_MESSAGE data = " + data);
events.Enqueue(data);
if (events.Count > 1)
{
_manualResetEvent.Set();
}
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
string result;
events.TryDequeue(out result);
Assert.Equal("hi", result);
events.TryDequeue(out result);
Assert.Equal("hello", result);
}
[Fact]
public void Handshake()
{
_manualResetEvent = new ManualResetEvent(false);
HandshakeData handshake_data = null;
var socket = new Socket(CreateOptionsSecure());
socket.On(Socket.EVENT_HANDSHAKE, (data) =>
{
//log.Info(Socket.EVENT_HANDSHAKE + string.Format(" data = {0}", data));
handshake_data = data as HandshakeData;
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
Assert.NotNull(handshake_data);
Assert.NotNull(handshake_data.Upgrades);
Assert.True(handshake_data.Upgrades.Count > 0);
Assert.True(handshake_data.PingInterval > 0);
Assert.True(handshake_data.PingTimeout > 0);
}
public class TestHandshakeListener : IListener
{
public HandshakeData HandshakeData;
private SSLServerConnectionTest serverConnectionTest;
public TestHandshakeListener(SSLServerConnectionTest serverConnectionTest)
{
this.serverConnectionTest = serverConnectionTest;
}
public void Call(params object[] args)
{
//log.Info(string.Format("open args[0]={0} args.Length={1}", args[0], args.Length));
HandshakeData = args[0] as HandshakeData;
serverConnectionTest._manualResetEvent.Set();
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
[Fact]
public void Handshake2()
{
_manualResetEvent = new ManualResetEvent(false);
var socket = new Socket(CreateOptionsSecure());
var testListener = new TestHandshakeListener(this);
socket.On(Socket.EVENT_HANDSHAKE, testListener);
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
Assert.NotNull(testListener.HandshakeData);
Assert.NotNull(testListener.HandshakeData.Upgrades);
Assert.True(testListener.HandshakeData.Upgrades.Count > 0);
Assert.True(testListener.HandshakeData.PingInterval > 0);
Assert.True(testListener.HandshakeData.PingTimeout > 0);
}
[Fact]
public void Upgrade()
{
_manualResetEvent = new ManualResetEvent(false);
var events = new ConcurrentQueue<object>();
var socket = new Socket(CreateOptionsSecure());
socket.On(Socket.EVENT_UPGRADING, (data) =>
{
//log.Info(Socket.EVENT_UPGRADING + string.Format(" data = {0}", data));
events.Enqueue(data);
});
socket.On(Socket.EVENT_UPGRADE, (data) =>
{
//log.Info(Socket.EVENT_UPGRADE + string.Format(" data = {0}", data));
events.Enqueue(data);
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
object test = null;
events.TryDequeue(out test);
Assert.NotNull(test);
Assert.IsAssignableFrom<Transport>(test);
events.TryDequeue(out test);
Assert.NotNull(test);
Assert.IsAssignableFrom<Transport>(test);
}
[Fact]
public void RememberWebsocket()
{
_manualResetEvent = new ManualResetEvent(false);
var socket1 = new Socket(CreateOptionsSecure());
string socket1TransportName = null;
string socket2TransportName = null;
socket1.On(Socket.EVENT_OPEN, () =>
{
socket1TransportName = socket1.Transport.Name;
});
socket1.On(Socket.EVENT_UPGRADE, (data) =>
{
//log.Info(Socket.EVENT_UPGRADE + string.Format(" data = {0}", data));
var transport = (Transport)data;
socket1.Close();
if (WebSocket.NAME == transport.Name)
{
var options = CreateOptionsSecure();
options.RememberUpgrade = true;
var socket2 = new Socket(options);
socket2.Open();
socket2TransportName = socket2.Transport.Name;
socket2.Close();
_manualResetEvent.Set();
}
});
socket1.Open();
_manualResetEvent.WaitOne();
Assert.Equal(Polling.NAME, socket1TransportName);
Assert.Equal(WebSocket.NAME, socket2TransportName);
}
[Fact]
public void NotRememberWebsocket()
{
_manualResetEvent = new ManualResetEvent(false);
var socket1 = new Socket(CreateOptionsSecure());
string socket1TransportName = null;
string socket2TransportName = null;
socket1.On(Socket.EVENT_OPEN, () =>
{
socket1TransportName = socket1.Transport.Name;
});
socket1.On(Socket.EVENT_UPGRADE, (data) =>
{
//log.Info(Socket.EVENT_UPGRADE + string.Format(" data = {0}", data));
var transport = (Transport)data;
if (WebSocket.NAME == transport.Name)
{
socket1.Close();
var options = CreateOptionsSecure();
options.RememberUpgrade = false;
var socket2 = new Socket(options);
socket2.On(Socket.EVENT_OPEN, () =>
{
//log.Info("EVENT_OPEN socket 2");
socket2TransportName = socket2.Transport.Name;
socket2.Close();
_manualResetEvent.Set();
});
socket2.Open();
}
});
socket1.Open();
_manualResetEvent.WaitOne();
Assert.Equal(Polling.NAME, socket1TransportName);
Assert.Equal(Polling.NAME, socket2TransportName);
}
}
}

View File

@@ -0,0 +1,451 @@
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.Client.Transports;
using Quobject.EngineIoClientDotNet.ComponentEmitter;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class ServerConnectionTest : Connection
{
private ManualResetEvent _manualResetEvent = null;
[Fact]
public void OpenAndClose()
{
_manualResetEvent = new ManualResetEvent(false);
var events = new ConcurrentQueue<string>();
var options = CreateOptions();
options.Query = new Dictionary<string, string>
{
{
"access_token", "akaka"
}
};
options.QueryString = "akka=ekek";
var socket = new Socket(options);
socket.On(Socket.EVENT_OPEN, () =>
{
events.Enqueue(Socket.EVENT_OPEN);
socket.Close();
});
socket.On(Socket.EVENT_CLOSE, () =>
{
//log.Info("EVENT_CLOSE");
events.Enqueue(Socket.EVENT_CLOSE);
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
string result;
events.TryDequeue(out result);
Assert.Equal(Socket.EVENT_OPEN, result);
events.TryDequeue(out result);
Assert.Equal(Socket.EVENT_CLOSE, result);
}
[Fact]
public void Messages()
{
_manualResetEvent = new ManualResetEvent(false);
var events = new ConcurrentQueue<string>();
var socket = new Socket(CreateOptions());
socket.On(Socket.EVENT_OPEN, () =>
{
socket.Send("hello");
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = (string)d;
//log.Info("EVENT_MESSAGE data = " + data);
events.Enqueue(data);
if (events.Count > 1)
{
_manualResetEvent.Set();
}
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
string result;
events.TryDequeue(out result);
Assert.Equal("hi", result);
events.TryDequeue(out result);
Assert.Equal("hello", result);
}
[Fact]
public void Handshake()
{
_manualResetEvent = new ManualResetEvent(false);
HandshakeData handshake_data = null;
var socket = new Socket(CreateOptions());
socket.On(Socket.EVENT_HANDSHAKE, (data) =>
{
//log.Info(Socket.EVENT_HANDSHAKE + string.Format(" data = {0}", data));
handshake_data = data as HandshakeData;
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
Assert.NotNull(handshake_data);
Assert.NotNull(handshake_data.Upgrades);
Assert.True(handshake_data.Upgrades.Count > 0);
Assert.True(handshake_data.PingInterval > 0);
Assert.True(handshake_data.PingTimeout > 0);
}
public class TestHandshakeListener : IListener
{
public HandshakeData HandshakeData;
private ServerConnectionTest serverConnectionTest;
public TestHandshakeListener(ServerConnectionTest serverConnectionTest)
{
this.serverConnectionTest = serverConnectionTest;
}
public void Call(params object[] args)
{
//log.Info(string.Format("open args[0]={0} args.Length={1}", args[0], args.Length));
HandshakeData = args[0] as HandshakeData;
serverConnectionTest._manualResetEvent.Set();
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
[Fact]
public void Handshake2()
{
_manualResetEvent = new ManualResetEvent(false);
var socket = new Socket(CreateOptions());
var testListener = new TestHandshakeListener(this);
socket.On(Socket.EVENT_HANDSHAKE, testListener);
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
Assert.NotNull(testListener.HandshakeData);
Assert.NotNull(testListener.HandshakeData.Upgrades);
Assert.True(testListener.HandshakeData.Upgrades.Count > 0);
Assert.True(testListener.HandshakeData.PingInterval > 0);
Assert.True(testListener.HandshakeData.PingTimeout > 0);
}
[Fact]
public void Upgrade()
{
_manualResetEvent = new ManualResetEvent(false);
var events = new ConcurrentQueue<object>();
var socket = new Socket(CreateOptions());
socket.On(Socket.EVENT_UPGRADING, (data) =>
{
//log.Info(Socket.EVENT_UPGRADING + string.Format(" data = {0}", data));
events.Enqueue(data);
});
socket.On(Socket.EVENT_UPGRADE, (data) =>
{
//log.Info(Socket.EVENT_UPGRADE + string.Format(" data = {0}", data));
events.Enqueue(data);
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
object test = null;
events.TryDequeue(out test);
Assert.NotNull(test);
Assert.IsAssignableFrom<Transport>(test);
events.TryDequeue(out test);
Assert.NotNull(test);
Assert.IsAssignableFrom<Transport>(test);
}
[Fact]
public void RememberWebsocket()
{
_manualResetEvent = new ManualResetEvent(false);
var socket1 = new Socket(CreateOptions());
string socket1TransportName = null;
string socket2TransportName = null;
socket1.On(Socket.EVENT_OPEN, () =>
{
socket1TransportName = socket1.Transport.Name;
});
socket1.On(Socket.EVENT_UPGRADE, (data) =>
{
//log.Info(Socket.EVENT_UPGRADE + string.Format(" data = {0}", data));
var transport = (Transport)data;
socket1.Close();
if (WebSocket.NAME == transport.Name)
{
var options = CreateOptions();
options.RememberUpgrade = true;
var socket2 = new Socket(options);
socket2.Open();
socket2TransportName = socket2.Transport.Name;
socket2.Close();
_manualResetEvent.Set();
}
});
socket1.Open();
_manualResetEvent.WaitOne();
Assert.Equal(Polling.NAME, socket1TransportName);
Assert.Equal(WebSocket.NAME, socket2TransportName);
}
[Fact]
public void NotRememberWebsocket()
{
_manualResetEvent = new ManualResetEvent(false);
var socket1 = new Socket(CreateOptions());
string socket1TransportName = null;
string socket2TransportName = null;
socket1.On(Socket.EVENT_OPEN, () =>
{
socket1TransportName = socket1.Transport.Name;
});
socket1.On(Socket.EVENT_UPGRADE, (data) =>
{
//log.Info(Socket.EVENT_UPGRADE + string.Format(" data = {0}", data));
var transport = (Transport)data;
if (WebSocket.NAME == transport.Name)
{
socket1.Close();
var options = CreateOptions();
options.RememberUpgrade = false;
var socket2 = new Socket(options);
socket2.On(Socket.EVENT_OPEN, () =>
{
//log.Info("EVENT_OPEN socket 2");
socket2TransportName = socket2.Transport.Name;
socket2.Close();
_manualResetEvent.Set();
});
socket2.Open();
}
});
socket1.Open();
_manualResetEvent.WaitOne();
Assert.Equal(Polling.NAME, socket1TransportName);
Assert.Equal(Polling.NAME, socket2TransportName);
}
//Fails in .netstandard1.3 for EngineIoClientDotNet 1.0.4
[Fact]
public void Cookie()
{
_manualResetEvent = new ManualResetEvent(false);
var events = new Queue<string>();
var options = CreateOptions();
options.Cookies.Add("foo", "bar");
var socket = new Socket(options);
socket.On(Socket.EVENT_OPEN, () =>
{
socket.Send("cookie");
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = (string)d;
//log.Info("EVENT_MESSAGE data = " + data);
events.Enqueue(data);
if (events.Count > 1)
{
_manualResetEvent.Set();
}
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
string result;
result = events.Dequeue();
Assert.Equal("hi", result);
result = events.Dequeue();
Assert.Equal("got cookie", result);
}
//Fails in .netstandard1.3 for EngineIoClientDotNet 1.0.4
[Fact]
public void UpgradeCookie()
{
_manualResetEvent = new ManualResetEvent(false);
var events = new Queue<object>();
var options = CreateOptions();
options.Cookies.Add("foo", "bar");
var socket = new Socket(options);
socket.On(Socket.EVENT_UPGRADING, (data) =>
{
//log.Info(Socket.EVENT_UPGRADING + string.Format(" data = {0}", data));
events.Enqueue(data);
});
socket.On(Socket.EVENT_UPGRADE, (data) =>
{
//log.Info(Socket.EVENT_UPGRADE + string.Format(" data = {0}", data));
events.Enqueue(data);
socket.Send("cookie");
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
if (events.Count > 1)
{
var data = (string)d;
//log.Info("EVENT_MESSAGE data = " + data);
events.Enqueue(data);
_manualResetEvent.Set();
}
});
socket.Open();
_manualResetEvent.WaitOne();
object test = null;
test = events.Dequeue();
Assert.NotNull(test);
Assert.IsAssignableFrom<Transport>(test);
test = events.Dequeue();
Assert.NotNull(test);
Assert.IsAssignableFrom<Transport>(test);
test = events.Dequeue();
Assert.Equal("got cookie", test);
}
//[Fact]
//public void PrimusEndpoint()
//{
// var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
// //log.Info("Start");
// _manualResetEvent = new ManualResetEvent(false);
// var events = new Queue<string>();
// var options = CreateOptions();
// options.Cookies.Add("foo", "bar");
// options.Hostname = "testme.quobject.com/";
// options.Path = "primus";
// var socket = new Socket(options);
// //var socket = new Socket("testme.quobject.com");
// socket.On(Socket.EVENT_OPEN, () =>
// {
// //log.Info("EVENT_OPEN");
// socket.Send("cookie");
// });
// socket.On(Socket.EVENT_MESSAGE, (d) =>
// {
// var data = (string)d;
// //log.Info("EVENT_MESSAGE data = " + data);
// events.Enqueue(data);
// if (events.Count > 1)
// {
// _manualResetEvent.Set();
// }
// });
// socket.Open();
// _manualResetEvent.WaitOne();
// socket.Close();
// string result;
// result = events.Dequeue();
// Assert.Equal("hi", result);
// result = events.Dequeue();
// Assert.Equal("got cookie", result);
//}
// [Fact]
//public void MessagesMulti()
//{
// //logManager.Enabled = true;
// var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
// //log.Info("Start");
// _manualResetEvent = new ManualResetEvent(false);
// var events = new ConcurrentQueue<string>();
// int count = 200;
// var socket = new Socket(CreateOptions());
// socket.On(Socket.EVENT_OPEN, () =>
// {
// //log.Info("EVENT_OPEN");
// Task.Run(() =>
// {
// for (int i = 0; i < count; i++)
// {
// socket.Send("multi");
// Task.Delay(TimeSpan.FromSeconds(1)).Wait();
// }
// });
// });
// socket.On(Socket.EVENT_MESSAGE, (d) =>
// {
// var data = (string)d;
// //log.Info("EVENT_MESSAGE data = " + data);
// events.Enqueue(data);
// if (events.Count > count)
// {
// _manualResetEvent.Set();
// }
// });
// socket.Open();
// _manualResetEvent.WaitOne();
// socket.Close();
// string result;
// events.TryDequeue(out result);
// Assert.Equal("hi", result);
// events.TryDequeue(out result);
// Assert.Equal("multi", result);
//}
}
}

View File

@@ -0,0 +1,76 @@
using Quobject.EngineIoClientDotNet.Client;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class SocketTest : Connection
{
private Socket socket;
public string Message;
[Fact]
public void FilterUpgrades()
{
var options = CreateOptions();
options.Transports = ImmutableList<string>.Empty.Add("polling");
socket = new Socket(options);
var immutablelist = socket.FilterUpgrades(ImmutableList<string>.Empty.Add("polling").Add("websocket"));
Assert.Equal("polling", immutablelist[0]);
Assert.Equal(1, immutablelist.Count);
}
[Fact]
public async Task SocketClosing()
{
var closed = false;
var error = false;
var options = CreateOptions();
socket = new Socket("ws://0.0.0.0:8080", options);
socket.On(Socket.EVENT_OPEN, () =>
{
//socket.Send("test send");
});
socket.On(Socket.EVENT_CLOSE, () =>
{
//log.Info("EVENT_CLOSE = ");
closed = true;
});
socket.Once(Socket.EVENT_ERROR, () =>
{
//log.Info("EVENT_ERROR = ");
error = true;
});
socket.Open();
//System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
await Task.Delay(1000);
Assert.True(closed);
Assert.True(error);
}
[Fact]
public void SocketOptionCookies()
{
var options = new Socket.Options();
options.Cookies.Add("foo", "bar");
Assert.Equal("foo=bar", options.GetCookiesAsString());
options.Cookies.Add("name2", "value2");
Assert.Equal("foo=bar; name2=value2", options.GetCookiesAsString());
}
[Fact]
public void DefaultProtocol()
{
var socket = new Socket("testme.quobject.com");
Assert.NotNull(socket);
}
}
}

View File

@@ -0,0 +1,170 @@
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.Client.Transports;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
// NOTE: tests for the rememberUpgrade option are on ServerConnectionTest.
public class TransportTest : Connection
{
[Fact]
public void Constructors()
{
var socket = new Socket(CreateOptions());
socket.Open();
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(3));
Assert.NotNull(socket.Transport);
socket.Close();
}
[Fact]
public void Uri()
{
var options = new Transport.Options
{
Path = "/engine.io",
Hostname = Connection.CreateOptions().Hostname,
Secure = false,
Query = new Dictionary<string, string> { { "sid", "test" } },
TimestampRequests = false
};
var polling = new Polling(options);
var expected = string.Format("http://{0}/engine.io?sid=test&b64=1", options.Hostname);
Assert.Contains(expected, polling.Uri());
}
[Fact]
public void UriWithDefaultPort()
{
var options = new Transport.Options
{
Path = "/engine.io",
Hostname = Connection.CreateOptions().Hostname,
Secure = false,
Query = new Dictionary<string, string> { { "sid", "test" } },
TimestampRequests = false,
Port = 80
};
var polling = new Polling(options);
//Assert.Contains("http://localhost/engine.io?sid=test&b64=1", polling.Uri());
var expected = string.Format("http://{0}/engine.io?sid=test&b64=1", options.Hostname);
Assert.Contains(expected, polling.Uri());
}
[Fact]
public void UriWithPort()
{
var options = new Transport.Options
{
Path = "/engine.io",
Hostname = Connection.CreateOptions().Hostname,
Secure = false,
Query = new Dictionary<string, string> { { "sid", "test" } },
TimestampRequests = false,
Port = 3000
};
var polling = new Polling(options);
//Assert.Contains("http://localhost:3000/engine.io?sid=test&b64=1", polling.Uri());
var expected = string.Format("http://{0}:{1}/engine.io?sid=test&b64=1", options.Hostname, options.Port);
Assert.Contains(expected, polling.Uri());
}
[Fact]
public void HttpsUriWithDefaultPort()
{
var options = new Transport.Options
{
Path = "/engine.io",
Hostname = Connection.CreateOptions().Hostname,
Secure = true,
Query = new Dictionary<string, string> { { "sid", "test" } },
TimestampRequests = false,
Port = 443
};
var polling = new Polling(options);
//Assert.Contains("https://localhost/engine.io?sid=test&b64=1", polling.Uri());
var expected = string.Format("https://{0}/engine.io?sid=test&b64=1", options.Hostname);
Assert.Contains(expected, polling.Uri());
}
[Fact]
public void TimestampedUri()
{
var options = new Transport.Options
{
Path = "/engine.io",
Hostname = "test",
Secure = false,
Query = new Dictionary<string, string> { { "sid", "test" } },
TimestampRequests = true,
TimestampParam = "t"
};
var polling = new Polling(options);
var pat = @"http://test/engine.io\?sid=test&(t=[0-9]+-[0-9]+)";
var r = new Regex(pat, RegexOptions.IgnoreCase);
var test = polling.Uri();
//log.Info(test);
var m = r.Match(test);
Assert.True(m.Success);
}
[Fact]
public void WsUri()
{
var options = new Transport.Options
{
Path = "/engine.io",
Hostname = "test",
Secure = false,
Query = new Dictionary<string, string> { { "transport", "websocket" } },
TimestampRequests = false
};
var ws = new WebSocket(options);
Assert.Contains("ws://test/engine.io?transport=websocket", ws.Uri());
}
[Fact]
public void WssUri()
{
var options = new Transport.Options
{
Path = "/engine.io",
Hostname = "test",
Secure = true,
Query = new Dictionary<string, string> { { "transport", "websocket" } },
TimestampRequests = false
};
var ws = new WebSocket(options);
Assert.Contains("wss://test/engine.io?transport=websocket", ws.Uri());
}
[Fact]
public void WsTimestampedUri()
{
var options = new Transport.Options
{
Path = "/engine.io",
Hostname = "test",
Secure = false,
Query = new Dictionary<string, string> { { "sid", "test" } },
TimestampRequests = true,
TimestampParam = "woot"
};
var ws = new WebSocket(options);
var pat = @"ws://test/engine.io\?sid=test&(woot=[0-9]+-[0-9]+)";
var r = new Regex(pat, RegexOptions.IgnoreCase);
var test = ws.Uri();
//log.Info(test);
var m = r.Match(test);
Assert.True(m.Success);
}
}
}

View File

@@ -0,0 +1,45 @@
using Quobject.EngineIoClientDotNet.Client;
using System;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class UsageTest : Connection
{
[Fact]
public void Usage1()
{
var options = CreateOptions();
var socket = new Socket(options);
//You can use `Socket` to connect:
//var socket = new Socket("ws://localhost");
socket.On(Socket.EVENT_OPEN, () =>
{
socket.Send("hi");
socket.Close();
});
socket.Open();
//System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
}
[Fact]
public void Usage2()
{
var options = CreateOptions();
var socket = new Socket(options);
//Receiving data
//var socket = new Socket("ws://localhost:3000");
socket.On(Socket.EVENT_OPEN, () =>
{
socket.On(Socket.EVENT_MESSAGE, (data) => Console.WriteLine((string)data));
});
socket.Open();
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
socket.Close();
}
}
}

View File

@@ -0,0 +1,399 @@
using Quobject.EngineIoClientDotNet.ComponentEmitter;
using Quobject.EngineIoClientDotNet.Modules;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ComponentEmitterTests
{
public class EmitterTests
{
public class TestListener1 : IListener
{
private readonly List<object> _calls;
public TestListener1(List<object> calls)
{
this._calls = calls;
}
public void Call(params object[] args)
{
_calls.Add("one");
_calls.Add(args[0]);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
public class TestListener2 : IListener
{
private readonly List<object> _calls;
public TestListener2(List<object> calls)
{
this._calls = calls;
}
public void Call(params object[] args)
{
_calls.Add("two");
_calls.Add(args[0]);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
[Fact]
public void On()
{
var emitter = new Emitter();
var calls = new List<object>();
var listener1 = new TestListener1(calls);
emitter.On("foo", listener1);
var listener2 = new TestListener2(calls);
emitter.On("foo", listener2);
emitter.Emit("foo", 1);
emitter.Emit("bar", 1);
emitter.Emit("foo", 2);
var expected = new Object[] {"one", 1, "two", 1, "one", 2, "two", 2};
Assert.Equal(expected, calls.ToArray());
}
[Fact]
public void Once()
{
var emitter = new Emitter();
var calls = new List<object>();
var listener1 = new TestListener1(calls);
emitter.Once("foo", listener1);
emitter.Emit("foo", 1);
emitter.Emit("foo", 2);
emitter.Emit("foo", 3);
emitter.Emit("bar", 1);
var expected = new Object[] {"one", 1};
Assert.Equal(expected, calls.ToArray());
}
public class TestListener3 : IListener
{
private readonly List<object> _calls;
public TestListener3(List<object> calls)
{
this._calls = calls;
}
public void Call(params object[] args)
{
_calls.Add("one");
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
public class TestListener4 : IListener
{
private readonly List<object> _calls;
public TestListener4(List<object> calls)
{
this._calls = calls;
}
public void Call(params object[] args)
{
_calls.Add("two");
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
[Fact]
public void Off()
{
var emitter = new Emitter();
var calls = new List<object>();
var listener3 = new TestListener3(calls);
emitter.On("foo", listener3);
var listener4 = new TestListener4(calls);
emitter.On("foo", listener4);
emitter.Off("foo", listener4);
emitter.Emit("foo");
var expected = new Object[] {"one"};
Assert.Equal(expected, calls.ToArray());
}
[Fact]
public void OffWithOnce()
{
var emitter = new Emitter();
var calls = new List<object>();
var listener3 = new TestListener3(calls);
emitter.Once("foo", listener3);
emitter.Off("foo", listener3);
emitter.Emit("foo");
var expected = new Object[] {};
Assert.Equal(expected, calls.ToArray());
}
public class TestListener5 : IListener
{
private readonly List<bool> _called;
public TestListener5(List<bool> called)
{
this._called = called;
}
public void Call(params object[] args)
{
this._called[0] = true;
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
public class TestListener6 : IListener
{
private readonly Emitter _emitter;
private readonly IListener _bListener;
public TestListener6(Emitter emitter, IListener bListener)
{
this._emitter = emitter;
this._bListener = bListener;
}
public void Call(params object[] args)
{
_emitter.Off("tobi", _bListener);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
[Fact]
public void OffWhenCalledfromEvent()
{
var emitter = new Emitter();
var called = new List<bool> {false};
var listener5 = new TestListener5(called);
var listener6 = new TestListener6(emitter, listener5);
emitter.On("tobi", listener6);
emitter.Once("tobi", listener5);
emitter.Emit("tobi");
Assert.True(called[0]);
called[0] = false;
emitter.Emit("tobi");
Assert.False(called[0]);
}
[Fact]
public void OffEvent()
{
var emitter = new Emitter();
var calls = new List<object>();
var listener3 = new TestListener3(calls);
emitter.On("foo", listener3);
var listener4 = new TestListener4(calls);
emitter.On("foo", listener3);
emitter.On("foo", listener4);
emitter.Off("foo");
emitter.Emit("foo");
emitter.Emit("foo");
var expected = new Object[] {};
Assert.Equal(expected, calls.ToArray());
}
[Fact]
public void OffAll()
{
var emitter = new Emitter();
var calls = new List<object>();
var listener3 = new TestListener3(calls);
var listener4 = new TestListener4(calls);
emitter.On("foo", listener3);
emitter.On("bar", listener4);
emitter.Emit("foo");
emitter.Emit("bar");
emitter.Off();
emitter.Emit("foo");
emitter.Emit("bar");
var expected = new Object[] {"one", "two"};
Assert.Equal(expected, calls.ToArray());
}
[Fact]
public void Listeners()
{
var emitter = new Emitter();
var calls = new List<object>();
var listener3 = new TestListener3(calls);
emitter.On("foo", listener3);
var expected = new IListener[] {listener3};
Assert.Equal(expected, emitter.Listeners("foo").ToArray());
}
[Fact]
public void ListenersWithoutHandlers()
{
var emitter = new Emitter();
var expected = new IListener[] {};
Assert.Equal(expected, emitter.Listeners("foo").ToArray());
}
[Fact]
public void HasListeners()
{
var emitter = new Emitter();
var calls = new List<object>();
Assert.False(emitter.HasListeners("foo"));
var listener3 = new TestListener3(calls);
emitter.On("foo", listener3);
Assert.True(emitter.HasListeners("foo"));
}
[Fact]
public void HasListenersWithoutHandlers()
{
var emitter = new Emitter();
Assert.False(emitter.HasListeners("foo"));
}
}
}

View File

@@ -0,0 +1,115 @@
<?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>{382C2A10-8043-49C6-9DE5-39CA25C2418C}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>EngineIoClientDotNet.Tests</RootNamespace>
<AssemblyName>EngineIoClientDotNet.Tests.mono</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</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>..\EngineIoClientDotNet.mono\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>..\EngineIoClientDotNet.mono\packages\SuperSocket.ClientEngine.Core.0.8.0.8\lib\net45\SuperSocket.ClientEngine.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Numerics" />
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.mono\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="WebSocket4Net, Version=0.15.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.mono\packages\WebSocket4Net.0.15.0-beta6\lib\net45\WebSocket4Net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.mono\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.assert, Version=2.2.0.3545, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.mono\packages\xunit.assert.2.2.0\lib\netstandard1.1\xunit.assert.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.core, Version=2.2.0.3545, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.mono\packages\xunit.extensibility.core.2.2.0\lib\netstandard1.1\xunit.core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.execution.dotnet, Version=2.2.0.3545, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.mono\packages\xunit.extensibility.execution.2.2.0\lib\netstandard1.1\xunit.execution.dotnet.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ClientTests\BinaryPollingTest.cs" />
<Compile Include="ClientTests\BinaryWebSocketTest.cs" />
<Compile Include="ClientTests\Connection.cs" />
<Compile Include="ClientTests\ConnectionTest.cs" />
<Compile Include="ClientTests\HandshakeDataTests.cs" />
<Compile Include="ClientTests\ServerConnectionTest.cs" />
<Compile Include="ClientTests\SocketTest.cs" />
<Compile Include="ClientTests\SSLServerConnectionTest.cs" />
<Compile Include="ClientTests\TransportTest.cs" />
<Compile Include="ClientTests\UsageTest.cs" />
<Compile Include="ComponentEmitterTests\EmitterTests.cs" />
<Compile Include="ModulesTests\ParseQSTests.cs" />
<Compile Include="ModulesTests\UTF8Tests.cs" />
<Compile Include="ParserTests\DecodeTests.cs" />
<Compile Include="ParserTests\TestsParser.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="ThreadTests\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EngineIoClientDotNet.mono\EngineIoClientDotNet.mono.csproj">
<Project>{b6731266-b247-4a63-b10b-f938288248b6}</Project>
<Name>EngineIoClientDotNet.mono</Name>
</ProjectReference>
</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,52 @@
using System.Collections.Immutable;
using Quobject.EngineIoClientDotNet.Modules;
using System.Collections.Generic;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ModulesTests
{
public class ParseQsTests
{
//should parse a querystring and return an object
[Fact]
public void Decode()
{
// Single assignment
var queryObj = ParseQS.Decode("foo=bar");
Assert.Equal("bar", queryObj["foo"]);
// Multiple assignments
queryObj = ParseQS.Decode("france=grenoble&germany=mannheim");
Assert.Equal("grenoble", queryObj["france"]);
Assert.Equal("mannheim", queryObj["germany"]);
// Assignments containing non-alphanumeric characters
queryObj = ParseQS.Decode("india=new%20delhi");
Assert.Equal("new delhi", queryObj["india"]);
}
//should construct a query string from an object'
[Fact]
public void Encode()
{
Dictionary<string, string> obj;
obj = new Dictionary<string, string> {{"a", "b"}};
var imObj = ImmutableDictionary.Create<string, string>().AddRange(obj);
Assert.Equal("a=b", ParseQS.Encode(imObj));
obj = new Dictionary<string, string> {{"a", "b"}, {"c", "d"}};
imObj = ImmutableDictionary.Create<string, string>().AddRange(obj);
Assert.Equal("a=b&c=d", ParseQS.Encode(imObj));
obj = new Dictionary<string, string> {{"a", "b"}, {"c", "tobi rocks"}};
imObj = ImmutableDictionary.Create<string, string>().AddRange(obj);
Assert.Equal("a=b&c=tobi%20rocks", ParseQS.Encode(imObj));
}
}
}

View File

@@ -0,0 +1,140 @@
using Quobject.EngineIoClientDotNet.Modules;
using System;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ModulesTests
{
public class Utf8Tests
{
private static readonly Data[] DATA = new Data[]
{
// 1-byte
new Data(0x0000, "\x00", "\x00"),
new Data(0x005c, "\u005C\u005C", "\u005C\u005C"), // = backslash
new Data(0x007f, "\u007F", "\u007F"),
// 2-byte
new Data(0x0080, "\u0080", "\u00C2\u0080"),
new Data(0x05CA, "\u05CA", "\u00D7\u008A"),
new Data(0x07FF, "\u07FF", "\u00DF\u00BF"),
// 3-byte
new Data(0x0800, "\u0800", "\u00E0\u00A0\u0080"),
new Data(0x2C3C, "\u2C3C", "\u00E2\u00B0\u00BC"),
new Data(0x07FF, "\uFFFF", "\u00EF\u00BF\u00BF"),
// unmatched surrogate halves
// high surrogates: 0xD800 to 0xDBFF
new Data(0xD800, "\uD800", "\u00ED\u00A0\u0080"),
new Data("High surrogate followed by another high surrogate",
"\uD800\uD800", "\u00ED\u00A0\u0080\u00ED\u00A0\u0080"),
new Data("High surrogate followed by a symbol that is not a surrogate",
"\uD800A", "\u00ED\u00A0\u0080A"),
new Data(
"Unmatched high surrogate, followed by a surrogate pair, followed by an unmatched high surrogate",
"\uD800\uD834\uDF06\uD800", "\u00ED\u00A0\u0080\u00F0\u009D\u008C\u0086\u00ED\u00A0\u0080"),
new Data(0xD9AF, "\uD9AF", "\u00ED\u00A6\u00AF"),
new Data(0xDBFF, "\uDBFF", "\u00ED\u00AF\u00BF"),
// low surrogates: 0xDC00 to 0xDFFF
new Data(0xDC00, "\uDC00", "\u00ED\u00B0\u0080"),
new Data("Low surrogate followed by another low surrogate",
"\uDC00\uDC00", "\u00ED\u00B0\u0080\u00ED\u00B0\u0080"),
new Data("Low surrogate followed by a symbol that is not a surrogate",
"\uDC00A", "\u00ED\u00B0\u0080A"),
new Data(
"Unmatched low surrogate, followed by a surrogate pair, followed by an unmatched low surrogate",
"\uDC00\uD834\uDF06\uDC00", "\u00ED\u00B0\u0080\u00F0\u009D\u008C\u0086\u00ED\u00B0\u0080"),
new Data(0xDEEE, "\uDEEE", "\u00ED\u00BB\u00AE"),
new Data(0xDFFF, "\uDFFF", "\u00ED\u00BF\u00BF"),
// 4-byte
new Data(0x010000, "\uD800\uDC00", "\u00F0\u0090\u0080\u0080"),
new Data(0x01D306, "\uD834\uDF06", "\u00F0\u009D\u008C\u0086"),
new Data(0x010FFF, "\uDBFF\uDFFF", "\u00F4\u008F\u00BF\u00BF"),
};
//
[Fact]
public void EncodeAndDecode()
{
foreach (var data in DATA)
{
data.Test();
}
}
private class Data
{
private readonly int _codePoint = -1;
private String Description { get; set; }
private String Decoded { get; set; }
private String Encoded { get; set; }
public Data(int codePoint, String decoded, String encoded)
{
this._codePoint = codePoint;
this.Decoded = decoded;
this.Encoded = encoded;
}
public Data(String description, String decoded, String encoded)
{
this.Description = description;
this.Decoded = decoded;
this.Encoded = encoded;
}
public void Test()
{
EncodingTest();
DecodingTest();
ExceptionTest();
}
private void EncodingTest()
{
var value = UTF8.Encode(Decoded);
Assert.Equal(Encoded, value);
}
private void DecodingTest()
{
Assert.Equal(Decoded, UTF8.Decode(Encoded));
}
private void ExceptionTest()
{
Assert.Throws<UTF8Exception>(
delegate
{
UTF8.Decode("\uFFFF");
});
Assert.Throws<UTF8Exception>(
delegate
{
UTF8.Decode("\xE9\x00\x00");
});
Assert.Throws<UTF8Exception>(
delegate
{
UTF8.Decode("\xC2\uFFFF");
});
Assert.Throws<UTF8Exception>(
delegate
{
UTF8.Decode("\xF0\x9D");
});
}
private string Reason
{
get { return Description ?? "U+" + _codePoint.ToString("X4").ToUpper(); }
}
}
}
}

View File

@@ -0,0 +1,82 @@
using Quobject.EngineIoClientDotNet.Modules;
using Quobject.EngineIoClientDotNet.Parser;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ParserTests
{
public class DecodeTests
{
private const string PARSER_ERROR = "parser error";
[Fact]
public void DecodeBadFormat()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger("DecodeTests DecodeBadFormat");
Packet p = Parser.DecodePacket(":::");
Assert.Equal(Packet.ERROR, p.Type);
Assert.Equal(PARSER_ERROR, p.Data);
}
[Fact]
public void DecodeInexistingTypes()
{
Packet p = Parser.DecodePacket("94103");
Assert.Equal(Packet.ERROR, p.Type);
Assert.Equal(PARSER_ERROR, p.Data);
}
[Fact]
public void DecodeInvalidUTF8()
{
Packet p = Parser.DecodePacket("4\uffff", true);
Assert.Equal(Packet.ERROR, p.Type);
Assert.Equal(PARSER_ERROR, p.Data);
}
public class DecodePayloadBadFormat_DecodeCallback : IDecodePayloadCallback
{
public bool Call(Packet packet, int index, int total)
{
var isLast = index + 1 == total;
Assert.True(isLast);
Assert.Equal(Packet.ERROR, packet.Type);
Assert.Equal(PARSER_ERROR, packet.Data);
return true;
}
}
[Fact]
public void EncodeAndDecodeEmptyPayloads()
{
Packet.DecodePayload("1!", new DecodePayloadBadFormat_DecodeCallback());
Packet.DecodePayload("", new DecodePayloadBadFormat_DecodeCallback());
Packet.DecodePayload("))", new DecodePayloadBadFormat_DecodeCallback());
}
[Fact]
public void DecodePayloadBadPacketFormat()
{
Packet.DecodePayload("3:99", new DecodePayloadBadFormat_DecodeCallback());
Packet.DecodePayload("1:aa", new DecodePayloadBadFormat_DecodeCallback());
Packet.DecodePayload("1:a2:b", new DecodePayloadBadFormat_DecodeCallback());
}
[Fact]
public void DecodePayloadInvalidUTF8()
{
Packet.DecodePayload("2:4\uffff", new DecodePayloadBadFormat_DecodeCallback());
}
}
}

View File

@@ -0,0 +1,449 @@
using Quobject.EngineIoClientDotNet.Modules;
using Quobject.EngineIoClientDotNet.Parser;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ParserTests
{
public class TestsParser
{
public interface IPacketTest
{
Packet GetPacket();
}
[Fact]
public void EncodeTests()
{
var testList = new List<IPacketTest>()
{
new EncodeAsStringCallback(),
new DecodeAsPacketCallback(),
new NoDataCallback(),
new EncodeOpenPacket(),
new EncodeClosePacket(),
new EncodePingPacket(),
new EncodePongPacket(),
new EncodeMessagePacket(),
new EncodeUTF8SpecialCharsPacket(),
new EncodeUpgradePacket(),
new EncodeFormat1(),
new EncodeFormat2(),
};
foreach (var test in testList)
{
Parser.EncodePacket(test.GetPacket(), (IEncodeCallback) test);
}
}
public class EncodeAsStringCallback : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Assert.IsType<string>(data);
}
public Packet GetPacket()
{
return new Packet(Packet.MESSAGE, "test");
}
}
public class DecodeAsPacketCallback : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Assert.IsType<Packet>(Parser.DecodePacket((string) data));
}
public Packet GetPacket()
{
return new Packet(Packet.MESSAGE, "test");
}
}
public class NoDataCallback : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.MESSAGE, p.Type);
Assert.Null(p.Data);
}
public Packet GetPacket()
{
return new Packet(Packet.MESSAGE);
}
}
public class EncodeOpenPacket : IEncodeCallback, IPacketTest
{
private static string Json = "{\"some\":\"json\"}";
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.OPEN, p.Type);
Assert.Equal(Json, p.Data);
}
public Packet GetPacket()
{
return new Packet(Packet.OPEN, Json);
}
}
public class EncodeClosePacket : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.CLOSE, p.Type);
}
public Packet GetPacket()
{
return new Packet(Packet.CLOSE);
}
}
public class EncodePingPacket : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.PING, p.Type);
Assert.Equal("1", p.Data);
}
public Packet GetPacket()
{
return new Packet(Packet.PING, "1");
}
}
public class EncodePongPacket : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.PONG, p.Type);
Assert.Equal("1", p.Data);
}
public Packet GetPacket()
{
return new Packet(Packet.PONG, "1");
}
}
public class EncodeMessagePacket : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.MESSAGE, p.Type);
Assert.Equal("aaa", p.Data);
}
public Packet GetPacket()
{
return new Packet(Packet.MESSAGE, "aaa");
}
}
public class EncodeUTF8SpecialCharsPacket : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.MESSAGE, p.Type);
Assert.Equal("utf8 — string", p.Data);
}
public Packet GetPacket()
{
return new Packet(Packet.MESSAGE, "utf8 — string");
}
}
public class EncodeUpgradePacket : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.UPGRADE, p.Type);
}
public Packet GetPacket()
{
return new Packet(Packet.UPGRADE);
}
}
public class EncodeFormat1 : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
var dataString = data as string;
var r = new Regex(@"[0-9]", RegexOptions.IgnoreCase);
Assert.True(r.Match(dataString).Success);
}
public Packet GetPacket()
{
return new Packet(Packet.MESSAGE);
}
}
public class EncodeFormat2 : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
var dataString = data as string;
Assert.Equal("4test", dataString);
}
public Packet GetPacket()
{
return new Packet(Packet.MESSAGE, "test");
}
}
public class EncodePayloadsCallback : IEncodeCallback
{
public void Call(object data)
{
Assert.IsType<byte[]>(data);
}
}
[Fact]
public void EncodePayloads()
{
var packets = new Packet[] {new Packet(Packet.PING), new Packet(Packet.PONG),};
Parser.EncodePayload(packets, new EncodePayloadsCallback());
}
public class EncodeAndDecodePayloads_EncodeCallback : IEncodeCallback
{
public void Call(object data)
{
Parser.DecodePayload((byte[]) data, new EncodeAndDecodePayloads_DecodeCallback());
}
public class EncodeAndDecodePayloads_DecodeCallback : IDecodePayloadCallback
{
public bool Call(Packet packet, int index, int total)
{
bool isLast = index + 1 == total;
Assert.True(isLast);
return true;
}
}
}
[Fact]
public void EncodeAndDecodePayloads()
{
var packets = new Packet[] {new Packet(Packet.MESSAGE, "a"),};
Parser.EncodePayload(packets, new EncodeAndDecodePayloads_EncodeCallback());
}
public class EncodeAndDecodePayloads_EncodeCallback2 : IEncodeCallback
{
public void Call(object data)
{
Parser.DecodePayload((byte[]) data, new EncodeAndDecodePayloads_DecodeCallback2());
}
public class EncodeAndDecodePayloads_DecodeCallback2 : IDecodePayloadCallback
{
public bool Call(Packet packet, int index, int total)
{
var isLast = index + 1 == total;
Assert.Equal(isLast ? Packet.PING : Packet.MESSAGE, packet.Type);
return true;
}
}
}
[Fact]
public void EncodeAndDecodePayloads2()
{
var packets = new Packet[] {new Packet(Packet.MESSAGE, "a"), new Packet(Packet.PING),};
Parser.EncodePayload(packets, new EncodeAndDecodePayloads_EncodeCallback2());
}
public class EncodeAndDecodeEmptyPayloads_EncodeCallback : IEncodeCallback
{
public void Call(object data)
{
Parser.DecodePayload((byte[]) data, new EncodeAndDecodeEmptyPayloads_DecodeCallback());
}
public class EncodeAndDecodeEmptyPayloads_DecodeCallback : IDecodePayloadCallback
{
public bool Call(Packet packet, int index, int total)
{
Assert.Equal(Packet.OPEN, packet.Type);
var isLast = index + 2 == total;
Assert.True(isLast);
return true;
}
}
}
[Fact]
public void EncodeAndDecodeEmptyPayloads()
{
var packets = new Packet[] {};
Parser.EncodePayload(packets, new EncodeAndDecodeEmptyPayloads_EncodeCallback());
}
public class EncodeAndDecodeBinaryContents_EncodeCallback : IEncodeCallback
{
public void Call(object data)
{
Parser.DecodePayload((byte[]) data, new EncodeAndDecodeBinaryContents_DecodeCallback());
}
public class EncodeAndDecodeBinaryContents_DecodeCallback : IDecodePayloadCallback
{
public bool Call(Packet packet, int index, int total)
{
Assert.Equal(Packet.MESSAGE, packet.Type);
var isLast = index + 1 == total;
if (!isLast)
{
Assert.Equal(FirstBuffer(), packet.Data);
}
else
{
Assert.Equal(SecondBuffer(), packet.Data);
}
return true;
}
}
}
[Fact]
public void EncodeAndDecodeBinaryContents()
{
var firstBuffer = FirstBuffer();
var secondBuffer = SecondBuffer();
var packets = new Packet[]
{new Packet(Packet.MESSAGE, firstBuffer), new Packet(Packet.MESSAGE, secondBuffer)};
Parser.EncodePayload(packets, new EncodeAndDecodeBinaryContents_EncodeCallback());
}
private static byte[] SecondBuffer()
{
var secondBuffer = new byte[4];
for (int i = 0; i < secondBuffer.Length; i++)
{
secondBuffer[i] = (byte) (5 + i);
}
return secondBuffer;
}
private static byte[] FirstBuffer()
{
var firstBuffer = new byte[5];
for (int i = 0; i < firstBuffer.Length; i++)
{
firstBuffer[i] = (byte) i;
}
return firstBuffer;
}
private static byte[] ThirdBuffer()
{
var result = new byte[123];
for (int i = 0; i < result.Length; i++)
{
result[i] = (byte) i;
}
return result;
}
public class EncodeMixedBinaryAndStringContents_EncodeCallback : IEncodeCallback
{
public void Call(object data)
{
Parser.DecodePayload((byte[]) data, new EncodeMixedBinaryAndStringContents_DecodeCallback());
}
public class EncodeMixedBinaryAndStringContents_DecodeCallback : IDecodePayloadCallback
{
public bool Call(Packet packet, int index, int total)
{
if (index == 0)
{
Assert.Equal(Packet.MESSAGE, packet.Type);
Assert.Equal(ThirdBuffer(), packet.Data);
}
else if (index == 1)
{
Assert.Equal(Packet.MESSAGE, packet.Type);
Assert.Equal("hello", packet.Data);
}
else
{
Assert.Equal(Packet.CLOSE, packet.Type);
}
return true;
}
}
}
[Fact]
public void EncodeMixedBinaryAndStringContents()
{
var packets = new Packet[]
{
new Packet(Packet.MESSAGE, ThirdBuffer()),
new Packet(Packet.MESSAGE, "hello"),
new Packet(Packet.CLOSE),
};
Parser.EncodePayload(packets, new EncodeMixedBinaryAndStringContents_EncodeCallback());
}
}
}

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,43 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.NETCore.Platforms" version="1.1.0" targetFramework="net45" />
<package id="NETStandard.Library" version="1.6.1" targetFramework="net45" />
<package id="Newtonsoft.Json" version="10.0.1" targetFramework="net45" />
<package id="SuperSocket.ClientEngine.Core" version="0.8.0.8" targetFramework="net45" />
<package id="System.Collections" version="4.3.0" targetFramework="net45" />
<package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net45" />
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net45" />
<package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net45" />
<package id="System.Diagnostics.Tracing" version="4.3.0" targetFramework="net45" />
<package id="System.Globalization" version="4.3.0" targetFramework="net45" />
<package id="System.IO" version="4.3.0" targetFramework="net45" />
<package id="System.IO.Compression" version="4.3.0" targetFramework="net45" />
<package id="System.Linq" version="4.3.0" targetFramework="net45" />
<package id="System.Linq.Expressions" version="4.3.0" targetFramework="net45" />
<package id="System.Net.Http" version="4.3.1" targetFramework="net45" />
<package id="System.Net.Primitives" version="4.3.0" targetFramework="net45" />
<package id="System.ObjectModel" version="4.3.0" targetFramework="net45" />
<package id="System.Reflection" version="4.3.0" targetFramework="net45" />
<package id="System.Reflection.Extensions" version="4.3.0" targetFramework="net45" />
<package id="System.Reflection.Primitives" version="4.3.0" targetFramework="net45" />
<package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net45" />
<package id="System.Runtime" version="4.3.0" targetFramework="net45" />
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net45" />
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net45" />
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net45" />
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net45" />
<package id="System.Text.Encoding" version="4.3.0" targetFramework="net45" />
<package id="System.Text.Encoding.Extensions" version="4.3.0" targetFramework="net45" />
<package id="System.Text.RegularExpressions" version="4.3.0" targetFramework="net45" />
<package id="System.Threading" version="4.3.0" targetFramework="net45" />
<package id="System.Threading.Tasks" version="4.3.0" targetFramework="net45" />
<package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="net45" />
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="net45" />
<package id="WebSocket4Net" version="0.15.0-beta6" targetFramework="net45" />
<package id="xunit" version="2.2.0" targetFramework="net45" />
<package id="xunit.abstractions" version="2.0.1" targetFramework="net45" />
<package id="xunit.assert" version="2.2.0" targetFramework="net45" />
<package id="xunit.core" version="2.2.0" targetFramework="net45" />
<package id="xunit.extensibility.core" version="2.2.0" targetFramework="net45" />
<package id="xunit.extensibility.execution" version="2.2.0" targetFramework="net45" />
</packages>

View File

@@ -0,0 +1,186 @@
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.Modules;
using System.Collections.Generic;
using System.Threading;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class BinaryPollingTest : Connection
{
//[Fact]
//public void PingTest()
//{
// var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
// log.Info("Start");
// var binaryData = new byte[5];
// for (int i = 0; i < binaryData.Length; i++)
// {
// binaryData[i] = (byte)i;
// }
// var events = new Queue<object>();
// var options = CreateOptions();
// options.Transports = new List<string>(){"polling"};
// var socket = new Socket(options);
// socket.On(Socket.EVENT_OPEN, () =>
// {
// log.Info("EVENT_OPEN");
// socket.Send(binaryData);
// socket.Send("cash money €€€");
// });
// socket.On(Socket.EVENT_MESSAGE, (d) =>
// {
// var data = d as string;
// log.Info(string.Format("EVENT_MESSAGE data ={0} d = {1} ", data, d));
// if (data == "hi")
// {
// return;
// }
// events.Enqueue(d);
// //socket.Close();
// });
// socket.Open();
// Task.Delay(20000).Wait();
// socket.Close();
// log.Info("ReceiveBinaryData end");
// var binaryData2 = new byte[5];
// for (int i = 0; i < binaryData2.Length; i++)
// {
// binaryData2[i] = (byte)(i + 1);
// }
// object result;
// events.TryDequeue(out result);
// Assert.Equal("1", "1");
//}
private ManualResetEvent _manualResetEvent = null;
[Fact]
public void ReceiveBinaryData()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var events = new Queue<object>();
var binaryData = new byte[5];
for (int i = 0; i < binaryData.Length; i++)
{
binaryData[i] = (byte)i;
}
var options = CreateOptions();
options.Transports = new List<string>() { "polling" };
var socket = new Socket(options);
socket.On(Socket.EVENT_OPEN, () =>
{
log.Info("EVENT_OPEN");
socket.Send(binaryData);
//socket.Send("cash money €€€");
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = d as string;
log.Info(string.Format("EVENT_MESSAGE data ={0} d = {1} ", data, d));
if (data == "hi")
{
return;
}
events.Enqueue(d);
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
log.Info("ReceiveBinaryData end");
var binaryData2 = new byte[5];
for (int i = 0; i < binaryData2.Length; i++)
{
binaryData2[i] = (byte)(i + 1);
}
object result;
result = events.Dequeue();
Assert.Equal(binaryData, result);
}
[Fact]
public void ReceiveBinaryDataAndMultibyteUTF8String()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var events = new Queue<object>();
var binaryData = new byte[5];
for (int i = 0; i < binaryData.Length; i++)
{
binaryData[i] = (byte)i;
}
const string stringData = "cash money €€€";
var options = CreateOptions();
options.Transports = new List<string>() { "polling" };
var socket = new Socket(options);
socket.On(Socket.EVENT_OPEN, () =>
{
log.Info("EVENT_OPEN");
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = d as string;
log.Info(string.Format("EVENT_MESSAGE data ={0} d = {1} ", data, d));
if (data == "hi")
{
return;
}
events.Enqueue(d);
if (events.Count > 1)
{
_manualResetEvent.Set();
}
});
socket.Send(binaryData);
socket.Send(stringData);
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
var binaryData2 = new byte[5];
for (int i = 0; i < binaryData2.Length; i++)
{
binaryData2[i] = (byte)(i + 1);
}
object result;
result = events.Dequeue();
Assert.Equal(binaryData, result);
result = events.Dequeue();
Assert.Equal(stringData, (string)result);
socket.Close();
}
}
}

View File

@@ -0,0 +1,138 @@
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.Modules;
using System.Collections.Generic;
using System.Threading;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class BinaryWebSocketTest : Connection
{
private ManualResetEvent _manualResetEvent = null;
[Fact]
public void ReceiveBinaryData()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var events = new Queue<object>();
var binaryData = new byte[5];
for (int i = 0; i < binaryData.Length; i++)
{
binaryData[i] = (byte)(i + 0);
}
var options = CreateOptions();
var socket = new Socket(options);
socket.On(Socket.EVENT_OPEN, () =>
{
log.Info(Socket.EVENT_OPEN);
});
socket.On(Socket.EVENT_UPGRADE, () =>
{
log.Info(Socket.EVENT_UPGRADE);
socket.Send(binaryData);
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = d as string;
log.Info(string.Format("EVENT_MESSAGE data ={0} d = {1} ", data, d));
if (data == "hi")
{
return;
}
events.Enqueue(d);
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
log.Info("ReceiveBinaryData end");
var binaryData2 = new byte[5];
for (int i = 0; i < binaryData2.Length; i++)
{
binaryData2[i] = (byte)(i + 1);
}
object result;
result = events.Dequeue();
Assert.Equal(binaryData, result);
}
[Fact]
public void ReceiveBinaryDataAndMultibyteUTF8String()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var events = new Queue<object>();
var binaryData = new byte[5];
for (int i = 0; i < binaryData.Length; i++)
{
binaryData[i] = (byte)i;
}
const string stringData = "Ä ä Ü ü ß";
var options = CreateOptions();
var socket = new Socket(options);
socket.On(Socket.EVENT_OPEN, () =>
{
log.Info("EVENT_OPEN");
});
socket.On(Socket.EVENT_UPGRADE, () =>
{
log.Info(Socket.EVENT_UPGRADE);
socket.Send(binaryData);
socket.Send(stringData);
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = d as string;
log.Info(string.Format("EVENT_MESSAGE data ={0} d = {1} ", data, d));
if (data == "hi")
{
return;
}
events.Enqueue(d);
if (events.Count > 1)
{
_manualResetEvent.Set();
}
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
var binaryData2 = new byte[5];
for (int i = 0; i < binaryData2.Length; i++)
{
binaryData2[i] = (byte)(i + 1);
}
object result;
result = events.Dequeue();
Assert.Equal(binaryData, result);
result = events.Dequeue();
Assert.Equal(stringData, (string)result);
log.Info("ReceiveBinaryDataAndMultibyteUTF8String end");
}
}
}

View File

@@ -0,0 +1,44 @@
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.Modules;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class Connection
{
static Connection()
{
LogManager.SetupLogManager();
}
protected Socket.Options CreateOptions()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
//var config = ConfigBase.Load();
var options = new Socket.Options
{
Port = ConnectionConstants.PORT,
Hostname = ConnectionConstants.HOSTNAME
};
log.Info("Please add to your hosts file: 127.0.0.1 " + options.Hostname);
return options;
}
protected Socket.Options CreateOptionsSecure()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
//var config = ConfigBase.Load();
var options = new Socket.Options
{
Port = ConnectionConstants.SSL_PORT,
Hostname = ConnectionConstants.HOSTNAME,
Secure = true,
IgnoreServerCertificateValidation = true
};
log.Info("Please add to your hosts file: 127.0.0.1 " + options.Hostname);
return options;
}
}
}

View File

@@ -0,0 +1,10 @@
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public static class ConnectionConstants
{
public static int PORT = 80;
public static string HOSTNAME = "testme.quobject.com";
public static int SSL_PORT = 443;
public static readonly int TIMEOUT = 300000;
}
}

View File

@@ -0,0 +1,227 @@
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.ComponentEmitter;
using Quobject.EngineIoClientDotNet.Modules;
using System;
using System.Collections.Generic;
using System.Threading;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class ConnectionTest : Connection
{
private ManualResetEvent _manualResetEvent = null;
private Socket socket;
public string Message;
[Fact]
public void ConnectToLocalhost()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var options = CreateOptions();
socket = new Socket(options);
socket.On(Socket.EVENT_OPEN, new TestListener());
socket.On(Socket.EVENT_MESSAGE, new MessageListener(socket, this));
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
Assert.Equal("hi", this.Message);
}
public class TestListener : IListener
{
public void Call(params object[] args)
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("open");
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
public class MessageListener : IListener
{
private Socket socket;
private ConnectionTest connectionTest;
public MessageListener(Socket socket)
{
this.socket = socket;
}
public MessageListener(Socket socket, ConnectionTest connectionTest)
{
this.socket = socket;
this.connectionTest = connectionTest;
}
public void Call(params object[] args)
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("message = " + args[0]);
connectionTest.Message = (string)args[0];
connectionTest._manualResetEvent.Set();
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
[Fact]
public void ConnectToLocalhost2()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
this.Message = "";
var options = CreateOptions();
options.Transports = new List<string>() { "polling" };
socket = new Socket(options);
//socket = new Socket(CreateOptions());
socket.On(Socket.EVENT_OPEN, () =>
{
log.Info("open");
//socket.Send("test send");
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = (string)d;
log.Info("message2 = " + data);
this.Message = data;
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
Assert.Equal("hi", this.Message);
}
[Fact]
public void TestmultibyteUtf8StringsWithPolling()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
const string SendMessage = "cash money €€€";
socket = new Socket(CreateOptions());
socket.On(Socket.EVENT_OPEN, () =>
{
log.Info("open");
socket.Send(SendMessage);
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = (string)d;
log.Info("TestMessage data = " + data);
if (data == "hi")
{
return;
}
this.Message = data;
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
log.Info("TestmultibyteUtf8StringsWithPolling this.Message = " + this.Message);
Assert.Equal(SendMessage, this.Message);
}
[Fact]
public void Testemoji()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
const string SendMessage = "\uD800-\uDB7F\uDB80-\uDBFF\uDC00-\uDFFF\uE000-\uF8FF";
var options = CreateOptions();
socket = new Socket(options);
socket.On(Socket.EVENT_OPEN, () =>
{
log.Info("open");
socket.Send(SendMessage);
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = (string)d;
log.Info(Socket.EVENT_MESSAGE);
if (data == "hi")
{
return;
}
this.Message = data;
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
Assert.True(SendMessage == this.Message);
}
[Fact]
public void NotSendPacketsIfSocketCloses()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var noPacket = true;
socket = new Socket(CreateOptions());
socket.On(Socket.EVENT_OPEN, () =>
{
noPacket = true;
});
socket.Open();
socket.On(Socket.EVENT_PACKET_CREATE, () =>
{
noPacket = false;
log.Info("NotSendPacketsIfSocketCloses EVENT_PACKET_CREATE noPacket = " + noPacket);
});
socket.Close();
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
//await Task.Delay(1000);
log.Info("NotSendPacketsIfSocketCloses end noPacket = " + noPacket);
Assert.True(noPacket);
}
}
}

View File

@@ -0,0 +1,26 @@
using Quobject.EngineIoClientDotNet.Client;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class HandshakeDataTests
{
[Fact]
public void Test()
{
var json = @"{
sid: 'nne323',
upgrades: ['u1','u2'],
pingInterval: 12,
pingTimeout: 23
}";
var handshakeData = new HandshakeData(json);
Assert.Equal("u1", handshakeData.Upgrades[0]);
Assert.Equal("u2", handshakeData.Upgrades[1]);
Assert.Equal(12, handshakeData.PingInterval);
Assert.Equal(23, handshakeData.PingTimeout);
}
}
}

View File

@@ -0,0 +1,283 @@
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.Client.Transports;
using Quobject.EngineIoClientDotNet.ComponentEmitter;
using Quobject.EngineIoClientDotNet.Modules;
using System.Collections.Generic;
using System.Threading;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class SSLServerConnectionTest : Connection
{
private ManualResetEvent _manualResetEvent = null;
[Fact]
public void OpenAndClose()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var events = new Queue<string>();
var socket = new Socket(CreateOptionsSecure());
socket.On(Socket.EVENT_OPEN, () =>
{
log.Info("EVENT_OPEN");
events.Enqueue(Socket.EVENT_OPEN);
socket.Close();
});
socket.On(Socket.EVENT_CLOSE, () =>
{
log.Info("EVENT_CLOSE");
events.Enqueue(Socket.EVENT_CLOSE);
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
string result;
result = events.Dequeue();
Assert.Equal(Socket.EVENT_OPEN, result);
result = events.Dequeue();
Assert.Equal(Socket.EVENT_CLOSE, result);
}
[Fact]
public void Messages()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var events = new Queue<string>();
var socket = new Socket(CreateOptionsSecure());
socket.On(Socket.EVENT_OPEN, () =>
{
log.Info("EVENT_OPEN");
socket.Send("hello");
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = (string)d;
log.Info("EVENT_MESSAGE data = " + data);
events.Enqueue(data);
if (events.Count > 1)
{
_manualResetEvent.Set();
}
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
string result;
result = events.Dequeue();
Assert.Equal("hi", result);
result = events.Dequeue();
Assert.Equal("hello", result);
}
[Fact]
public void Handshake()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
HandshakeData handshake_data = null;
var socket = new Socket(CreateOptionsSecure());
socket.On(Socket.EVENT_HANDSHAKE, (data) =>
{
log.Info(Socket.EVENT_HANDSHAKE + string.Format(" data = {0}", data));
handshake_data = data as HandshakeData;
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
Assert.NotNull(handshake_data);
Assert.NotNull(handshake_data.Upgrades);
Assert.True(handshake_data.Upgrades.Count > 0);
Assert.True(handshake_data.PingInterval > 0);
Assert.True(handshake_data.PingTimeout > 0);
}
public class TestHandshakeListener : IListener
{
public HandshakeData HandshakeData;
private SSLServerConnectionTest serverConnectionTest;
public TestHandshakeListener(SSLServerConnectionTest serverConnectionTest)
{
this.serverConnectionTest = serverConnectionTest;
}
public void Call(params object[] args)
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info(string.Format("open args[0]={0} args.Length={1}", args[0], args.Length));
HandshakeData = args[0] as HandshakeData;
serverConnectionTest._manualResetEvent.Set();
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
[Fact]
public void Handshake2()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var socket = new Socket(CreateOptionsSecure());
var testListener = new TestHandshakeListener(this);
socket.On(Socket.EVENT_HANDSHAKE, testListener);
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
Assert.NotNull(testListener.HandshakeData);
Assert.NotNull(testListener.HandshakeData.Upgrades);
Assert.True(testListener.HandshakeData.Upgrades.Count > 0);
Assert.True(testListener.HandshakeData.PingInterval > 0);
Assert.True(testListener.HandshakeData.PingTimeout > 0);
}
[Fact]
public void Upgrade()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var events = new Queue<object>();
var socket = new Socket(CreateOptionsSecure());
socket.On(Socket.EVENT_UPGRADING, (data) =>
{
log.Info(Socket.EVENT_UPGRADING + string.Format(" data = {0}", data));
events.Enqueue(data);
});
socket.On(Socket.EVENT_UPGRADE, (data) =>
{
log.Info(Socket.EVENT_UPGRADE + string.Format(" data = {0}", data));
events.Enqueue(data);
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
object test = null;
test = events.Dequeue();
Assert.NotNull(test);
Assert.IsAssignableFrom<Transport>(test);
test = events.Dequeue();
Assert.NotNull(test);
Assert.IsAssignableFrom<Transport>(test);
}
[Fact]
public void RememberWebsocket()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var socket1 = new Socket(CreateOptionsSecure());
string socket1TransportName = null;
string socket2TransportName = null;
socket1.On(Socket.EVENT_OPEN, () =>
{
log.Info("EVENT_OPEN");
socket1TransportName = socket1.Transport.Name;
});
socket1.On(Socket.EVENT_UPGRADE, (data) =>
{
log.Info(Socket.EVENT_UPGRADE + string.Format(" data = {0}", data));
var transport = (Transport)data;
socket1.Close();
if (WebSocket.NAME == transport.Name)
{
var options = CreateOptionsSecure();
options.RememberUpgrade = true;
var socket2 = new Socket(options);
socket2.Open();
socket2TransportName = socket2.Transport.Name;
socket2.Close();
_manualResetEvent.Set();
}
});
socket1.Open();
_manualResetEvent.WaitOne();
Assert.Equal(Polling.NAME, socket1TransportName);
Assert.Equal(WebSocket.NAME, socket2TransportName);
}
[Fact]
public void NotRememberWebsocket()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var socket1 = new Socket(CreateOptionsSecure());
string socket1TransportName = null;
string socket2TransportName = null;
socket1.On(Socket.EVENT_OPEN, () =>
{
log.Info("EVENT_OPEN");
socket1TransportName = socket1.Transport.Name;
});
socket1.On(Socket.EVENT_UPGRADE, (data) =>
{
log.Info(Socket.EVENT_UPGRADE + string.Format(" data = {0}", data));
var transport = (Transport)data;
if (WebSocket.NAME == transport.Name)
{
socket1.Close();
var options = CreateOptionsSecure();
options.RememberUpgrade = false;
var socket2 = new Socket(options);
socket2.On(Socket.EVENT_OPEN, () =>
{
log.Info("EVENT_OPEN socket 2");
socket2TransportName = socket2.Transport.Name;
socket2.Close();
_manualResetEvent.Set();
});
socket2.Open();
}
});
socket1.Open();
_manualResetEvent.WaitOne();
Assert.Equal(Polling.NAME, socket1TransportName);
Assert.Equal(Polling.NAME, socket2TransportName);
}
}
}

View File

@@ -0,0 +1,373 @@
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.Client.Transports;
using Quobject.EngineIoClientDotNet.ComponentEmitter;
using Quobject.EngineIoClientDotNet.Modules;
using System.Collections.Generic;
using System.Threading;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class ServerConnectionTest : Connection
{
private ManualResetEvent _manualResetEvent = null;
[Fact]
public void OpenAndClose()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var events = new Queue<string>();
var socket = new Socket(CreateOptions());
socket.On(Socket.EVENT_OPEN, () =>
{
log.Info("EVENT_OPEN");
events.Enqueue(Socket.EVENT_OPEN);
socket.Close();
});
socket.On(Socket.EVENT_CLOSE, () =>
{
log.Info("EVENT_CLOSE");
events.Enqueue(Socket.EVENT_CLOSE);
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
string result;
result = events.Dequeue();
Assert.Equal(Socket.EVENT_OPEN, result);
result = events.Dequeue();
Assert.Equal(Socket.EVENT_CLOSE, result);
}
[Fact]
public void Messages()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var events = new Queue<string>();
var socket = new Socket(CreateOptions());
socket.On(Socket.EVENT_OPEN, () =>
{
log.Info("EVENT_OPEN");
socket.Send("hello");
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = (string)d;
log.Info("EVENT_MESSAGE data = " + data);
events.Enqueue(data);
if (events.Count > 1)
{
_manualResetEvent.Set();
}
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
string result;
result = events.Dequeue();
Assert.Equal("hi", result);
result = events.Dequeue();
Assert.Equal("hello", result);
}
[Fact]
public void Handshake()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
HandshakeData handshake_data = null;
var socket = new Socket(CreateOptions());
socket.On(Socket.EVENT_HANDSHAKE, (data) =>
{
log.Info(Socket.EVENT_HANDSHAKE + string.Format(" data = {0}", data));
handshake_data = data as HandshakeData;
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
Assert.NotNull(handshake_data);
Assert.NotNull(handshake_data.Upgrades);
Assert.True(handshake_data.Upgrades.Count > 0);
Assert.True(handshake_data.PingInterval > 0);
Assert.True(handshake_data.PingTimeout > 0);
}
public class TestHandshakeListener : IListener
{
public HandshakeData HandshakeData;
private ServerConnectionTest serverConnectionTest;
public TestHandshakeListener(ServerConnectionTest serverConnectionTest)
{
this.serverConnectionTest = serverConnectionTest;
}
public void Call(params object[] args)
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info(string.Format("open args[0]={0} args.Length={1}", args[0], args.Length));
HandshakeData = args[0] as HandshakeData;
serverConnectionTest._manualResetEvent.Set();
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
[Fact]
public void Handshake2()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var socket = new Socket(CreateOptions());
var testListener = new TestHandshakeListener(this);
socket.On(Socket.EVENT_HANDSHAKE, testListener);
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
Assert.NotNull(testListener.HandshakeData);
Assert.NotNull(testListener.HandshakeData.Upgrades);
Assert.True(testListener.HandshakeData.Upgrades.Count > 0);
Assert.True(testListener.HandshakeData.PingInterval > 0);
Assert.True(testListener.HandshakeData.PingTimeout > 0);
}
[Fact]
public void Upgrade()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var events = new Queue<object>();
var socket = new Socket(CreateOptions());
socket.On(Socket.EVENT_UPGRADING, (data) =>
{
log.Info(Socket.EVENT_UPGRADING + string.Format(" data = {0}", data));
events.Enqueue(data);
});
socket.On(Socket.EVENT_UPGRADE, (data) =>
{
log.Info(Socket.EVENT_UPGRADE + string.Format(" data = {0}", data));
events.Enqueue(data);
_manualResetEvent.Set();
});
socket.Open();
_manualResetEvent.WaitOne();
object test = null;
test = events.Dequeue();
Assert.NotNull(test);
Assert.IsAssignableFrom<Transport>(test);
test = events.Dequeue();
Assert.NotNull(test);
Assert.IsAssignableFrom<Transport>(test);
}
[Fact]
public void RememberWebsocket()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var socket1 = new Socket(CreateOptions());
string socket1TransportName = null;
string socket2TransportName = null;
socket1.On(Socket.EVENT_OPEN, () =>
{
log.Info("EVENT_OPEN");
socket1TransportName = socket1.Transport.Name;
});
socket1.On(Socket.EVENT_UPGRADE, (data) =>
{
log.Info(Socket.EVENT_UPGRADE + string.Format(" data = {0}", data));
var transport = (Transport)data;
socket1.Close();
if (WebSocket.NAME == transport.Name)
{
var options = CreateOptions();
options.RememberUpgrade = true;
var socket2 = new Socket(options);
socket2.Open();
socket2TransportName = socket2.Transport.Name;
socket2.Close();
_manualResetEvent.Set();
}
});
socket1.Open();
_manualResetEvent.WaitOne();
Assert.Equal(Polling.NAME, socket1TransportName);
Assert.Equal(WebSocket.NAME, socket2TransportName);
}
[Fact]
public void NotRememberWebsocket()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var socket1 = new Socket(CreateOptions());
string socket1TransportName = null;
string socket2TransportName = null;
socket1.On(Socket.EVENT_OPEN, () =>
{
log.Info("EVENT_OPEN");
socket1TransportName = socket1.Transport.Name;
});
socket1.On(Socket.EVENT_UPGRADE, (data) =>
{
log.Info(Socket.EVENT_UPGRADE + string.Format(" data = {0}", data));
var transport = (Transport)data;
if (WebSocket.NAME == transport.Name)
{
socket1.Close();
var options = CreateOptions();
options.RememberUpgrade = false;
var socket2 = new Socket(options);
socket2.On(Socket.EVENT_OPEN, () =>
{
log.Info("EVENT_OPEN socket 2");
socket2TransportName = socket2.Transport.Name;
socket2.Close();
_manualResetEvent.Set();
});
socket2.Open();
}
});
socket1.Open();
_manualResetEvent.WaitOne();
Assert.Equal(Polling.NAME, socket1TransportName);
Assert.Equal(Polling.NAME, socket2TransportName);
}
[Fact]
public void Cookie()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var events = new Queue<string>();
var options = CreateOptions();
options.Cookies.Add("foo", "bar");
var socket = new Socket(options);
socket.On(Socket.EVENT_OPEN, () =>
{
log.Info("EVENT_OPEN");
socket.Send("cookie");
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
var data = (string)d;
log.Info("EVENT_MESSAGE data = " + data);
events.Enqueue(data);
if (events.Count > 1)
{
_manualResetEvent.Set();
}
});
socket.Open();
_manualResetEvent.WaitOne();
socket.Close();
string result;
result = events.Dequeue();
Assert.Equal("hi", result);
result = events.Dequeue();
Assert.Equal("got cookie", result);
}
[Fact]
public void UpgradeCookie()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
_manualResetEvent = new ManualResetEvent(false);
var events = new Queue<object>();
var options = CreateOptions();
options.Cookies.Add("foo", "bar");
var socket = new Socket(options);
socket.On(Socket.EVENT_UPGRADING, (data) =>
{
log.Info(Socket.EVENT_UPGRADING + string.Format(" data = {0}", data));
events.Enqueue(data);
});
socket.On(Socket.EVENT_UPGRADE, (data) =>
{
log.Info(Socket.EVENT_UPGRADE + string.Format(" data = {0}", data));
events.Enqueue(data);
socket.Send("cookie");
});
socket.On(Socket.EVENT_MESSAGE, (d) =>
{
if (events.Count > 1)
{
var data = (string)d;
log.Info("EVENT_MESSAGE data = " + data);
events.Enqueue(data);
_manualResetEvent.Set();
}
});
socket.Open();
_manualResetEvent.WaitOne();
object test = null;
test = events.Dequeue();
Assert.NotNull(test);
Assert.IsAssignableFrom<Transport>(test);
test = events.Dequeue();
Assert.NotNull(test);
Assert.IsAssignableFrom<Transport>(test);
test = events.Dequeue();
Assert.Equal("got cookie", test);
}
}
}

View File

@@ -0,0 +1,77 @@
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.Modules;
using System;
using System.Collections.Generic;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class SocketTest : Connection
{
private Socket socket;
public string Message;
[Fact]
public void FilterUpgrades()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var options = CreateOptions();
options.Transports = new List<string>() { "polling" };
socket = new Socket(options);
var List = socket.FilterUpgrades(new List<string>() { "polling", "websocket" });
Assert.Equal("polling", List[0]);
Assert.Equal(1, List.Count);
}
[Fact]
public void SocketClosing()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var closed = false;
var error = false;
var options = CreateOptions();
socket = new Socket("ws://0.0.0.0:8080", options);
socket.On(Socket.EVENT_OPEN, () =>
{
log.Info("EVENT_OPEN");
//socket.Send("test send");
});
socket.On(Socket.EVENT_CLOSE, () =>
{
log.Info("EVENT_CLOSE = ");
closed = true;
});
socket.Once(Socket.EVENT_ERROR, () =>
{
log.Info("EVENT_ERROR = ");
error = true;
});
socket.Open();
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
//Task.Delay(1000);
Assert.True(closed);
Assert.True(error);
}
[Fact]
public void SocketOptionCookies()
{
var options = new Socket.Options();
options.Cookies.Add("foo", "bar");
Assert.Equal("foo=bar", options.GetCookiesAsString());
options.Cookies.Add("name2", "value2");
Assert.Equal("foo=bar; name2=value2", options.GetCookiesAsString());
}
}
}

View File

@@ -0,0 +1,182 @@
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.Client.Transports;
using Quobject.EngineIoClientDotNet.Modules;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
// NOTE: tests for the rememberUpgrade option are on ServerConnectionTest.
public class TransportTest : Connection
{
[Fact]
public void Constructors()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var socket = new Socket(CreateOptions());
socket.Open();
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(3));
Assert.NotNull(socket.Transport);
socket.Close();
}
[Fact]
public void Uri()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var options = new Transport.Options();
options.Path = "/engine.io";
options.Hostname = this.CreateOptions().Hostname;
options.Secure = false;
options.Query = new Dictionary<string, string> { { "sid", "test" } };
options.TimestampRequests = false;
var polling = new Polling(options);
var expected = string.Format("http://{0}/engine.io?sid=test&b64=1", options.Hostname);
Assert.Contains(expected, polling.Uri());
}
[Fact]
public void UriWithDefaultPort()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var options = new Transport.Options();
options.Path = "/engine.io";
options.Hostname = this.CreateOptions().Hostname;
options.Secure = false;
options.Query = new Dictionary<string, string> { { "sid", "test" } };
options.TimestampRequests = false;
options.Port = 80;
var polling = new Polling(options);
//Assert.Contains("http://localhost/engine.io?sid=test&b64=1", polling.Uri());
var expected = string.Format("http://{0}/engine.io?sid=test&b64=1", options.Hostname);
Assert.Contains(expected, polling.Uri());
}
[Fact]
public void UriWithPort()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var options = new Transport.Options();
options.Path = "/engine.io";
options.Hostname = this.CreateOptions().Hostname;
options.Secure = false;
options.Query = new Dictionary<string, string> { { "sid", "test" } };
options.TimestampRequests = false;
options.Port = 3000;
var polling = new Polling(options);
//Assert.Contains("http://localhost:3000/engine.io?sid=test&b64=1", polling.Uri());
var expected = string.Format("http://{0}:{1}/engine.io?sid=test&b64=1", options.Hostname, options.Port);
Assert.Contains(expected, polling.Uri());
}
[Fact]
public void HttpsUriWithDefaultPort()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var options = new Transport.Options();
options.Path = "/engine.io";
options.Hostname = this.CreateOptions().Hostname;
options.Secure = true;
options.Query = new Dictionary<string, string> { { "sid", "test" } };
options.TimestampRequests = false;
options.Port = 443;
var polling = new Polling(options);
//Assert.Contains("https://localhost/engine.io?sid=test&b64=1", polling.Uri());
var expected = string.Format("https://{0}/engine.io?sid=test&b64=1", options.Hostname);
Assert.Contains(expected, polling.Uri());
}
[Fact]
public void TimestampedUri()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var options = new Transport.Options();
options.Path = "/engine.io";
options.Hostname = "test";
options.Secure = false;
options.Query = new Dictionary<string, string> { { "sid", "test" } };
options.TimestampRequests = true;
options.TimestampParam = "t";
var polling = new Polling(options);
string pat = @"http://test/engine.io\?sid=test&(t=[0-9]+-[0-9]+)";
var r = new Regex(pat, RegexOptions.IgnoreCase);
var test = polling.Uri();
log.Info(test);
Match m = r.Match(test);
Assert.True(m.Success);
}
[Fact]
public void WsUri()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var options = new Transport.Options();
options.Path = "/engine.io";
options.Hostname = "test";
options.Secure = false;
options.Query = new Dictionary<string, string> { { "transport", "websocket" } };
options.TimestampRequests = false;
var ws = new WebSocket(options);
Assert.Contains("ws://test/engine.io?transport=websocket", ws.Uri());
}
[Fact]
public void WssUri()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var options = new Transport.Options();
options.Path = "/engine.io";
options.Hostname = "test";
options.Secure = true;
options.Query = new Dictionary<string, string> { { "transport", "websocket" } };
options.TimestampRequests = false;
var ws = new WebSocket(options);
Assert.Contains("wss://test/engine.io?transport=websocket", ws.Uri());
}
[Fact]
public void WsTimestampedUri()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var options = new Transport.Options();
options.Path = "/engine.io";
options.Hostname = "test";
options.Secure = false;
options.Query = new Dictionary<string, string> { { "sid", "test" } };
options.TimestampRequests = true;
options.TimestampParam = "woot";
var ws = new WebSocket(options);
string pat = @"ws://test/engine.io\?sid=test&(woot=[0-9]+-[0-9]+)";
var r = new Regex(pat, RegexOptions.IgnoreCase);
var test = ws.Uri();
log.Info(test);
Match m = r.Match(test);
Assert.True(m.Success);
}
}
}

View File

@@ -0,0 +1,52 @@
using Quobject.EngineIoClientDotNet.Client;
using Quobject.EngineIoClientDotNet.Modules;
using System;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public class UsageTest : Connection
{
[Fact]
public void Usage1()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var options = CreateOptions();
var socket = new Socket(options);
//You can use `Socket` to connect:
//var socket = new Socket("ws://localhost");
socket.On(Socket.EVENT_OPEN, () =>
{
socket.Send("hi");
socket.Close();
});
socket.Open();
//System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
}
[Fact]
public void Usage2()
{
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var options = CreateOptions();
var socket = new Socket(options);
//Receiving data
//var socket = new Socket("ws://localhost:3000");
socket.On(Socket.EVENT_OPEN, () =>
{
socket.On(Socket.EVENT_MESSAGE, (data) => Console.WriteLine((string)data));
});
socket.Open();
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
socket.Close();
}
}
}

View File

@@ -0,0 +1,399 @@
using Quobject.EngineIoClientDotNet.ComponentEmitter;
using Quobject.EngineIoClientDotNet.Modules;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ComponentEmitterTests
{
public class EmitterTests
{
public class TestListener1 : IListener
{
private readonly List<object> _calls;
public TestListener1(List<object> calls)
{
this._calls = calls;
}
public void Call(params object[] args)
{
_calls.Add("one");
_calls.Add(args[0]);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
public class TestListener2 : IListener
{
private readonly List<object> _calls;
public TestListener2(List<object> calls)
{
this._calls = calls;
}
public void Call(params object[] args)
{
_calls.Add("two");
_calls.Add(args[0]);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
[Fact]
public void On()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var emitter = new Emitter();
var calls = new List<object>();
var listener1 = new TestListener1(calls);
emitter.On("foo", listener1);
var listener2 = new TestListener2(calls);
emitter.On("foo", listener2);
emitter.Emit("foo", 1);
emitter.Emit("bar", 1);
emitter.Emit("foo", 2);
var expected = new Object[] {"one", 1, "two", 1, "one", 2, "two", 2};
Assert.Equal(expected, calls.ToArray());
}
[Fact]
public void Once()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var emitter = new Emitter();
var calls = new List<object>();
var listener1 = new TestListener1(calls);
emitter.Once("foo", listener1);
emitter.Emit("foo", 1);
emitter.Emit("foo", 2);
emitter.Emit("foo", 3);
emitter.Emit("bar", 1);
var expected = new Object[] {"one", 1};
Assert.Equal(expected, calls.ToArray());
}
public class TestListener3 : IListener
{
private readonly List<object> _calls;
public TestListener3(List<object> calls)
{
this._calls = calls;
}
public void Call(params object[] args)
{
_calls.Add("one");
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
public class TestListener4 : IListener
{
private readonly List<object> _calls;
public TestListener4(List<object> calls)
{
this._calls = calls;
}
public void Call(params object[] args)
{
_calls.Add("two");
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
[Fact]
public void Off()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var emitter = new Emitter();
var calls = new List<object>();
var listener3 = new TestListener3(calls);
emitter.On("foo", listener3);
var listener4 = new TestListener4(calls);
emitter.On("foo", listener4);
emitter.Off("foo", listener4);
emitter.Emit("foo");
var expected = new Object[] {"one"};
Assert.Equal(expected, calls.ToArray());
}
[Fact]
public void OffWithOnce()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var emitter = new Emitter();
var calls = new List<object>();
var listener3 = new TestListener3(calls);
emitter.Once("foo", listener3);
emitter.Off("foo", listener3);
emitter.Emit("foo");
var expected = new Object[] {};
Assert.Equal(expected, calls.ToArray());
}
public class TestListener5 : IListener
{
private readonly List<bool> _called;
public TestListener5(List<bool> called)
{
this._called = called;
}
public void Call(params object[] args)
{
this._called[0] = true;
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
public class TestListener6 : IListener
{
private readonly Emitter _emitter;
private readonly IListener _bListener;
public TestListener6(Emitter emitter, IListener bListener)
{
this._emitter = emitter;
this._bListener = bListener;
}
public void Call(params object[] args)
{
_emitter.Off("tobi", _bListener);
}
public int CompareTo(IListener other)
{
return this.GetId().CompareTo(other.GetId());
}
public int GetId()
{
return 0;
}
}
[Fact]
public void OffWhenCalledfromEvent()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var emitter = new Emitter();
var called = new List<bool>() {false};
var listener5 = new TestListener5(called);
var listener6 = new TestListener6(emitter, listener5);
emitter.On("tobi", listener6);
emitter.Once("tobi", listener5);
emitter.Emit("tobi");
Assert.True(called[0]);
called[0] = false;
emitter.Emit("tobi");
Assert.False(called[0]);
}
[Fact]
public void OffEvent()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var emitter = new Emitter();
var calls = new List<object>();
var listener3 = new TestListener3(calls);
emitter.On("foo", listener3);
var listener4 = new TestListener4(calls);
emitter.On("foo", listener3);
emitter.On("foo", listener4);
emitter.Off("foo");
emitter.Emit("foo");
emitter.Emit("foo");
var expected = new Object[] {};
Assert.Equal(expected, calls.ToArray());
}
[Fact]
public void OffAll()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var emitter = new Emitter();
var calls = new List<object>();
var listener3 = new TestListener3(calls);
var listener4 = new TestListener4(calls);
emitter.On("foo", listener3);
emitter.On("bar", listener4);
emitter.Emit("foo");
emitter.Emit("bar");
emitter.Off();
emitter.Emit("foo");
emitter.Emit("bar");
var expected = new Object[] {"one", "two"};
Assert.Equal(expected, calls.ToArray());
}
[Fact]
public void Listeners()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var emitter = new Emitter();
var calls = new List<object>();
var listener3 = new TestListener3(calls);
emitter.On("foo", listener3);
var expected = new IListener[] {listener3};
Assert.Equal(expected, emitter.Listeners("foo").ToArray());
}
[Fact]
public void ListenersWithoutHandlers()
{
LogManager.SetupLogManager();
var emitter = new Emitter();
var expected = new IListener[] {};
Assert.Equal(expected, emitter.Listeners("foo").ToArray());
}
[Fact]
public void HasListeners()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var emitter = new Emitter();
var calls = new List<object>();
Assert.False(emitter.HasListeners("foo"));
var listener3 = new TestListener3(calls);
emitter.On("foo", listener3);
Assert.True(emitter.HasListeners("foo"));
}
[Fact]
public void HasListenersWithoutHandlers()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var emitter = new Emitter();
Assert.False(emitter.HasListeners("foo"));
}
}
}

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.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>{BA788BBE-0FE8-4C2F-8A02-457A5E9E2703}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>EngineIoClientDotNet.Tests.net35</RootNamespace>
<AssemblyName>EngineIoClientDotNet.Tests.net35</AssemblyName>
<TargetFrameworkVersion>v3.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=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net35\packages\Newtonsoft.Json.9.0.1\lib\net35\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SuperSocket.ClientEngine, Version=0.9.0.0, Culture=neutral, PublicKeyToken=ee9af13f57f00acc, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net35\packages\SuperSocket.ClientEngine.Core.0.9.0\lib\net35-client\SuperSocket.ClientEngine.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Threading.Tasks.NET35, Version=3.0.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net35\packages\System.Threading.Tasks.Unofficial.3.1\lib\net35\System.Threading.Tasks.NET35.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="WebSocket4Net, Version=0.15.1.10, Culture=neutral, PublicKeyToken=eb4e154b696bf72a, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net35\packages\WebSocket4Net.0.15.1\lib\net35\WebSocket4Net.dll</HintPath>
</Reference>
<Reference Include="xunit, Version=1.9.2.1705, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net35\packages\xunit.1.9.2\lib\net20\xunit.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ClientTests\BinaryPollingTest.cs" />
<Compile Include="ClientTests\BinaryWebSocketTest.cs" />
<Compile Include="ClientTests\Connection.cs" />
<Compile Include="ClientTests\ConnectionConstants.cs" />
<Compile Include="ClientTests\ConnectionTest.cs" />
<Compile Include="ClientTests\HandshakeDataTests.cs" />
<Compile Include="ClientTests\ServerConnectionTest.cs" />
<Compile Include="ClientTests\SocketTest.cs" />
<Compile Include="ClientTests\SSLServerConnectionTest.cs" />
<Compile Include="ClientTests\TransportTest.cs" />
<Compile Include="ClientTests\UsageTest.cs" />
<Compile Include="ComponentEmitterTests\EmitterTests.cs" />
<Compile Include="ModulesTests\ParseQSTests.cs" />
<Compile Include="ModulesTests\UTF8Tests.cs" />
<Compile Include="ParserTests\DecodeTests.cs" />
<Compile Include="ParserTests\TestsParser.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<ProjectReference Include="..\EngineIoClientDotNet.net35\EngineIoClientDotNet.net35.csproj">
<Project>{568d67d0-3253-4601-9b04-7730a9ec5cc0}</Project>
<Name>EngineIoClientDotNet.net35</Name>
</ProjectReference>
</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,68 @@

using System.Collections.Concurrent;
using Quobject.EngineIoClientDotNet.Modules;
using System.Collections.Generic;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ModulesTests
{
public class ParseQsTests
{
//should parse a querystring and return an object
[Fact]
public void Decode()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
// Single assignment
var queryObj = ParseQS.Decode("foo=bar");
Assert.Equal("bar", queryObj["foo"]);
// Multiple assignments
queryObj = ParseQS.Decode("france=grenoble&germany=mannheim");
Assert.Equal("grenoble", queryObj["france"]);
Assert.Equal("mannheim", queryObj["germany"]);
// Assignments containing non-alphanumeric characters
queryObj = ParseQS.Decode("india=new%20delhi");
Assert.Equal("new delhi", queryObj["india"]);
}
//should construct a query string from an object'
[Fact]
public void Encode()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
//Dictionary<string, string> obj;
//obj = new Dictionary<string, string> {{"a", "b"}};
//var imObj = ImmutableDictionary.Create<string, string>().AddRange(obj);
var imObj = new ConcurrentDictionary<string, string>();
imObj.TryAdd("a","b");
Assert.Equal("a=b", ParseQS.Encode(imObj));
//obj = new Dictionary<string, string> {{"a", "b"}, {"c", "d"}};
//imObj = ImmutableDictionary.Create<string, string>().AddRange(obj);
imObj = new ConcurrentDictionary<string, string>();
imObj.TryAdd("a", "b");
imObj.TryAdd("c", "d");
Assert.Equal("a=b&c=d", ParseQS.Encode(imObj));
//obj = new Dictionary<string, string> {{"a", "b"}, {"c", "tobi rocks"}};
//imObj = ImmutableDictionary.Create<string, string>().AddRange(obj);
imObj = new ConcurrentDictionary<string, string>();
imObj.TryAdd("a", "b");
imObj.TryAdd("c", "tobi rocks");
Assert.Equal("a=b&c=tobi%20rocks", ParseQS.Encode(imObj));
}
}
}

View File

@@ -0,0 +1,144 @@
using Quobject.EngineIoClientDotNet.Modules;
using System;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ModulesTests
{
public class Utf8Tests
{
private static readonly Data[] DATA = new Data[]
{
// 1-byte
new Data(0x0000, "\x00", "\x00"),
new Data(0x005c, "\u005C\u005C", "\u005C\u005C"), // = backslash
new Data(0x007f, "\u007F", "\u007F"),
// 2-byte
new Data(0x0080, "\u0080", "\u00C2\u0080"),
new Data(0x05CA, "\u05CA", "\u00D7\u008A"),
new Data(0x07FF, "\u07FF", "\u00DF\u00BF"),
// 3-byte
new Data(0x0800, "\u0800", "\u00E0\u00A0\u0080"),
new Data(0x2C3C, "\u2C3C", "\u00E2\u00B0\u00BC"),
new Data(0x07FF, "\uFFFF", "\u00EF\u00BF\u00BF"),
// unmatched surrogate halves
// high surrogates: 0xD800 to 0xDBFF
new Data(0xD800, "\uD800", "\u00ED\u00A0\u0080"),
new Data("High surrogate followed by another high surrogate",
"\uD800\uD800", "\u00ED\u00A0\u0080\u00ED\u00A0\u0080"),
new Data("High surrogate followed by a symbol that is not a surrogate",
"\uD800A", "\u00ED\u00A0\u0080A"),
new Data(
"Unmatched high surrogate, followed by a surrogate pair, followed by an unmatched high surrogate",
"\uD800\uD834\uDF06\uD800", "\u00ED\u00A0\u0080\u00F0\u009D\u008C\u0086\u00ED\u00A0\u0080"),
new Data(0xD9AF, "\uD9AF", "\u00ED\u00A6\u00AF"),
new Data(0xDBFF, "\uDBFF", "\u00ED\u00AF\u00BF"),
// low surrogates: 0xDC00 to 0xDFFF
new Data(0xDC00, "\uDC00", "\u00ED\u00B0\u0080"),
new Data("Low surrogate followed by another low surrogate",
"\uDC00\uDC00", "\u00ED\u00B0\u0080\u00ED\u00B0\u0080"),
new Data("Low surrogate followed by a symbol that is not a surrogate",
"\uDC00A", "\u00ED\u00B0\u0080A"),
new Data(
"Unmatched low surrogate, followed by a surrogate pair, followed by an unmatched low surrogate",
"\uDC00\uD834\uDF06\uDC00", "\u00ED\u00B0\u0080\u00F0\u009D\u008C\u0086\u00ED\u00B0\u0080"),
new Data(0xDEEE, "\uDEEE", "\u00ED\u00BB\u00AE"),
new Data(0xDFFF, "\uDFFF", "\u00ED\u00BF\u00BF"),
// 4-byte
new Data(0x010000, "\uD800\uDC00", "\u00F0\u0090\u0080\u0080"),
new Data(0x01D306, "\uD834\uDF06", "\u00F0\u009D\u008C\u0086"),
new Data(0x010FFF, "\uDBFF\uDFFF", "\u00F4\u008F\u00BF\u00BF"),
};
//
[Fact]
public void EncodeAndDecode()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
foreach (var data in DATA)
{
data.Test();
}
}
private class Data
{
private readonly int _codePoint = -1;
private String Description { get; set; }
private String Decoded { get; set; }
private String Encoded { get; set; }
public Data(int codePoint, String decoded, String encoded)
{
this._codePoint = codePoint;
this.Decoded = decoded;
this.Encoded = encoded;
}
public Data(String description, String decoded, String encoded)
{
this.Description = description;
this.Decoded = decoded;
this.Encoded = encoded;
}
public void Test()
{
EncodingTest();
DecodingTest();
ExceptionTest();
}
private void EncodingTest()
{
var value = UTF8.Encode(Decoded);
Assert.Equal(Encoded, value);
}
private void DecodingTest()
{
Assert.Equal(Decoded, UTF8.Decode(Encoded));
}
private void ExceptionTest()
{
Assert.Throws<UTF8Exception>(
delegate
{
UTF8.Decode("\uFFFF");
});
Assert.Throws<UTF8Exception>(
delegate
{
UTF8.Decode("\xE9\x00\x00");
});
Assert.Throws<UTF8Exception>(
delegate
{
UTF8.Decode("\xC2\uFFFF");
});
Assert.Throws<UTF8Exception>(
delegate
{
UTF8.Decode("\xF0\x9D");
});
}
private string Reason
{
get { return Description ?? "U+" + _codePoint.ToString("X4").ToUpper(); }
}
}
}
}

View File

@@ -0,0 +1,98 @@
using Quobject.EngineIoClientDotNet.Modules;
using Quobject.EngineIoClientDotNet.Parser;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ParserTests
{
public class DecodeTests
{
private const string PARSER_ERROR = "parser error";
[Fact]
public void DecodeBadFormat()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
Packet p = Parser.DecodePacket(":::");
Assert.Equal(Packet.ERROR, p.Type);
Assert.Equal(PARSER_ERROR, p.Data);
}
[Fact]
public void DecodeInexistingTypes()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
Packet p = Parser.DecodePacket("94103");
Assert.Equal(Packet.ERROR, p.Type);
Assert.Equal(PARSER_ERROR, p.Data);
}
[Fact]
public void DecodeInvalidUTF8()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
Packet p = Parser.DecodePacket("4\uffff", true);
Assert.Equal(Packet.ERROR, p.Type);
Assert.Equal(PARSER_ERROR, p.Data);
}
public class DecodePayloadBadFormat_DecodeCallback : IDecodePayloadCallback
{
public bool Call(Packet packet, int index, int total)
{
var isLast = index + 1 == total;
Assert.True(isLast);
Assert.Equal(Packet.ERROR, packet.Type);
Assert.Equal(PARSER_ERROR, packet.Data);
return true;
}
}
[Fact]
public void EncodeAndDecodeEmptyPayloads()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
Packet.DecodePayload("1!", new DecodePayloadBadFormat_DecodeCallback());
Packet.DecodePayload("", new DecodePayloadBadFormat_DecodeCallback());
Packet.DecodePayload("))", new DecodePayloadBadFormat_DecodeCallback());
}
[Fact]
public void DecodePayloadBadPacketFormat()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
Packet.DecodePayload("3:99", new DecodePayloadBadFormat_DecodeCallback());
Packet.DecodePayload("1:aa", new DecodePayloadBadFormat_DecodeCallback());
Packet.DecodePayload("1:a2:b", new DecodePayloadBadFormat_DecodeCallback());
}
[Fact]
public void DecodePayloadInvalidUTF8()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
Packet.DecodePayload("2:4\uffff", new DecodePayloadBadFormat_DecodeCallback());
}
}
}

View File

@@ -0,0 +1,477 @@
using Quobject.EngineIoClientDotNet.Modules;
using Quobject.EngineIoClientDotNet.Parser;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Xunit;
namespace Quobject.EngineIoClientDotNet_Tests.ParserTests
{
public class TestsParser
{
public interface IPacketTest
{
Packet GetPacket();
}
[Fact]
public void EncodeTests()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var testList = new List<IPacketTest>()
{
new EncodeAsStringCallback(),
new DecodeAsPacketCallback(),
new NoDataCallback(),
new EncodeOpenPacket(),
new EncodeClosePacket(),
new EncodePingPacket(),
new EncodePongPacket(),
new EncodeMessagePacket(),
new EncodeUTF8SpecialCharsPacket(),
new EncodeUpgradePacket(),
new EncodeFormat1(),
new EncodeFormat2(),
};
foreach (var test in testList)
{
Parser.EncodePacket(test.GetPacket(), (IEncodeCallback) test);
}
}
public class EncodeAsStringCallback : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Assert.IsType<string>(data);
}
public Packet GetPacket()
{
return new Packet(Packet.MESSAGE, "test");
}
}
public class DecodeAsPacketCallback : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Assert.IsType<Packet>(Parser.DecodePacket((string) data));
}
public Packet GetPacket()
{
return new Packet(Packet.MESSAGE, "test");
}
}
public class NoDataCallback : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.MESSAGE, p.Type);
Assert.Null(p.Data);
}
public Packet GetPacket()
{
return new Packet(Packet.MESSAGE);
}
}
public class EncodeOpenPacket : IEncodeCallback, IPacketTest
{
private static string Json = "{\"some\":\"json\"}";
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.OPEN, p.Type);
Assert.Equal(Json, p.Data);
}
public Packet GetPacket()
{
return new Packet(Packet.OPEN, Json);
}
}
public class EncodeClosePacket : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.CLOSE, p.Type);
}
public Packet GetPacket()
{
return new Packet(Packet.CLOSE);
}
}
public class EncodePingPacket : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.PING, p.Type);
Assert.Equal("1", p.Data);
}
public Packet GetPacket()
{
return new Packet(Packet.PING, "1");
}
}
public class EncodePongPacket : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.PONG, p.Type);
Assert.Equal("1", p.Data);
}
public Packet GetPacket()
{
return new Packet(Packet.PONG, "1");
}
}
public class EncodeMessagePacket : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.MESSAGE, p.Type);
Assert.Equal("aaa", p.Data);
}
public Packet GetPacket()
{
return new Packet(Packet.MESSAGE, "aaa");
}
}
public class EncodeUTF8SpecialCharsPacket : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.MESSAGE, p.Type);
Assert.Equal("utf8 — string", p.Data);
}
public Packet GetPacket()
{
return new Packet(Packet.MESSAGE, "utf8 — string");
}
}
public class EncodeUpgradePacket : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
Packet p = Parser.DecodePacket((string) data);
Assert.Equal(Packet.UPGRADE, p.Type);
}
public Packet GetPacket()
{
return new Packet(Packet.UPGRADE);
}
}
public class EncodeFormat1 : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
var dataString = data as string;
var r = new Regex(@"[0-9]", RegexOptions.IgnoreCase);
Assert.True(r.Match(dataString).Success);
}
public Packet GetPacket()
{
return new Packet(Packet.MESSAGE);
}
}
public class EncodeFormat2 : IEncodeCallback, IPacketTest
{
public void Call(object data)
{
var dataString = data as string;
Assert.Equal("4test", dataString);
}
public Packet GetPacket()
{
return new Packet(Packet.MESSAGE, "test");
}
}
public class EncodePayloadsCallback : IEncodeCallback
{
public void Call(object data)
{
Assert.IsType<byte[]>(data);
}
}
[Fact]
public void EncodePayloads()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var packets = new Packet[] {new Packet(Packet.PING), new Packet(Packet.PONG),};
Parser.EncodePayload(packets, new EncodePayloadsCallback());
}
public class EncodeAndDecodePayloads_EncodeCallback : IEncodeCallback
{
public void Call(object data)
{
Parser.DecodePayload((byte[]) data, new EncodeAndDecodePayloads_DecodeCallback());
}
public class EncodeAndDecodePayloads_DecodeCallback : IDecodePayloadCallback
{
public bool Call(Packet packet, int index, int total)
{
bool isLast = index + 1 == total;
Assert.True(isLast);
return true;
}
}
}
[Fact]
public void EncodeAndDecodePayloads()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var packets = new Packet[] {new Packet(Packet.MESSAGE, "a"),};
Parser.EncodePayload(packets, new EncodeAndDecodePayloads_EncodeCallback());
}
public class EncodeAndDecodePayloads_EncodeCallback2 : IEncodeCallback
{
public void Call(object data)
{
Parser.DecodePayload((byte[]) data, new EncodeAndDecodePayloads_DecodeCallback2());
}
public class EncodeAndDecodePayloads_DecodeCallback2 : IDecodePayloadCallback
{
public bool Call(Packet packet, int index, int total)
{
var isLast = index + 1 == total;
Assert.Equal(isLast ? Packet.PING : Packet.MESSAGE, packet.Type);
return true;
}
}
}
[Fact]
public void EncodeAndDecodePayloads2()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var packets = new Packet[] {new Packet(Packet.MESSAGE, "a"), new Packet(Packet.PING),};
Parser.EncodePayload(packets, new EncodeAndDecodePayloads_EncodeCallback2());
}
public class EncodeAndDecodeEmptyPayloads_EncodeCallback : IEncodeCallback
{
public void Call(object data)
{
Parser.DecodePayload((byte[]) data, new EncodeAndDecodeEmptyPayloads_DecodeCallback());
}
public class EncodeAndDecodeEmptyPayloads_DecodeCallback : IDecodePayloadCallback
{
public bool Call(Packet packet, int index, int total)
{
Assert.Equal(Packet.OPEN, packet.Type);
var isLast = index + 2 == total;
Assert.True(isLast);
return true;
}
}
}
[Fact]
public void EncodeAndDecodeEmptyPayloads()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var packets = new Packet[] {};
Parser.EncodePayload(packets, new EncodeAndDecodeEmptyPayloads_EncodeCallback());
}
public class EncodeAndDecodeBinaryContents_EncodeCallback : IEncodeCallback
{
public void Call(object data)
{
Parser.DecodePayload((byte[]) data, new EncodeAndDecodeBinaryContents_DecodeCallback());
}
public class EncodeAndDecodeBinaryContents_DecodeCallback : IDecodePayloadCallback
{
public bool Call(Packet packet, int index, int total)
{
Assert.Equal(Packet.MESSAGE, packet.Type);
var isLast = index + 1 == total;
if (!isLast)
{
Assert.Equal(FirstBuffer(), packet.Data);
}
else
{
Assert.Equal(SecondBuffer(), packet.Data);
}
return true;
}
}
}
[Fact]
public void EncodeAndDecodeBinaryContents()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var firstBuffer = FirstBuffer();
var secondBuffer = SecondBuffer();
var packets = new Packet[]
{new Packet(Packet.MESSAGE, firstBuffer), new Packet(Packet.MESSAGE, secondBuffer)};
Parser.EncodePayload(packets, new EncodeAndDecodeBinaryContents_EncodeCallback());
}
private static byte[] SecondBuffer()
{
var secondBuffer = new byte[4];
for (int i = 0; i < secondBuffer.Length; i++)
{
secondBuffer[i] = (byte) (5 + i);
}
return secondBuffer;
}
private static byte[] FirstBuffer()
{
var firstBuffer = new byte[5];
for (int i = 0; i < firstBuffer.Length; i++)
{
firstBuffer[i] = (byte) i;
}
return firstBuffer;
}
private static byte[] ThirdBuffer()
{
var result = new byte[123];
for (int i = 0; i < result.Length; i++)
{
result[i] = (byte) i;
}
return result;
}
public class EncodeMixedBinaryAndStringContents_EncodeCallback : IEncodeCallback
{
public void Call(object data)
{
Parser.DecodePayload((byte[]) data, new EncodeMixedBinaryAndStringContents_DecodeCallback());
}
public class EncodeMixedBinaryAndStringContents_DecodeCallback : IDecodePayloadCallback
{
public bool Call(Packet packet, int index, int total)
{
if (index == 0)
{
Assert.Equal(Packet.MESSAGE, packet.Type);
Assert.Equal(ThirdBuffer(), packet.Data);
}
else if (index == 1)
{
Assert.Equal(Packet.MESSAGE, packet.Type);
Assert.Equal("hello", packet.Data);
}
else
{
Assert.Equal(Packet.CLOSE, packet.Type);
}
return true;
}
}
}
[Fact]
public void EncodeMixedBinaryAndStringContents()
{
LogManager.SetupLogManager();
var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod());
log.Info("Start");
var packets = new Packet[]
{
new Packet(Packet.MESSAGE, ThirdBuffer()),
new Packet(Packet.MESSAGE, "hello"),
new Packet(Packet.CLOSE),
};
Parser.EncodePayload(packets, new EncodeMixedBinaryAndStringContents_EncodeCallback());
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
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.Tests2.net35")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("EngineIoClientDotNet.Tests2.net35")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[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("ba788bbe-0fe8-4c2f-8a02-457a5e9e2703")]
// 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("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="SuperSocket.ClientEngine" publicKeyToken="ee9af13f57f00acc" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-0.9.0.0" newVersion="0.9.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="more.xunit.runner.visualstudio" version="2.3.1" targetFramework="net35" developmentDependency="true" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net35" />
<package id="SuperSocket.ClientEngine.Core" version="0.9.0" targetFramework="net35" />
<package id="System.Threading.Tasks.Unofficial" version="3.1" targetFramework="net35" />
<package id="WebSocket4Net" version="0.15.1" targetFramework="net35" />
<package id="xunit" version="1.9.2" targetFramework="net35" />
</packages>

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public static class ConnectionConstants
{
public static int PORT = 80;
public static string HOSTNAME = "testme.quobject.com";
public static int SSL_PORT = 443;
public static readonly int TIMEOUT = 300000;
}
}

View File

@@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\EngineIoClientDotNet.net40\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.props" Condition="Exists('..\EngineIoClientDotNet.net40\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.props')" />
<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>{DF3284AF-2FE7-4855-8111-38835A703564}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>EngineIoClientDotNet.Tests.net40</RootNamespace>
<AssemblyName>EngineIoClientDotNet.Tests.net40</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFrameworkProfile />
</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>
<Prefer32Bit>false</Prefer32Bit>
</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>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net40\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SuperSocket.ClientEngine, Version=0.9.0.0, Culture=neutral, PublicKeyToken=ee9af13f57f00acc, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net40\packages\SuperSocket.ClientEngine.Core.0.9.0\lib\net45\SuperSocket.ClientEngine.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="WebSocket4Net, Version=0.15.1.10, Culture=neutral, PublicKeyToken=eb4e154b696bf72a, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net40\packages\WebSocket4Net.0.15.1\lib\net45\WebSocket4Net.dll</HintPath>
</Reference>
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net40\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.assert, Version=2.3.0.3705, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net40\packages\xunit.assert.2.3.0-beta3-build3705\lib\netstandard1.1\xunit.assert.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.core, Version=2.3.0.3705, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net40\packages\xunit.extensibility.core.2.3.0-beta3-build3705\lib\netstandard1.1\xunit.core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.execution.desktop, Version=2.3.0.3705, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net40\packages\xunit.extensibility.execution.2.3.0-beta3-build3705\lib\net452\xunit.execution.desktop.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\EngineIoClientDotNet.Tests.net35\ClientTests\BinaryPollingTest.cs">
<Link>ClientTests\BinaryPollingTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.net35\ClientTests\BinaryWebSocketTest.cs">
<Link>ClientTests\BinaryWebSocketTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.net35\ClientTests\Connection.cs">
<Link>ClientTests\Connection.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.net35\ClientTests\ConnectionTest.cs">
<Link>ClientTests\ConnectionTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.net35\ClientTests\HandshakeDataTests.cs">
<Link>ClientTests\HandshakeDataTests.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.net35\ClientTests\ServerConnectionTest.cs">
<Link>ClientTests\ServerConnectionTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.net35\ClientTests\SocketTest.cs">
<Link>ClientTests\SocketTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.net35\ClientTests\SSLServerConnectionTest.cs">
<Link>ClientTests\SSLServerConnectionTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.net35\ClientTests\TransportTest.cs">
<Link>ClientTests\TransportTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.net35\ClientTests\UsageTest.cs">
<Link>ClientTests\UsageTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.net35\ComponentEmitterTests\EmitterTests.cs">
<Link>ComponentEmitterTests\EmitterTests.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.net35\ModulesTests\ParseQSTests.cs">
<Link>ModulesTests\ParseQSTests.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.net35\ModulesTests\UTF8Tests.cs">
<Link>ModulesTests\UTF8Tests.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.net35\ParserTests\DecodeTests.cs">
<Link>ParserTests\DecodeTests.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.net35\ParserTests\TestsParser.cs">
<Link>ParserTests\TestsParser.cs</Link>
</Compile>
<Compile Include="ClientTests\ConnectionConstants.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EngineIoClientDotNet.net40\EngineIoClientDotNet.net40.csproj">
<Project>{833dbca1-0b01-4477-9937-a8e50e426ee5}</Project>
<Name>EngineIoClientDotNet.net40</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="config.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\EngineIoClientDotNet.net40\packages\xunit.analyzers.0.3.0\analyzers\dotnet\cs\xunit.analyzers.dll" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\EngineIoClientDotNet.net40\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.props')" Text="$([System.String]::Format('$(ErrorText)', '..\EngineIoClientDotNet.net40\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.props'))" />
<Error Condition="!Exists('..\EngineIoClientDotNet.net40\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\EngineIoClientDotNet.net40\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.targets'))" />
</Target>
<Import Project="..\EngineIoClientDotNet.net40\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.targets" Condition="Exists('..\EngineIoClientDotNet.net40\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.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,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
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.Tests.net40")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("EngineIoClientDotNet.Tests.net40")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[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("75432de3-510e-4d31-ba47-b25eaa997026")]
// 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("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="SuperSocket.ClientEngine" publicKeyToken="ee9af13f57f00acc" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-0.9.0.0" newVersion="0.9.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,19 @@
{
"version":"0.9.23",
"server":{
"port":80,
"ssl_port":443,
"hostname":"testme.quobject.com"
},
"win":{
"powershell":"C:/WINDOWS/System32/WindowsPowerShell/v1.0/powershell.exe",
"msbuild": "C:/Windows/Microsoft.NET/Framework/v4.0.30319/msbuild.exe",
// "xunit_path":"C:/ProgramData/chocolatey/bin",
"xunit_path":"C:/Development/quobject.visualstudio.com/EngineIoClientDotNet/Src/EngineIoClientDotNet.net45/packages/xunit.runner.console.2.0.0/tools/",
"nuget":"C:/ProgramData/chocolatey/bin/NuGet.exe"
},
"linux":{
"msbuild":"xbuild",
"xunit_path":"/home/apollo/vendors/xunit"
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
<package id="SuperSocket.ClientEngine.Core" version="0.9.0" targetFramework="net452" />
<package id="WebSocket4Net" version="0.15.1" targetFramework="net452" />
<package id="xunit" version="2.3.0-beta3-build3705" targetFramework="net452" />
<package id="xunit.abstractions" version="2.0.1" targetFramework="net452" />
<package id="xunit.analyzers" version="0.3.0" targetFramework="net452" />
<package id="xunit.assert" version="2.3.0-beta3-build3705" targetFramework="net452" />
<package id="xunit.core" version="2.3.0-beta3-build3705" targetFramework="net452" />
<package id="xunit.extensibility.core" version="2.3.0-beta3-build3705" targetFramework="net452" />
<package id="xunit.extensibility.execution" version="2.3.0-beta3-build3705" targetFramework="net452" />
</packages>

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
{
public static class ConnectionConstants
{
public static int PORT = 80;
public static string HOSTNAME = "testme.quobject.com";
public static int SSL_PORT = 443;
public static readonly int TIMEOUT = 300000;
}
}

View File

@@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\EngineIoClientDotNet.net45\packages\xunit.runner.visualstudio.2.3.0-beta3-build3705\build\net20\xunit.runner.visualstudio.props" Condition="Exists('..\EngineIoClientDotNet.net45\packages\xunit.runner.visualstudio.2.3.0-beta3-build3705\build\net20\xunit.runner.visualstudio.props')" />
<Import Project="..\EngineIoClientDotNet.net45\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.props" Condition="Exists('..\EngineIoClientDotNet.net45\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.props')" />
<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>{BEFF0675-8A73-4012-9651-C253E06E0F87}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>EngineIoClientDotNet.Tests</RootNamespace>
<AssemblyName>EngineIoClientDotNet.Tests.net45</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</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=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net45\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net45\packages\System.Collections.Immutable.1.4.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Numerics" />
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net45\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net45\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.assert, Version=2.3.0.3705, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net45\packages\xunit.assert.2.3.0-beta3-build3705\lib\netstandard1.1\xunit.assert.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.core, Version=2.3.0.3705, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net45\packages\xunit.extensibility.core.2.3.0-beta3-build3705\lib\netstandard1.1\xunit.core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.execution.dotnet, Version=2.3.0.3705, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\EngineIoClientDotNet.net45\packages\xunit.extensibility.execution.2.3.0-beta3-build3705\lib\netstandard1.1\xunit.execution.dotnet.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Folder Include="ThreadTests\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EngineIoClientDotNet.net45\EngineIoClientDotNet.net45.csproj">
<Project>{842d8b13-daf3-4919-80a0-03efa3c17178}</Project>
<Name>EngineIoClientDotNet.net45</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\BinaryPollingTest.cs">
<Link>ClientTests\BinaryPollingTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\BinaryWebSocketTest.cs">
<Link>ClientTests\BinaryWebSocketTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\Connection.cs">
<Link>ClientTests\Connection.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\ConnectionTest.cs">
<Link>ClientTests\ConnectionTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\HandshakeDataTests.cs">
<Link>ClientTests\HandshakeDataTests.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\ServerConnectionTest.cs">
<Link>ClientTests\ServerConnectionTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\SocketTest.cs">
<Link>ClientTests\SocketTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\SSLServerConnectionTest.cs">
<Link>ClientTests\SSLServerConnectionTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\TransportTest.cs">
<Link>ClientTests\TransportTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\UsageTest.cs">
<Link>ClientTests\UsageTest.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ComponentEmitterTests\EmitterTests.cs">
<Link>ComponentEmitterTests\EmitterTests.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ModulesTests\ParseQSTests.cs">
<Link>ModulesTests\ParseQSTests.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ModulesTests\UTF8Tests.cs">
<Link>ModulesTests\UTF8Tests.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ParserTests\DecodeTests.cs">
<Link>ParserTests\DecodeTests.cs</Link>
</Compile>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ParserTests\TestsParser.cs">
<Link>ParserTests\TestsParser.cs</Link>
</Compile>
<Compile Include="ClientTests\ConnectionConstants.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\EngineIoClientDotNet.net45\packages\xunit.analyzers.0.5.0\analyzers\dotnet\cs\xunit.analyzers.dll" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\EngineIoClientDotNet.net45\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.props')" Text="$([System.String]::Format('$(ErrorText)', '..\EngineIoClientDotNet.net45\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.props'))" />
<Error Condition="!Exists('..\EngineIoClientDotNet.net45\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\EngineIoClientDotNet.net45\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.targets'))" />
<Error Condition="!Exists('..\EngineIoClientDotNet.net45\packages\xunit.runner.visualstudio.2.3.0-beta3-build3705\build\net20\xunit.runner.visualstudio.props')" Text="$([System.String]::Format('$(ErrorText)', '..\EngineIoClientDotNet.net45\packages\xunit.runner.visualstudio.2.3.0-beta3-build3705\build\net20\xunit.runner.visualstudio.props'))" />
<Error Condition="!Exists('..\EngineIoClientDotNet.net45\packages\NETStandard.Library.2.0.0-preview2-25401-01\build\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\EngineIoClientDotNet.net45\packages\NETStandard.Library.2.0.0-preview2-25401-01\build\NETStandard.Library.targets'))" />
</Target>
<Import Project="..\EngineIoClientDotNet.net45\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.targets" Condition="Exists('..\EngineIoClientDotNet.net45\packages\xunit.core.2.3.0-beta3-build3705\build\xunit.core.targets')" />
<Import Project="..\EngineIoClientDotNet.net45\packages\NETStandard.Library.2.0.0-preview2-25401-01\build\NETStandard.Library.targets" Condition="Exists('..\EngineIoClientDotNet.net45\packages\NETStandard.Library.2.0.0-preview2-25401-01\build\NETStandard.Library.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,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 © 2015")]
[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.19")]
[assembly: AssemblyFileVersion("0.9.19")]

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="SuperSocket.ClientEngine" publicKeyToken="ee9af13f57f00acc" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-0.9.0.0" newVersion="0.9.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.NETCore.Platforms" version="2.0.0-preview2-25405-01" targetFramework="net45" />
<package id="NETStandard.Library" version="2.0.0-preview2-25401-01" targetFramework="net45" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
<package id="System.Collections" version="4.3.0" targetFramework="net45" />
<package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net45" />
<package id="System.Collections.Immutable" version="1.4.0" targetFramework="net45" />
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net45" />
<package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net45" />
<package id="System.Diagnostics.Tracing" version="4.3.0" targetFramework="net45" />
<package id="System.Globalization" version="4.3.0" targetFramework="net45" />
<package id="System.IO" version="4.3.0" targetFramework="net45" />
<package id="System.IO.Compression" version="4.3.0" targetFramework="net45" />
<package id="System.Linq" version="4.3.0" targetFramework="net45" />
<package id="System.Linq.Expressions" version="4.3.0" targetFramework="net45" />
<package id="System.Net.Http" version="4.3.2" targetFramework="net45" />
<package id="System.Net.Primitives" version="4.3.0" targetFramework="net45" />
<package id="System.ObjectModel" version="4.3.0" targetFramework="net45" />
<package id="System.Reflection" version="4.3.0" targetFramework="net45" />
<package id="System.Reflection.Extensions" version="4.3.0" targetFramework="net45" />
<package id="System.Reflection.Primitives" version="4.3.0" targetFramework="net45" />
<package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net45" />
<package id="System.Runtime" version="4.3.0" targetFramework="net45" />
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net45" />
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net45" />
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net45" />
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net45" />
<package id="System.Text.Encoding" version="4.3.0" targetFramework="net45" />
<package id="System.Text.Encoding.Extensions" version="4.3.0" targetFramework="net45" />
<package id="System.Text.RegularExpressions" version="4.3.0" targetFramework="net45" />
<package id="System.Threading" version="4.3.0" targetFramework="net45" />
<package id="System.Threading.Tasks" version="4.3.0" targetFramework="net45" />
<package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="net45" />
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="net45" />
<package id="xunit" version="2.3.0-beta3-build3705" targetFramework="net45" />
<package id="xunit.abstractions" version="2.0.1" targetFramework="net45" />
<package id="xunit.analyzers" version="0.5.0" targetFramework="net45" />
<package id="xunit.assert" version="2.3.0-beta3-build3705" targetFramework="net45" />
<package id="xunit.core" version="2.3.0-beta3-build3705" targetFramework="net45" />
<package id="xunit.extensibility.core" version="2.3.0-beta3-build3705" targetFramework="net45" />
<package id="xunit.extensibility.execution" version="2.3.0-beta3-build3705" targetFramework="net45" />
<package id="xunit.runner.visualstudio" version="2.3.0-beta3-build3705" targetFramework="net45" developmentDependency="true" />
</packages>

View File

@@ -0,0 +1,43 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\BinaryPollingTest.cs" Link="ClientTests\BinaryPollingTest.cs" />
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\BinaryWebSocketTest.cs" Link="ClientTests\BinaryWebSocketTest.cs" />
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\Connection.cs" Link="ClientTests\Connection.cs" />
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\ConnectionConstants.cs" Link="ClientTests\ConnectionConstants.cs" />
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\ConnectionTest.cs" Link="ClientTests\ConnectionTest.cs" />
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\HandshakeDataTests.cs" Link="ClientTests\HandshakeDataTests.cs" />
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\ServerConnectionTest.cs" Link="ClientTests\ServerConnectionTest.cs" />
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\SocketTest.cs" Link="ClientTests\SocketTest.cs" />
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\SSLServerConnectionTest.cs" Link="ClientTests\SSLServerConnectionTest.cs" />
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\TransportTest.cs" Link="ClientTests\TransportTest.cs" />
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ClientTests\UsageTest.cs" Link="ClientTests\UsageTest.cs" />
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ComponentEmitterTests\EmitterTests.cs" Link="ComponentEmitterTests\EmitterTests.cs" />
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ModulesTests\ParseQSTests.cs" Link="ModulesTests\ParseQSTests.cs" />
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ModulesTests\UTF8Tests.cs" Link="ModulesTests\UTF8Tests.cs" />
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ParserTests\DecodeTests.cs" Link="ParserTests\DecodeTests.cs" />
<Compile Include="..\EngineIoClientDotNet.Tests.mono\ParserTests\TestsParser.cs" Link="ParserTests\TestsParser.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EngineIoClientDotNet.netstandard1.3\EngineIoClientDotNet.netstandard1.3.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="ModulesTests\" />
<Folder Include="ParserTests\" />
<Folder Include="ComponentEmitterTests\" />
<Folder Include="ClientTests\" />
</ItemGroup>
</Project>

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();
}
}
}

Some files were not shown because too many files have changed in this diff Show More