├── grunt
├── .gitignore
├── packages.config
├── .jshintrc
├── config.json
├── package.json
├── tasks
│ ├── install-npm.js
│ ├── nuget.js
│ ├── test-client.js
│ ├── start-server.js
│ ├── build-test.js
│ ├── build-client.js
│ └── createNugetPackage.js
├── templates
│ ├── AssemblyInfo.cs
│ ├── EngineIoClientDotNet.nuspec
│ └── EngineIoClientDotNet - with xamarin.nuspec
└── Gruntfile.js
├── TestServer
├── .gitignore
├── testme.quobject.com.p7b
├── packages.config
├── package.json
├── .jshintrc
├── testme.quobject.com.cert
├── testme.quobject.com.key
└── server.js
├── Src
├── EngineIoClientDotNet
│ ├── Parser
│ │ ├── IEncodeCallback.cs
│ │ ├── IDecodePayloadCallback.cs
│ │ ├── Buffer.cs
│ │ ├── Parser.cs
│ │ ├── ByteBuffer.cs
│ │ └── Packet.cs
│ ├── Modules
│ │ ├── UTF8Exception.cs
│ │ ├── ServerCertificate_netstandard.cs
│ │ ├── ParseQS.cs
│ │ ├── LogManager.cs
│ │ ├── Global.cs
│ │ └── UTF8.cs
│ ├── Client
│ │ ├── EngineIOException.cs
│ │ ├── HandshakeData.cs
│ │ ├── Transport.cs
│ │ └── Transports
│ │ │ ├── WebSocket.cs
│ │ │ ├── Polling.cs
│ │ │ └── PollingXHR.cs
│ ├── EngineIoClientDotNet.csproj
│ ├── Thread
│ │ ├── Heartbeat.cs
│ │ ├── TriggeredLoopTimer.cs
│ │ └── EasyTimer.cs
│ └── ComponentEmitter
│ │ └── Emitter.cs
├── EngineIoClientDotNet.Tests
│ ├── ClientTests
│ │ ├── ConnectionConstants.cs
│ │ ├── HandshakeDataTests.cs
│ │ ├── Connection.cs
│ │ ├── UsageTest.cs
│ │ ├── SocketTest.cs
│ │ ├── BinaryWebSocketTest.cs
│ │ ├── BinaryPollingTest.cs
│ │ ├── TransportTest.cs
│ │ ├── ConnectionTest.cs
│ │ └── SSLServerConnectionTest.cs
│ ├── EngineIoClientDotNet.Tests.csproj
│ ├── ModulesTests
│ │ ├── ParseQSTests.cs
│ │ └── UTF8Tests.cs
│ ├── ParserTests
│ │ └── DecodeTests.cs
│ └── ComponentEmitterTests
│ │ └── EmitterTests.cs
└── EngineIoClientDotNet.sln
├── LICENSE.md
├── README.md
└── .gitignore
/grunt/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | test.xml
--------------------------------------------------------------------------------
/TestServer/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | test.xml
3 | *.pem
4 |
--------------------------------------------------------------------------------
/TestServer/testme.quobject.com.p7b:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Quobject/EngineIoClientDotNet/HEAD/TestServer/testme.quobject.com.p7b
--------------------------------------------------------------------------------
/grunt/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/TestServer/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet/Parser/IEncodeCallback.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Quobject.EngineIoClientDotNet.Parser
3 | {
4 | public interface IEncodeCallback
5 | {
6 | void Call(object data);
7 | }
8 |
9 | }
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet/Parser/IDecodePayloadCallback.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Quobject.EngineIoClientDotNet.Parser
3 | {
4 |
5 | public interface IDecodePayloadCallback
6 | {
7 | bool Call(Packet packet, int index, int total);
8 | }
9 | }
--------------------------------------------------------------------------------
/TestServer/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "engine.io-client.java-test",
3 | "version": "0.0.0",
4 | "private": true,
5 | "dependencies": {
6 | "engine.io": "^1.8.4",
7 | "express": "^4.15.3",
8 | "strip-json-comments": "^2.0.1"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet/Modules/UTF8Exception.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Quobject.EngineIoClientDotNet.Modules
4 | {
5 | public class UTF8Exception : Exception
6 | {
7 | public UTF8Exception(string message) : base(message)
8 | {}
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/grunt/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "devel": true,
4 | "indent": 2,
5 | "maxerr": 50,
6 | "newcap": true,
7 | "nomen": true,
8 | "plusplus": false,
9 | "regexp": true,
10 | "white": false,
11 | "curly": true,
12 | "eqnull": true,
13 | "eqeqeq": true,
14 | "undef": true
15 |
16 | }
--------------------------------------------------------------------------------
/TestServer/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "devel": true,
4 | "indent": 2,
5 | "maxerr": 50,
6 | "newcap": true,
7 | "nomen": true,
8 | "plusplus": false,
9 | "regexp": true,
10 | "white": false,
11 | "curly": true,
12 | "eqnull": true,
13 | "eqeqeq": true,
14 | "undef": true
15 |
16 | }
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet.Tests/ClientTests/ConnectionConstants.cs:
--------------------------------------------------------------------------------
1 | namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
2 | {
3 | public static class ConnectionConstants
4 | {
5 | public static int PORT = 80;
6 | public static string HOSTNAME = "localhost";
7 | public static int SSL_PORT = 443;
8 | public static readonly int TIMEOUT = 300000;
9 | }
10 | }
--------------------------------------------------------------------------------
/grunt/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0.2",
3 | "server": {
4 | "port": 80,
5 | "ssl_port": 443,
6 | "hostname": "testme.quobject.com"
7 | },
8 | "win": {
9 | "powershell": "C:/WINDOWS/System32/WindowsPowerShell/v1.0/powershell.exe",
10 | "msbuild": "C:/Windows/Microsoft.NET/Framework/v4.0.30319/msbuild.exe",
11 | "nuget": "C:/ProgramData/chocolatey/bin/nuget.exe"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet/Modules/ServerCertificate_netstandard.cs:
--------------------------------------------------------------------------------
1 | namespace Quobject.EngineIoClientDotNet.Modules
2 | {
3 | public class ServerCertificate
4 | {
5 | public static bool Ignore { get; set; }
6 |
7 | static ServerCertificate()
8 | {
9 | Ignore = false;
10 | }
11 |
12 | public static void IgnoreServerCertificateValidation()
13 | {
14 | Ignore = true;
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet/Client/EngineIOException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Quobject.EngineIoClientDotNet.Client
4 | {
5 | public class EngineIOException : Exception
6 | {
7 | public string Transport;
8 | public object code;
9 |
10 | public EngineIOException(string message)
11 | : base(message)
12 | {
13 | }
14 |
15 |
16 | public EngineIOException(Exception cause)
17 | : base("", cause)
18 | {
19 | }
20 |
21 | public EngineIOException(string message, Exception cause)
22 | : base(message, cause)
23 | {
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/grunt/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "EngineIoClientDotNet",
3 | "version": "0.1.0",
4 | "author": "Matthias Ludwig",
5 | "description": "Engine.IO Client Library for .Net",
6 | "repository": {
7 | "type": "git",
8 | "url": ""
9 | },
10 | "readme": "This is the Engine.IO Client Library for C#, which is ported from the [JavaScript client](https://github.com/LearnBoost/engine.io-client).",
11 | "devDependencies": {
12 | "grunt": "^1.0.1",
13 | "grunt-shell": "^2.1.0",
14 | "grunt-contrib-jshint": "^1.1.0"
15 | },
16 | "dependencies": {
17 | "string": "^3.3.3",
18 | "string-formatter": "^0.2.5",
19 | "grunt-contrib-clean": "^0.6.0",
20 | "grunt-contrib-copy": "^1.0.0",
21 | "rimraf": "^2.6.1",
22 | "strip-json-comments": "^2.0.1"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet.Tests/EngineIoClientDotNet.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.0
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 | all
14 | runtime; build; native; contentfiles; analyzers; buildtransitive
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet.Tests/ClientTests/HandshakeDataTests.cs:
--------------------------------------------------------------------------------
1 | using Quobject.EngineIoClientDotNet.Client;
2 | using Xunit;
3 |
4 | namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
5 | {
6 | public class HandshakeDataTests
7 | {
8 | [Fact]
9 | public void Test()
10 | {
11 | var json = @"{
12 | sid: 'nne323',
13 | upgrades: ['u1','u2'],
14 | pingInterval: 12,
15 | pingTimeout: 23
16 | }";
17 |
18 | var handshakeData = new HandshakeData(json);
19 | Assert.Equal("u1", handshakeData.Upgrades[0]);
20 | Assert.Equal("u2", handshakeData.Upgrades[1]);
21 |
22 | Assert.Equal(12, handshakeData.PingInterval);
23 | Assert.Equal(23, handshakeData.PingTimeout);
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet/Client/HandshakeData.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json.Linq;
2 | using System.Collections.Immutable;
3 |
4 |
5 | namespace Quobject.EngineIoClientDotNet.Client
6 | {
7 | public class HandshakeData
8 | {
9 | public string Sid;
10 | public ImmutableList Upgrades = ImmutableList.Empty;
11 | public long PingInterval;
12 | public long PingTimeout;
13 |
14 | public HandshakeData(string data)
15 | : this(JObject.Parse(data))
16 | {
17 | }
18 |
19 | public HandshakeData(JObject data)
20 | {
21 | var upgrades = data.GetValue("upgrades");
22 |
23 | foreach (var e in upgrades)
24 | {
25 | Upgrades = Upgrades.Add(e.ToString());
26 | }
27 |
28 | Sid = data.GetValue("sid").Value();
29 | PingInterval = data.GetValue("pingInterval").Value();
30 | PingTimeout = data.GetValue("pingTimeout").Value();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet/Parser/Buffer.cs:
--------------------------------------------------------------------------------
1 | namespace Quobject.EngineIoClientDotNet.Parser
2 | {
3 | internal class Buffer
4 | {
5 |
6 | private Buffer()
7 | {
8 | }
9 |
10 | public static byte[] Concat(byte[][] list)
11 | {
12 | int length = 0;
13 | foreach (var buf in list)
14 | {
15 | length += buf.Length;
16 | }
17 |
18 | return Concat(list, length);
19 | }
20 |
21 | public static byte[] Concat(byte[][] list, int length)
22 | {
23 | if (list.Length == 0)
24 | {
25 | return new byte[0];
26 | }
27 | if (list.Length == 1)
28 | {
29 | return list[0];
30 | }
31 |
32 | ByteBuffer buffer = ByteBuffer.Allocate(length);
33 | foreach (var buf in list)
34 | {
35 | buffer.Put(buf);
36 | }
37 |
38 | return buffer.Array();
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/grunt/tasks/install-npm.js:
--------------------------------------------------------------------------------
1 | module.exports = function (grunt) {
2 |
3 | grunt.registerTask('installNpm',
4 | 'install node modules', function () {
5 | var
6 | string = require('string-formatter'),
7 | server_path2 = grunt.config('server_path'),
8 | os = grunt.config('os'),
9 | config = grunt.config('config'),
10 | win_pwd_command = string.format('{0} pwd', config.win.powershell);
11 |
12 | grunt.log.writeln('server_path = "%s"', server_path2);
13 | grunt.log.writeln('win_pwd_command = "%s"', win_pwd_command);
14 |
15 | if (os === 'win') {
16 | grunt.config('shell.exec.options.execOptions.cwd', '<%= server_path %>');
17 |
18 | grunt.config('shell.exec.command', [win_pwd_command,
19 | 'npm install'].join('&&'));
20 | grunt.task.run('shell');
21 |
22 | } else {
23 |
24 | grunt.config('shell.exec.options.execOptions.cwd', '<%= server_path %>');
25 | grunt.config('shell.exec.command', ['pwd', 'npm install'].join('&&'));
26 | grunt.task.run('shell');
27 | }
28 |
29 | });
30 | };
31 |
32 |
33 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Quobject
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/TestServer/testme.quobject.com.cert:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDDzCCAfegAwIBAgIJANW6WUwZpQs+MA0GCSqGSIb3DQEBBQUAMB4xHDAaBgNV
3 | BAMME3Rlc3RtZS5xdW9iamVjdC5jb20wHhcNMTQwODI2MTkwMDQzWhcNMjQwODIz
4 | MTkwMDQzWjAeMRwwGgYDVQQDDBN0ZXN0bWUucXVvYmplY3QuY29tMIIBIjANBgkq
5 | hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtJCU+74bnPPYg0SPBCws1WYdT7+lXDaf
6 | IZdCLXU3RT/hAszD/Hi8oCijD1BvfjRcPr9XAqKBWMeLTorV8YL/I5g+5Nzmcaep
7 | LjnmQV3YDR+ioBfx+PRwF8gx/ZGdmK/hcoFq27xbF6cLI4mbvddlwUdKEGgZ+g/a
8 | B+CzFF9xCKoll6zqnnHS+DImGNbH4+ex33vQj4yoQrRT5E85s7/nSwvbDve+AlJ3
9 | ChJVod4kepwixhV90ENP0u65lpgi7ipIDCNxtf/7ZazsSj33eSKioz3xy2mFX7WO
10 | Fqtg1f3h/njH4uI6RkPUbuFyj3IOqv6OQwbl7NXbzuPfkmGC7QBGqwIDAQABo1Aw
11 | TjAdBgNVHQ4EFgQUE28o7tGA1Aw53KhiC0PyTDlA29EwHwYDVR0jBBgwFoAUE28o
12 | 7tGA1Aw53KhiC0PyTDlA29EwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC
13 | AQEAqbOxXwelUcV9psZl8fr+FIbkl5/mLqZV1RdrHCkUD2OwGH5M8AlCqj42hmxi
14 | n6KIgE45MOo9UYHWNQ1Aem3ziEGPRDVZpsoNW1GfG6XnAH5r1DK34Td7lU1JebNN
15 | hxqV3AfVfeqrW1ZOmqEFJ95VwCoN1RPPh3MgFI1zjOjEJyk0pPxFNFRtpIHfLgve
16 | TFe88aVMAbDLVzGyDkkS2DxNvyZ5153W3JRh2u8PqhLSzCIGF+IcCOrwZya+VC63
17 | wWg8AckPXIGmhU/6P4zdQ/WCZ/tqErFYls49zwp6xAfvvfdTbqYCSNyOqsTKbYyP
18 | qAd5L9YKITYYa8IupRyIJGbXnw==
19 | -----END CERTIFICATE-----
20 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet.Tests/ClientTests/Connection.cs:
--------------------------------------------------------------------------------
1 | using Quobject.EngineIoClientDotNet.Client;
2 | using Quobject.EngineIoClientDotNet.Modules;
3 |
4 | namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
5 | {
6 | public class Connection
7 | {
8 | static Connection()
9 | {
10 | LogManager.SetupLogManager();
11 | }
12 |
13 | protected static Socket.Options CreateOptions()
14 | {
15 | var options = new Socket.Options
16 | {
17 | Port = ConnectionConstants.PORT,
18 | Hostname = ConnectionConstants.HOSTNAME
19 | };
20 | //log.Info("Please add to your hosts file: 127.0.0.1 " + options.Hostname);
21 |
22 | return options;
23 | }
24 |
25 | protected static Socket.Options CreateOptionsSecure()
26 | {
27 | var options = new Socket.Options
28 | {
29 | Port = ConnectionConstants.SSL_PORT,
30 | Hostname = ConnectionConstants.HOSTNAME,
31 | //log.Info("Please add to your hosts file: 127.0.0.1 " + options.Hostname);
32 | Secure = true,
33 | IgnoreServerCertificateValidation = true
34 | };
35 | return options;
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/grunt/tasks/nuget.js:
--------------------------------------------------------------------------------
1 | module.exports = function (grunt) {
2 |
3 | grunt.registerTask('nuget',
4 | 'get nuget assemblies', function () {
5 | var
6 | //fs = require('fs'),
7 | //S = require('string'),
8 | string = require('string-formatter'),
9 | os = grunt.config('os'),
10 | config = grunt.config('config'),
11 | //configuration = grunt.config('msbuild_configuration'),
12 | nuget_builds = grunt.config('nuget_builds'),
13 | nuget_path = os === 'win' ?
14 | config.win.nuget : config.linux.nuget,
15 | format_str = os === 'win' ?
16 | '{0} restore "{1}"' :
17 | 'mono --runtime=v4.0.30319 {0} restore {1}',
18 | tasks = [],
19 | i;
20 |
21 | function restorePackagesWithTitle(title) {
22 | var
23 | sln = string.format('{0}/../../Src/{1}/{2}.sln',__dirname, title,title),
24 | restore = string.format(format_str, nuget_path, sln);
25 |
26 | tasks.push(restore);
27 | }
28 |
29 | if (os === 'win') {
30 | for (i = 0; i < nuget_builds.length; i++) {
31 | restorePackagesWithTitle(nuget_builds[i].Name);
32 | }
33 | }
34 |
35 | grunt.log.writeln('tasks = %s', JSON.stringify(tasks));
36 | grunt.config('shell.exec.command', tasks.join('&&'));
37 | grunt.task.run('shell');
38 | });
39 | };
40 |
41 |
--------------------------------------------------------------------------------
/grunt/tasks/test-client.js:
--------------------------------------------------------------------------------
1 | module.exports = function (grunt) {
2 |
3 | grunt.registerTask('testClient',
4 | 'test cs', function () {
5 | var
6 | string = require('string-formatter'),
7 | os = grunt.config('os'),
8 | config = grunt.config('config'),
9 | tasks = [],
10 | configuration = grunt.config('msbuild_configuration'),
11 | test_format_str = os === 'win' ?
12 | '{0}/xunit.console.exe {1} -nunit test.xml -parallel none' :
13 | 'mono {0}/xunit.console.clr4.exe {1}',
14 |
15 | xunit_path = os === 'win' ?
16 | config.win.xunit_path : config.linux.xunit_path;
17 |
18 | function addTestDllWithTitle(title) {
19 | var
20 | dir_path = string.format('{0}/../../Src/{1}/', __dirname, title),
21 | test_dll = string.format('{0}bin/{1}/{2}.dll', dir_path, configuration, title);
22 |
23 | tasks.push( string.format(test_format_str,xunit_path, test_dll) );
24 | }
25 |
26 | if (os === 'win') {
27 | addTestDllWithTitle('EngineIoClientDotNet.Tests.net45');
28 | } else {
29 | addTestDllWithTitle('EngineIoClientDotNet.Tests.mono');
30 | }
31 |
32 | grunt.log.writeln('tasks = %s', JSON.stringify(tasks));
33 | grunt.config('shell.exec.command', tasks.join('&&'));
34 | grunt.task.run('shell');
35 |
36 | });
37 | };
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet/EngineIoClientDotNet.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | true
6 | 0.0.6
7 | EngineIoClientDotNet.Standard
8 |
9 | Joe Wen
10 | false
11 |
12 | https://github.com/joewen/EngineIoClientDotNet
13 | Engine.IO Client Library for .NET Standard
14 | LICENSE.md
15 |
16 | https://github.com/joewen/EngineIoClientDotNet
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | True
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet.Tests/ClientTests/UsageTest.cs:
--------------------------------------------------------------------------------
1 | using Quobject.EngineIoClientDotNet.Client;
2 | using System;
3 | using Xunit;
4 |
5 | namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
6 | {
7 | public class UsageTest : Connection
8 | {
9 | [Fact]
10 | public void Usage1()
11 | {
12 | var options = CreateOptions();
13 | var socket = new Socket(options);
14 |
15 | //You can use `Socket` to connect:
16 | //var socket = new Socket("ws://localhost");
17 | socket.On(Socket.EVENT_OPEN, () =>
18 | {
19 | socket.Send("hi");
20 | socket.Close();
21 | });
22 | socket.Open();
23 |
24 | //System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
25 | }
26 |
27 | [Fact]
28 | public void Usage2()
29 | {
30 | var options = CreateOptions();
31 | var socket = new Socket(options);
32 |
33 | //Receiving data
34 | //var socket = new Socket("ws://localhost:3000");
35 | socket.On(Socket.EVENT_OPEN, () =>
36 | {
37 | socket.On(Socket.EVENT_MESSAGE, (data) => Console.WriteLine((string)data));
38 | });
39 | socket.Open();
40 |
41 | System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
42 | socket.Close();
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/grunt/tasks/start-server.js:
--------------------------------------------------------------------------------
1 | module.exports = function (grunt) {
2 |
3 | grunt.registerTask('startServer',
4 | 'install node modules', function () {
5 | var
6 | server_path = grunt.config('server_path'),
7 | os = grunt.config('os'),
8 | string = require('string-formatter'),
9 | config = grunt.config('config'),
10 | tasks = [],
11 | start,
12 | pwd;
13 |
14 | grunt.log.writeln('server_path = "%s"', server_path);
15 |
16 | if (os === 'win') {
17 |
18 | start = '{0} start-process ' +
19 | '-NoNewWindow ' +
20 | //'-WindowStyle Normal ' + //-WindowStyle (Hidden | Normal) | -NoNewWindow
21 | '-FilePath node ' +
22 | '-ArgumentList \' server.js \' ';
23 | start = string.format(start, config.win.powershell);
24 | pwd = string.format('{0} pwd',config.win.powershell);
25 |
26 | tasks.push(pwd);
27 | tasks.push(start);
28 |
29 | grunt.log.writeln('tasks = %s', JSON.stringify(tasks));
30 | grunt.config('shell.exec.options.execOptions.cwd', '<%= server_path %>');
31 | grunt.config('shell.exec.command', tasks.join('&&'));
32 | grunt.task.run('shell');
33 |
34 | } else {
35 |
36 | grunt.config('shell.exec.options.execOptions.cwd', '<%= server_path %>');
37 | grunt.config('shell.exec.command', ['pwd', 'node server.js'].join('&&'));
38 | grunt.task.run('shell');
39 | }
40 |
41 | });
42 | };
43 |
44 |
45 |
--------------------------------------------------------------------------------
/grunt/templates/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("EngineIoClientDotNet")]
8 | [assembly: AssemblyDescription("Engine.IO Client Library for .Net")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("Quobject Software")]
11 | [assembly: AssemblyProduct("EngineIoClientDotNet")]
12 | [assembly: AssemblyCopyright("Copyright © 2017")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("a95e75cd-35e6-4e88-9e22-631e3fd01546")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("@VERSION@")]
35 | [assembly: AssemblyFileVersion("@VERSION@")]
36 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet/Parser/Parser.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Quobject.EngineIoClientDotNet.Parser
3 | {
4 | ///
5 | /// This is the JavaScript parser for the engine.io protocol encoding,
6 | /// shared by both engine.io-client and engine.io.
7 | /// https://github.com/Automattic/engine.io-parser
8 | ///
9 | public class Parser
10 | {
11 |
12 | public static readonly int Protocol = 3;
13 |
14 |
15 | private Parser()
16 | {
17 | }
18 |
19 | public static void EncodePacket(Packet packet, IEncodeCallback callback)
20 | {
21 | packet.Encode(callback);
22 | }
23 |
24 | public static Packet DecodePacket(string data, bool utf8decode = false)
25 | {
26 | return Packet.DecodePacket(data, utf8decode);
27 | }
28 |
29 | public static Packet DecodePacket(byte[] data)
30 | {
31 | return Packet.DecodePacket(data);
32 | }
33 |
34 | public static void EncodePayload(Packet[] packets, IEncodeCallback callback)
35 | {
36 | Packet.EncodePayload(packets, callback);
37 | }
38 |
39 |
40 | public static void DecodePayload(string data, IDecodePayloadCallback callback)
41 | {
42 | Packet.DecodePayload(data, callback);
43 | }
44 |
45 | public static void DecodePayload(byte[] data, IDecodePayloadCallback callback)
46 | {
47 | Packet.DecodePayload(data, callback);
48 | }
49 |
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # EngineIoClientDotNet
2 |
3 | Engine.IO Client Library for .Net
4 |
5 | Fork from [https://github.com/joewen/EngineIoClientDotNet](https://github.com/joewen/EngineIoClientDotNet).
6 |
7 | This is the Engine.IO Client Library for C#, which is ported from the [JavaScript client](https://github.com/Automattic/engine.io-client).
8 |
9 |
10 | ##### Installation
11 | Nuget install:
12 | ```
13 | Install-Package EngineIoClientDotNet.Standard
14 | ```
15 |
16 | * NuGet Package: [](https://www.nuget.org/packages/EngineIoClientDotNet.Standard/)
17 |
18 |
19 | ##### Usage
20 | EngineIoClientDotNet has a similar api to those of the [JavaScript client](https://github.com/Automattic/engine.io-client).
21 |
22 | You can use `Socket` to connect:
23 |
24 | ```cs
25 | var socket = new Socket("ws://localhost");
26 | socket.On(Socket.EVENT_OPEN, () =>
27 | {
28 | socket.Send("hi", () =>
29 | {
30 | socket.Close();
31 | });
32 | });
33 | socket.Open();
34 | ```
35 |
36 | Receiving data
37 | ```cs
38 | var socket = new Socket("ws://localhost");
39 | socket.On(Socket.EVENT_OPEN, () =>
40 | {
41 | socket.On(Socket.EVENT_MESSAGE, (data) =>
42 | {
43 | Console.WriteLine((string)data);
44 | });
45 | });
46 | socket.Open();
47 | ```
48 |
49 | #### Features
50 | This library supports all of the features the JS client does, including events, options and upgrading transport.
51 |
52 | #### Framework Versions
53 | .Net Standard 2.0
54 |
55 | ## License
56 |
57 | [MIT](http://opensource.org/licenses/MIT)
58 |
59 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet/Thread/Heartbeat.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Threading;
4 |
5 | namespace Quobject.EngineIoClientDotNet.Thread
6 | {
7 | public class Heartbeat
8 | {
9 | private volatile bool gotHeartbeat = false;
10 | private BackgroundWorker heartBeatTimer;
11 | private CancellationTokenSource ts;
12 |
13 | private Heartbeat()
14 | {
15 | ts = new CancellationTokenSource();
16 | }
17 |
18 | public static Heartbeat Start(Action onTimeout, int timeout)
19 | {
20 | Heartbeat heartbeat = new Heartbeat();
21 | heartbeat.Run(onTimeout, timeout);
22 | return heartbeat;
23 | }
24 |
25 | public void OnHeartbeat()
26 | {
27 | gotHeartbeat = true;
28 | }
29 |
30 | private void Run(Action onTimeout, int timeout)
31 | {
32 | heartBeatTimer = new BackgroundWorker();
33 |
34 | heartBeatTimer.DoWork += (s, e) =>
35 | {
36 | while (!ts.IsCancellationRequested)
37 | {
38 | System.Threading.Thread.Sleep(timeout);
39 | if (!gotHeartbeat && !ts.IsCancellationRequested)
40 | {
41 | onTimeout();
42 | break;
43 | }
44 | }
45 | };
46 |
47 | heartBeatTimer.RunWorkerAsync();
48 | }
49 |
50 | public void Stop()
51 | {
52 | ts.Cancel();
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29519.87
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EngineIoClientDotNet", "EngineIoClientDotNet\EngineIoClientDotNet.csproj", "{2596BA35-6391-4955-9439-AAB7D0FE668A}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EngineIoClientDotNet.Tests", "EngineIoClientDotNet.Tests\EngineIoClientDotNet.Tests.csproj", "{05954C40-D0B5-4557-ADFD-02A091064F44}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {2596BA35-6391-4955-9439-AAB7D0FE668A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {2596BA35-6391-4955-9439-AAB7D0FE668A}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {2596BA35-6391-4955-9439-AAB7D0FE668A}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {2596BA35-6391-4955-9439-AAB7D0FE668A}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {05954C40-D0B5-4557-ADFD-02A091064F44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {05954C40-D0B5-4557-ADFD-02A091064F44}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {05954C40-D0B5-4557-ADFD-02A091064F44}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {05954C40-D0B5-4557-ADFD-02A091064F44}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {ABCEAB3D-05C7-4ACC-99B3-64BCECF1C2EE}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/TestServer/testme.quobject.com.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpAIBAAKCAQEAtJCU+74bnPPYg0SPBCws1WYdT7+lXDafIZdCLXU3RT/hAszD
3 | /Hi8oCijD1BvfjRcPr9XAqKBWMeLTorV8YL/I5g+5NzmcaepLjnmQV3YDR+ioBfx
4 | +PRwF8gx/ZGdmK/hcoFq27xbF6cLI4mbvddlwUdKEGgZ+g/aB+CzFF9xCKoll6zq
5 | nnHS+DImGNbH4+ex33vQj4yoQrRT5E85s7/nSwvbDve+AlJ3ChJVod4kepwixhV9
6 | 0ENP0u65lpgi7ipIDCNxtf/7ZazsSj33eSKioz3xy2mFX7WOFqtg1f3h/njH4uI6
7 | RkPUbuFyj3IOqv6OQwbl7NXbzuPfkmGC7QBGqwIDAQABAoIBAQCy2/0YGUqVAF7a
8 | ONFKGtAWWt5yHq6YV2ruBT0CdnfXWt1yvo7sylReeaJ8CvtGEmvFpBd2fq6N2Ku/
9 | k3s1jsNY6Ph0D/UdZC0Lo0LYQTNAXLPkzZNdPhTDGgWa3eE0XBSALn5BR6UcGtXH
10 | 0Am71V/wQsO02MnSkF0zLHt3lMsM/oPoJx8S6Tw+PpxGOhwQipdLMjKH49vyy5IM
11 | pS5OiGuAjmIq7bB0QPbgeZkQgSVgvZ+XP4OLuRt7I6GwMnChrVucybYWuetTSoUI
12 | uyRmOtlwUFBVJdSwEY5RfdF71kOH9DPpuTY6M4UJGdprEM1N1dX0WF2y/5D+ExeA
13 | rb06SXrxAoGBANfSja+YFn5+M8N/favt2/nGP6ePQJutjeiz0PgYOpe/85MrqNK/
14 | 5rlU89QNDm616xEJnsPO/J/ZFDf+2rhuTfNCeNtzA/10j07xhHYN62Us9S5bsaXC
15 | JSMgdLcAnbUAXRJVrxPoUYgIoJIR65IG9UAHshoAysGPfBKQqR4hWKsHAoGBANYt
16 | wMnPA2sZH651pIe9lMETHeY5AIx7QGEDtu12raTgHaQanJFTXz5oXsEkJYUJKVvK
17 | XS2I74ZbIjvruASj2Tf7/L21xxo2JmxJCXVMlgyrVRKBIb9d0Ea7tUqLsIukYV3X
18 | iXrSabVtLLJA/SCtZME0tHrc/4RJwLIG0XVltMo9AoGARrQl0qbCh8IUdzFnHFIa
19 | RKOb6urVQasD2H5AMWbOmzQ5ObeN4S0ZCxI3pvp4BfD3B2fdaUyAGmXlZ8rIIK+S
20 | PeVC7rGpVvk+kaAxwvMgcM7fq8ZCVolZ3T4evm0nPUrXMtB7QMxVGXmqEPBp+jbp
21 | VYav5DDqO6sj/HkDzmkiQTUCgYEAxXMUonfITPmybWFjNwidlImNLOssCFav+UA1
22 | aiHY34EFkn4+DPPxgFUz1Zb/R/A0Qr0CvbHaL+DgZKFg2lY7MROL41Erpox5S6bh
23 | o1PhmPhyy0Zk2Ekic7Mk5P522aXHZX4I7kQA1BM7+3FSasevdTajlAkdPtXHYdhL
24 | TZFf5HkCgYB4qGARdPa0JJ+YbNilsykkIKs602Faen7qR1uVYFzbM+GUOjMrHkxt
25 | mmLE4+IrkhrWKQTW4vDAlIvTBZYJYeXZtu0IRilKccSExcKDhBmWhIDyFqRoyl3V
26 | OYmrskNT5YtBTEFKerAOKJ5LXxVQQ7k2YDz3uSli3NNsCMpfqo7Lxg==
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet/Thread/TriggeredLoopTimer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Threading;
4 |
5 | namespace Quobject.EngineIoClientDotNet.Thread
6 | {
7 | public class TriggeredLoopTimer
8 | {
9 | private ManualResetEvent trigger;
10 | private CancellationTokenSource ts;
11 |
12 | private TriggeredLoopTimer()
13 | {
14 | trigger = new ManualResetEvent(false);
15 | ts = new CancellationTokenSource();
16 | }
17 |
18 | public static TriggeredLoopTimer Start (Action method, int delayInMilliseconds)
19 | {
20 | TriggeredLoopTimer ping = new TriggeredLoopTimer();
21 | ping.Run (method, delayInMilliseconds);
22 | return ping;
23 | }
24 |
25 |
26 | public void Trigger()
27 | {
28 | trigger.Set();
29 | }
30 |
31 | private void Run (Action method, int delayInMilliseconds)
32 | {
33 | var worker = new BackgroundWorker();
34 |
35 | worker.DoWork += (s, e) =>
36 | {
37 | while (!ts.IsCancellationRequested)
38 | {
39 | System.Threading.Thread.Sleep (delayInMilliseconds);
40 | if (!ts.IsCancellationRequested)
41 | {
42 | method();
43 | trigger.WaitOne();
44 | trigger.Reset();
45 | }
46 | }
47 | };
48 |
49 | worker.RunWorkerAsync();
50 | }
51 |
52 | public void Stop()
53 | {
54 | if (ts != null)
55 | {
56 | ts.Cancel();
57 | trigger.Set();
58 | }
59 | }
60 | }
61 | }
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet.Tests/ModulesTests/ParseQSTests.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Immutable;
2 | using Quobject.EngineIoClientDotNet.Modules;
3 | using System.Collections.Generic;
4 | using Xunit;
5 |
6 |
7 | namespace Quobject.EngineIoClientDotNet_Tests.ModulesTests
8 | {
9 | public class ParseQsTests
10 | {
11 | //should parse a querystring and return an object
12 | [Fact]
13 | public void Decode()
14 | {
15 | // Single assignment
16 | var queryObj = ParseQS.Decode("foo=bar");
17 | Assert.Equal("bar", queryObj["foo"]);
18 |
19 | // Multiple assignments
20 | queryObj = ParseQS.Decode("france=grenoble&germany=mannheim");
21 | Assert.Equal("grenoble", queryObj["france"]);
22 | Assert.Equal("mannheim", queryObj["germany"]);
23 |
24 | // Assignments containing non-alphanumeric characters
25 | queryObj = ParseQS.Decode("india=new%20delhi");
26 | Assert.Equal("new delhi", queryObj["india"]);
27 | }
28 |
29 | //should construct a query string from an object'
30 | [Fact]
31 | public void Encode()
32 | {
33 |
34 | Dictionary obj;
35 |
36 | obj = new Dictionary {{"a", "b"}};
37 | var imObj = ImmutableDictionary.Create().AddRange(obj);
38 | Assert.Equal("a=b", ParseQS.Encode(imObj));
39 |
40 | obj = new Dictionary {{"a", "b"}, {"c", "d"}};
41 | imObj = ImmutableDictionary.Create().AddRange(obj);
42 | Assert.Equal("a=b&c=d", ParseQS.Encode(imObj));
43 |
44 | obj = new Dictionary {{"a", "b"}, {"c", "tobi rocks"}};
45 | imObj = ImmutableDictionary.Create().AddRange(obj);
46 | Assert.Equal("a=b&c=tobi%20rocks", ParseQS.Encode(imObj));
47 |
48 | }
49 |
50 |
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/grunt/templates/EngineIoClientDotNet.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | EngineIoClientDotNet
5 | @VERSION@-beta1
6 | EngineIoClientDotNet
7 | Matthias Ludwig
8 | http://opensource.org/licenses/MIT
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | https://github.com/Quobject/EngineIoClientDotNet/
35 | This is the Engine.IO Client Library for C#.
36 | This library supports all of the features the JS client does, including events, options and upgrading transport. EngineIoClientDotNet has a similar api to those of the JavaScript client.
37 | engine.io.client
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet/Thread/EasyTimer.cs:
--------------------------------------------------------------------------------
1 |
2 | using System.ComponentModel;
3 | using System.Diagnostics;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Quobject.EngineIoClientDotNet.Modules;
7 | using System;
8 |
9 |
10 |
11 | namespace Quobject.EngineIoClientDotNet.Thread
12 | {
13 | public class EasyTimer
14 | {
15 |
16 |
17 | private CancellationTokenSource ts;
18 |
19 |
20 | public EasyTimer(CancellationTokenSource ts)
21 | {
22 | this.ts = ts;
23 | }
24 |
25 | public static EasyTimer SetTimeout(Action method, int delayInMilliseconds)
26 | {
27 | var ts = new CancellationTokenSource();
28 | var ct = ts.Token;
29 |
30 |
31 | var worker = new BackgroundWorker();
32 |
33 | worker.DoWork += (s, e) => System.Threading.Thread.Sleep(delayInMilliseconds);
34 |
35 | worker.RunWorkerCompleted += (s, e) =>
36 | {
37 | if (!ts.IsCancellationRequested)
38 | {
39 | Task.Factory.StartNew(method, ct, TaskCreationOptions.None, TaskScheduler.Default);
40 | }
41 | };
42 |
43 | worker.RunWorkerAsync();
44 |
45 |
46 |
47 | // Returns a stop handle which can be used for stopping
48 | // the timer, if required
49 | return new EasyTimer(ts);
50 | }
51 |
52 | public void Stop()
53 | {
54 | var log = LogManager.GetLogger(Global.CallerName());
55 | log.Info("EasyTimer stop");
56 | if (ts != null)
57 | {
58 | ts.Cancel();
59 | }
60 | }
61 |
62 | public static void TaskRun(Action action)
63 | {
64 | var t = new Task(action);
65 | t.RunSynchronously();
66 | if (t.IsFaulted)
67 | {
68 | if (t.Exception != null)
69 | {
70 | throw t.Exception;
71 | }
72 | throw new Exception();
73 | }
74 | //Task.Run(action).Wait();
75 | }
76 |
77 | public static Task TaskRunNoWait(Action action)
78 | {
79 | var t = new Task(action);
80 | t.Start();
81 | return t;
82 | }
83 |
84 | }
85 |
86 |
87 | }
88 |
89 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet.Tests/ClientTests/SocketTest.cs:
--------------------------------------------------------------------------------
1 | using Quobject.EngineIoClientDotNet.Client;
2 | using System.Collections.Immutable;
3 | using System.Threading.Tasks;
4 | using Xunit;
5 |
6 | namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
7 | {
8 | public class SocketTest : Connection
9 | {
10 | private Socket socket;
11 | public string Message;
12 |
13 | [Fact]
14 | public void FilterUpgrades()
15 | {
16 | var options = CreateOptions();
17 | options.Transports = ImmutableList.Empty.Add("polling");
18 |
19 | socket = new Socket(options);
20 |
21 | var immutablelist = socket.FilterUpgrades(ImmutableList.Empty.Add("polling").Add("websocket"));
22 |
23 | Assert.Equal("polling", immutablelist[0]);
24 | Assert.Equal(1, immutablelist.Count);
25 | }
26 |
27 | [Fact]
28 | public async Task SocketClosing()
29 | {
30 | var closed = false;
31 | var error = false;
32 |
33 | var options = CreateOptions();
34 |
35 | socket = new Socket("ws://0.0.0.0:8080", options);
36 | socket.On(Socket.EVENT_OPEN, () =>
37 | {
38 | //socket.Send("test send");
39 | });
40 | socket.On(Socket.EVENT_CLOSE, () =>
41 | {
42 | //log.Info("EVENT_CLOSE = ");
43 | closed = true;
44 | });
45 |
46 | socket.Once(Socket.EVENT_ERROR, () =>
47 | {
48 | //log.Info("EVENT_ERROR = ");
49 | error = true;
50 | });
51 |
52 | socket.Open();
53 | //System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
54 | await Task.Delay(1000);
55 | Assert.True(closed);
56 | Assert.True(error);
57 | }
58 |
59 | [Fact]
60 | public void SocketOptionCookies()
61 | {
62 | var options = new Socket.Options();
63 | options.Cookies.Add("foo", "bar");
64 | Assert.Equal("foo=bar", options.GetCookiesAsString());
65 | options.Cookies.Add("name2", "value2");
66 | Assert.Equal("foo=bar; name2=value2", options.GetCookiesAsString());
67 | }
68 |
69 | [Fact]
70 | public void DefaultProtocol()
71 | {
72 | var socket = new Socket("testme.quobject.com");
73 | Assert.NotNull(socket);
74 | }
75 | }
76 | }
--------------------------------------------------------------------------------
/grunt/tasks/build-test.js:
--------------------------------------------------------------------------------
1 | module.exports = function (grunt) {
2 |
3 | grunt.registerTask('buildTest',
4 | 'test modules', function () {
5 | var
6 | fs = require('fs'),
7 | S = require('string'),
8 | string = require('string-formatter'),
9 | os = grunt.config('os'),
10 | config = grunt.config('config'),
11 | configuration = grunt.config('msbuild_configuration'),
12 | tasks = [],
13 | clean_format = os === 'win' ? '{0} start-process ' +
14 | '-NoNewWindow ' +
15 | //'-WindowStyle Normal ' + //-WindowStyle (Hidden | Normal) | -NoNewWindow
16 | '-FilePath {1} ' +
17 | '-ArgumentList \' {2} /t:clean /p:Configuration={3} \' ' :
18 | '{0} {1} /t:clean /p:Configuration={2}',
19 | build_format = os === 'win' ? '{0} start-process ' +
20 | '-NoNewWindow ' +
21 | //'-WindowStyle Normal ' + //-WindowStyle (Hidden | Normal) | -NoNewWindow
22 | '-FilePath {1} ' +
23 | '-ArgumentList \' {2} /p:Configuration={3} \' ' :
24 | '{0} {1} /p:Configuration={2}';
25 |
26 | function addBuildWithTitle(title) {
27 | var
28 | dir_path = string.format('{0}/../../Src/{1}/', __dirname,title),
29 | csproj = string.format('{0}{1}.csproj', dir_path, title),
30 | clean = os === 'win' ? string.format(clean_format, config.win.powershell, config.win.msbuild, csproj, configuration ):
31 | string.format(clean_format, config.linux.msbuild, csproj, configuration),
32 | build = os === 'win' ? string.format(build_format, config.win.powershell, config.win.msbuild, csproj, configuration ):
33 | string.format(build_format, config.linux.msbuild, csproj, configuration),
34 | template_file_content = fs.readFileSync('./templates/AssemblyInfo.cs');
35 |
36 | template_file_content = S(template_file_content).replaceAll('@VERSION@', config.version).s;
37 | //grunt.log.writeln('template_file_content = "%s"', template_file_content);
38 | fs.writeFileSync(string.format('{0}Properties/AssemblyInfo.cs', dir_path), template_file_content);
39 |
40 | tasks.push(clean);
41 | tasks.push(build);
42 | }
43 |
44 | if (os === 'win') {
45 | addBuildWithTitle('EngineIoClientDotNet.Tests.net45');
46 | } else {
47 | addBuildWithTitle('EngineIoClientDotNet.Tests.mono');
48 | }
49 |
50 | grunt.log.writeln('tasks = %s', JSON.stringify(tasks));
51 | grunt.config('shell.exec.command', tasks.join('&&'));
52 | grunt.task.run('shell');
53 | });
54 | };
55 |
56 |
57 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet.Tests/ParserTests/DecodeTests.cs:
--------------------------------------------------------------------------------
1 | using Quobject.EngineIoClientDotNet.Modules;
2 | using Quobject.EngineIoClientDotNet.Parser;
3 | using Xunit;
4 |
5 | namespace Quobject.EngineIoClientDotNet_Tests.ParserTests
6 | {
7 | public class DecodeTests
8 | {
9 | private const string PARSER_ERROR = "parser error";
10 |
11 | [Fact]
12 | public void DecodeBadFormat()
13 | {
14 | LogManager.SetupLogManager();
15 | var log = LogManager.GetLogger("DecodeTests DecodeBadFormat");
16 |
17 |
18 | Packet p = Parser.DecodePacket(":::");
19 | Assert.Equal(Packet.ERROR, p.Type);
20 | Assert.Equal(PARSER_ERROR, p.Data);
21 | }
22 |
23 | [Fact]
24 | public void DecodeInexistingTypes()
25 | {
26 |
27 | Packet p = Parser.DecodePacket("94103");
28 | Assert.Equal(Packet.ERROR, p.Type);
29 | Assert.Equal(PARSER_ERROR, p.Data);
30 | }
31 |
32 | [Fact]
33 | public void DecodeInvalidUTF8()
34 | {
35 |
36 | Packet p = Parser.DecodePacket("4\uffff", true);
37 | Assert.Equal(Packet.ERROR, p.Type);
38 | Assert.Equal(PARSER_ERROR, p.Data);
39 | }
40 |
41 |
42 | public class DecodePayloadBadFormat_DecodeCallback : IDecodePayloadCallback
43 | {
44 |
45 | public bool Call(Packet packet, int index, int total)
46 | {
47 | var isLast = index + 1 == total;
48 | Assert.True(isLast);
49 | Assert.Equal(Packet.ERROR, packet.Type);
50 | Assert.Equal(PARSER_ERROR, packet.Data);
51 | return true;
52 | }
53 | }
54 |
55 | [Fact]
56 | public void EncodeAndDecodeEmptyPayloads()
57 | {
58 |
59 | Packet.DecodePayload("1!", new DecodePayloadBadFormat_DecodeCallback());
60 | Packet.DecodePayload("", new DecodePayloadBadFormat_DecodeCallback());
61 | Packet.DecodePayload("))", new DecodePayloadBadFormat_DecodeCallback());
62 | }
63 |
64 | [Fact]
65 | public void DecodePayloadBadPacketFormat()
66 | {
67 |
68 | Packet.DecodePayload("3:99", new DecodePayloadBadFormat_DecodeCallback());
69 | Packet.DecodePayload("1:aa", new DecodePayloadBadFormat_DecodeCallback());
70 | Packet.DecodePayload("1:a2:b", new DecodePayloadBadFormat_DecodeCallback());
71 | }
72 |
73 | [Fact]
74 | public void DecodePayloadInvalidUTF8()
75 | {
76 | Packet.DecodePayload("2:4\uffff", new DecodePayloadBadFormat_DecodeCallback());
77 | }
78 |
79 |
80 |
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet/Modules/ParseQS.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Immutable;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Quobject.EngineIoClientDotNet.Modules
7 | {
8 | ///
9 | /// Provides methods for parsing a query string into an object, and vice versa.
10 | /// Ported from the JavaScript module.
11 | /// https://www.npmjs.org/package/parseqs
12 | ///
13 | public class ParseQS
14 | {
15 | ///
16 | /// Compiles a querystring
17 | /// Returns string representation of the object
18 | ///
19 | ///
20 | ///
21 | public static string Encode(ImmutableDictionary obj)
22 | {
23 | var sb = new StringBuilder();
24 | foreach (var key in obj.Keys.OrderBy(x=>x))
25 | {
26 | if (sb.Length > 0)
27 | {
28 | sb.Append("&");
29 | }
30 | sb.Append(Global.EncodeURIComponent(key));
31 | sb.Append("=");
32 | sb.Append(Global.EncodeURIComponent(obj[key]));
33 | }
34 | return sb.ToString();
35 | }
36 |
37 | ///
38 | /// Compiles a querystring
39 | /// Returns string representation of the object
40 | ///
41 | ///
42 | ///
43 | internal static string Encode(System.Collections.Generic.Dictionary obj)
44 | {
45 | var sb = new StringBuilder();
46 | foreach (var key in obj.Keys)
47 | {
48 | if (sb.Length > 0)
49 | {
50 | sb.Append("&");
51 | }
52 | sb.Append(Global.EncodeURIComponent(key));
53 | sb.Append("=");
54 | sb.Append(Global.EncodeURIComponent(obj[key]));
55 | }
56 | return sb.ToString();
57 | }
58 |
59 | ///
60 | /// Parses a simple querystring into an object
61 | ///
62 | ///
63 | ///
64 | public static Dictionary Decode(string qs)
65 | {
66 | var qry = new Dictionary();
67 | var pairs = qs.Split('&');
68 | for (int i = 0; i < pairs.Length; i++)
69 | {
70 | var pair = pairs[i].Split('=');
71 |
72 | qry.Add(Global.DecodeURIComponent(pair[0]), Global.DecodeURIComponent(pair[1]));
73 | }
74 | return qry;
75 | }
76 |
77 |
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/grunt/Gruntfile.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = function (grunt) {
3 | var
4 | node_os = require('os'),
5 | fs = require('fs'),
6 | strip_json = require('strip-json-comments'),
7 | config = JSON.parse(strip_json(String(fs.readFileSync('./config.json')))),
8 | util = require('util'),
9 | os = node_os.platform() === 'win32' ? 'win' : 'linux',
10 | nuget_builds = [
11 | { "Name": "EngineIoClientDotNet.net35", "NuGetDir": "net35", "SourceDir": "net35", copyOnly: true },
12 | { "Name": "EngineIoClientDotNet.net40", "NuGetDir": "net40", "SourceDir": "net40", copyOnly: true },
13 | { "Name": "EngineIoClientDotNet.net45", "NuGetDir": "net45", "SourceDir": "net45", copyOnly: true },
14 | { "Name": "EngineIoClientDotNet.netstandard1.3", "NuGetDir": "netstandard1.3", "SourceDir": "netstandard1.3", copyOnly: true },
15 | ];
16 |
17 | grunt.log.writeln(util.inspect(config));
18 | grunt.log.writeln( 'os = "%s"', os );
19 |
20 | grunt.loadTasks('./tasks');
21 |
22 | grunt.initConfig({
23 | os: os,
24 | config: config,
25 | //msbuild_configuration: 'Debug',
26 | msbuild_configuration: 'Release',
27 | nuget_builds: nuget_builds,
28 | release_path: './../Releases/<%= config.version %>/',
29 | working_path: './../Working/',
30 | server_path: '../TestServer/',
31 | shell: {
32 | exec: {
33 | options: {
34 | stdout: true,
35 | stderr: true
36 | }
37 | }
38 | },
39 | jshint: {
40 | options: {
41 | jshintrc: true,
42 | },
43 | target: [
44 | 'Gruntfile.js',
45 | '<%= server_path %>server.js',
46 | 'tasks/**/*.js'
47 | ]
48 | },
49 | clean: {
50 | release: ['<%= release_path %>/*'],
51 | working: ['<%= working_path %>/*'],
52 | options: { force: true }
53 | },
54 | copy: {
55 | release: {
56 | files: [
57 | {
58 | expand: true,
59 | cwd: './../EngineIoClientDotNet/bin/Release',
60 | src: '*',
61 | dest: '<%= release_path %>/net45'
62 | }
63 | ]
64 | },
65 | release_mono: {
66 | files: [
67 | {
68 | expand: true,
69 | cwd: './../EngineIoClientDotNet_Mono/bin/Release',
70 | src: '*',
71 | dest: '<%= release_path %>/mono'
72 | }
73 | ]
74 | },
75 | }
76 | });
77 |
78 | grunt.loadNpmTasks('grunt-contrib-copy');
79 | grunt.loadNpmTasks('grunt-contrib-clean');
80 | grunt.loadNpmTasks('grunt-shell');
81 | grunt.loadNpmTasks('grunt-contrib-jshint');
82 | grunt.registerTask('default', ['jshint', 'installNpm', 'nuget', 'buildClient', 'buildTest', 'startServer', 'testClient']);
83 | grunt.registerTask('test', ['jshint', 'buildClient', 'buildTest', 'testClient']);
84 | grunt.registerTask('makeNuget', ['jshint','clean:working','createNugetPackage']);
85 | };
86 |
--------------------------------------------------------------------------------
/grunt/templates/EngineIoClientDotNet - with xamarin.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | EngineIoClientDotNet
5 | @VERSION@
6 | EngineIoClientDotNet
7 | Matthias Ludwig
8 | http://opensource.org/licenses/MIT
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | https://github.com/Quobject/EngineIoClientDotNet/
52 | This is the Engine.IO Client Library for C#.
53 | This library supports all of the features the JS client does, including events, options and upgrading transport. EngineIoClientDotNet has a similar api to those of the JavaScript client.
54 | engine.io.client
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/grunt/tasks/build-client.js:
--------------------------------------------------------------------------------
1 | module.exports = function (grunt) {
2 |
3 | grunt.registerTask('buildClient',
4 | 'build cs modules', function () {
5 | var
6 | fs = require('fs'),
7 | S = require('string'),
8 | string = require('string-formatter'),
9 | os = grunt.config('os'),
10 | config = grunt.config('config'),
11 | configuration = grunt.config('msbuild_configuration'),
12 | output_path_base = 'bin\\'+ configuration +'\\',
13 | nuget_builds = grunt.config('nuget_builds'),
14 | tasks = [],
15 | clean_format = os === 'win' ? '{0} start-process ' +
16 | '-NoNewWindow ' +
17 | //'-WindowStyle Normal ' + //-WindowStyle (Hidden | Normal) | -NoNewWindow
18 | '-FilePath {1} ' +
19 | '-ArgumentList \' {2} /t:clean;Rebuild /p:Configuration={3} /p:OutputPath={4} \' ' :
20 | '{0} {1} /t:Rebuild /p:Configuration={2} ',
21 | //build_format = os === 'win' ? '{0} start-process ' +
22 | // '-NoNewWindow ' +
23 | // //'-WindowStyle Normal ' + //-WindowStyle (Hidden | Normal) | -NoNewWindow
24 | // '-FilePath {1} ' +
25 | // '-ArgumentList \' {2} /p:Configuration={3} \' ' :
26 | // '{0} {1} /p:Configuration={2}',
27 | i;
28 |
29 | function addBuildWithTitle(title, dir, copyOnly) {
30 | var
31 | dir_path = string.format('{0}/../../Src/{1}/', __dirname, title),
32 | csproj = string.format('{0}{1}.csproj', dir_path, title),
33 | output_path = output_path_base + dir +'\\',
34 | clean = os === 'win' ? string.format(clean_format, config.win.powershell, config.win.msbuild, csproj, configuration, output_path) :
35 | string.format(clean_format, config.linux.msbuild, csproj, configuration),
36 | //build = os === 'win' ? string.format(build_format, config.win.powershell, config.win.msbuild, csproj, configuration ):
37 | // string.format(build_format, config.linux.msbuild, csproj, configuration),
38 | template_file_content = fs.readFileSync('./templates/AssemblyInfo.cs');
39 |
40 | //template_file_content = S(template_file_content).replaceAll('@TITLE@', title).s;
41 | template_file_content = S(template_file_content).replaceAll('@VERSION@', config.version).s;
42 | //grunt.log.writeln('template_file_content = "%s"', template_file_content);
43 | fs.writeFileSync(string.format('{0}Properties/AssemblyInfo.cs', dir_path), template_file_content);
44 | if (!copyOnly) {
45 | tasks.push(clean);
46 | }
47 | }
48 |
49 | for (i = 0; i < nuget_builds.length; i++) {
50 | if (nuget_builds[i].Name !== 'EngineIoClientDotNet.netstandard1.3') {
51 | addBuildWithTitle(nuget_builds[i].Name, nuget_builds[i].NuGetDir, nuget_builds[i].copyOnly);
52 | }
53 | }
54 |
55 | grunt.log.writeln('tasks = %s', JSON.stringify(tasks));
56 | grunt.config('shell.exec.command', tasks.join('&&'));
57 | grunt.task.run('shell');
58 |
59 | if (configuration === 'Release') {
60 | //grunt.task.run('clean:release');
61 | if (os === 'win') {
62 | grunt.task.run('copy:release');
63 | } else {
64 | grunt.task.run('copy:release_mono');
65 | }
66 | }
67 | });
68 | };
69 |
70 |
71 |
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet/Modules/LogManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 | using System.Reflection;
5 | using System.Text;
6 |
7 | namespace Quobject.EngineIoClientDotNet.Modules
8 | {
9 | public class LogManager
10 | {
11 | private const string LogFilePath = "XunitTrace.log";
12 |
13 | private static readonly LogManager EmptyLogger = new LogManager(null);
14 |
15 | private static StreamWriter writer;
16 |
17 | private readonly string type;
18 |
19 | #region Statics
20 |
21 | public static void SetupLogManager()
22 | {}
23 |
24 | public static LogManager GetLogger(string type)
25 | {
26 | return new LogManager(type);
27 | }
28 |
29 | public static LogManager GetLogger(Type type)
30 | {
31 | return GetLogger(type.ToString());
32 | }
33 |
34 | public static LogManager GetLogger(MethodBase methodBase)
35 | {
36 | #if DEBUG
37 | string declaringType = methodBase.DeclaringType != null
38 | ? methodBase.DeclaringType.ToString()
39 | : string.Empty;
40 | string fullType = string.Format("{0}#{1}", declaringType, methodBase.Name);
41 | return GetLogger(fullType);
42 | #else
43 | return EmptyLogger;
44 | #endif
45 | }
46 |
47 | #endregion
48 |
49 | public LogManager(string type)
50 | {
51 | this.type = type;
52 | }
53 |
54 | public static bool Enabled { get; set; }
55 |
56 | private static StreamWriter Writer
57 | {
58 | get
59 | {
60 | if (writer == null)
61 | {
62 | FileStream fs = new FileStream(
63 | LogFilePath, FileMode.Append, FileAccess.Write, FileShare.Read);
64 | writer = new StreamWriter(fs, Encoding.UTF8)
65 | {
66 | AutoFlush = true
67 | };
68 | }
69 |
70 | return writer;
71 | }
72 | }
73 |
74 | [Conditional("DEBUG")]
75 | public void Info(string msg)
76 | {
77 | if (!Enabled)
78 | {
79 | return;
80 | }
81 |
82 | Writer.WriteLine(
83 | "{0:yyyy-MM-dd HH:mm:ss fff} [] {1} {2}",
84 | DateTime.Now,
85 | this.type,
86 | Global.StripInvalidUnicodeCharacters(msg));
87 | }
88 |
89 | [Conditional("DEBUG")]
90 | public void Error(string p, Exception exception)
91 | {
92 | this.Info($"ERROR {p} {exception.Message} {exception.StackTrace}");
93 | if (exception.InnerException != null)
94 | {
95 | this.Info($"ERROR exception.InnerException {p} {exception.InnerException.Message} {exception.InnerException.StackTrace}");
96 | }
97 | }
98 |
99 |
100 | [Conditional("DEBUG")]
101 | internal void Error(Exception e)
102 | {
103 | this.Error("", e);
104 | }
105 | }
106 | }
--------------------------------------------------------------------------------
/TestServer/server.js:
--------------------------------------------------------------------------------
1 | var
2 | ssl = true,
3 | express = require('express'),
4 | fs = require('fs'),
5 | strip_json = require('strip-json-comments'),
6 | config = JSON.parse(strip_json(String(fs.readFileSync('./../grunt/config.json')))),
7 | util = require('util'),
8 | app = express(),
9 | fs = require('fs'),
10 | options = {
11 | key: fs.readFileSync(__dirname + '/testme.quobject.com.key'),
12 | cert: fs.readFileSync(__dirname + '/testme.quobject.com.cert'),
13 | requestCert: true
14 | },
15 | server,
16 | https,
17 | http,
18 | primus_server,
19 | ssl_server ;
20 |
21 |
22 | console.log("https port = " + config.server.ssl_port);
23 | https = require('https').createServer(options, app);
24 | ssl_server = require('engine.io').attach(https, {'pingInterval': 500});
25 | https.listen(config.server.ssl_port, function(d) {
26 | console.log('Engine.IO server listening on port', config.server.ssl_port);
27 | });
28 |
29 | console.log("http port = " + config.server.port);
30 | http = require('http').createServer(app);
31 | server = require('engine.io').attach(http, { 'pingInterval': 500 });
32 | primus_server = require('engine.io').attach(http, { 'pingInterval': 500, 'path' : '/primus/engine.io' });
33 | http.listen( config.server.port, function() {
34 | console.log('Engine.IO server listening on port', config.server.port);
35 | });
36 |
37 |
38 | primus_server.on('connection', function (socket) {
39 | console.log('primus_server connection');
40 | socket.send('hi');
41 | });
42 |
43 |
44 | http.on('request', function(request, response) {
45 | //console.log('request ' +util.inspect( request.headers));
46 |
47 | });
48 |
49 |
50 |
51 |
52 | server.on('connection', function(socket){
53 | socket.send('hi');
54 |
55 |
56 |
57 |
58 | // Bounce any received messages back
59 | socket.on('message', function (data) {
60 |
61 | console.log('got message1 data = "' + data + '"');
62 | console.log('got message data stringify = "' + JSON.stringify(data) + '"');
63 | var result = new Int8Array(data);
64 | console.log('got message data Int8Array = "' + JSON.stringify(result) + '"\n\n');
65 |
66 | if (data === 'give binary') {
67 | var abv = new Int8Array(5);
68 | for (var i = 0; i < 5; i++) {
69 | abv[i] = i;
70 | }
71 | socket.send(abv);
72 | return;
73 | }
74 |
75 | if (data === 'cookie') {
76 | console.log('cookie ' + util.inspect(socket.request.headers));
77 | if (socket.request.headers !== undefined) {
78 | if (socket.request.headers.cookie === "foo=bar") {
79 | socket.send('got cookie');
80 | return;
81 | }
82 | }
83 | socket.send('no cookie');
84 | return;
85 | }
86 |
87 |
88 | socket.send(data);
89 |
90 | });
91 |
92 | });
93 |
94 |
95 |
96 |
97 | ssl_server.on('connection', function(socket){
98 | socket.send('hi');
99 |
100 | // Bounce any received messages back
101 | socket.on('message', function (data) {
102 | if (data === 'give binary') {
103 | var abv = new Int8Array(5);
104 | for (var i = 0; i < 5; i++) {
105 | abv[i] = i;
106 | }
107 | socket.send(abv);
108 | return;
109 | }
110 | console.log('got message data = "' + data + '"');
111 | console.log('got message data stringify = "' + JSON.stringify(data) + '"');
112 | var result = new Int8Array(data);
113 | console.log('got message data Int8Array = "' + JSON.stringify(result) + '"\n\n');
114 |
115 | socket.send(data);
116 |
117 | });
118 | });
--------------------------------------------------------------------------------
/grunt/tasks/createNugetPackage.js:
--------------------------------------------------------------------------------
1 | module.exports = function (grunt) {
2 |
3 | grunt.registerTask('createNugetPackage',
4 | 'create package ', function () {
5 | var
6 | fs = require('fs'),
7 | S = require('string'),
8 | string = require('string-formatter'),
9 | os = grunt.config('os'),
10 | config = grunt.config('config'),
11 | working_path = grunt.config('working_path'),
12 | package_path = working_path + '/NuGet/',
13 | package_lib_path = working_path + '/NuGet/lib/',
14 | //configuration = grunt.config('msbuild_configuration'),
15 | configuration = grunt.config('msbuild_configuration'),
16 | output_path_base = 'bin\\' + configuration + '\\',
17 | nuget_builds = grunt.config('nuget_builds'),
18 | nuget_path = os === 'win' ?
19 | config.win.nuget : config.linux.nuget,
20 | dst_path,
21 | template_file_content,
22 | i,
23 | tasks = [];
24 |
25 | //function createPackageWithTitle(title) {
26 | // var
27 | // dir_path = string.format('{0}/../../{1}/', __dirname, title),
28 | // csproj = string.format('{0}{1}.csproj', dir_path, title),
29 | // pack = string.format('{0} pack {1}', nuget_path, csproj);
30 |
31 | // tasks.push(pack);
32 | //}
33 |
34 | if (os !== 'win') {
35 | return;
36 | }
37 | if (configuration !== 'Release') {
38 | grunt.log.writeln('wrong configuration = ' + configuration);
39 | return;
40 | }
41 |
42 | //createPackageWithTitle('EngineIoClientDotNet');
43 |
44 |
45 | if (! fs.existsSync(working_path)) {
46 | fs.mkdirSync(working_path);
47 | fs.mkdirSync(package_path);
48 | fs.mkdirSync(package_lib_path);
49 | }
50 | if (!fs.existsSync(package_path)) {
51 | fs.mkdirSync(package_path);
52 | fs.mkdirSync(package_lib_path);
53 | }
54 | if (!fs.existsSync(package_lib_path)) {
55 | fs.mkdirSync(package_lib_path);
56 | }
57 |
58 | for (i = 0; i < nuget_builds.length; i++) {
59 | dst_path = package_lib_path + nuget_builds[i].NuGetDir + '/';
60 | //files = fs.readdirSync(dst_path);
61 | grunt.log.writeln(string.format('dst_path={0}', dst_path));
62 | fs.mkdirSync(dst_path);
63 | }
64 |
65 |
66 | template_file_content = fs.readFileSync('./templates/EngineIoClientDotNet.nuspec');
67 | template_file_content = S(template_file_content).replaceAll('@VERSION@', config.version).s;
68 | fs.writeFileSync(string.format('{0}EngineIoClientDotNet.nuspec', package_path), template_file_content);
69 |
70 |
71 |
72 | function addBuildWithTitle(title, destsubdir, srcsubdir) {
73 | var src_path = string.format('{0}/../../Src/{1}/{2}{3}/', __dirname, title, output_path_base, srcsubdir);
74 | var dst_path = package_lib_path + destsubdir + '/';
75 | var filename = 'EngineIoClientDotNet.dll';
76 | var src_file = string.format('{0}{1}', src_path, filename);
77 | var dst_file = string.format('{0}EngineIoClientDotNet.dll', dst_path);
78 |
79 | grunt.log.writeln(string.format('src_file={0} dst_file={1}', src_file, dst_file));
80 | fs.writeFileSync(dst_file, fs.readFileSync(src_file));
81 |
82 | //src_file = src_path + string.format('{0}.xml', title);
83 | //dst_file = string.format('{0}EngineIoClientDotNet.xml', dst_path);
84 | //grunt.log.writeln(string.format('src_file={0} dst_file={1}', src_file, dst_file));
85 | //fs.writeFileSync(dst_file, fs.readFileSync(src_file));
86 | }
87 |
88 | for (i = 0; i < nuget_builds.length; i++) {
89 | addBuildWithTitle(nuget_builds[i].Name, nuget_builds[i].NuGetDir, nuget_builds[i].SourceDir);
90 | }
91 | tasks.push('C:/WINDOWS/System32/WindowsPowerShell/v1.0/powershell.exe pwd');
92 | tasks.push(string.format('{0} pack EngineIoClientDotNet.nuspec', config.win.nuget));
93 | grunt.log.writeln('tasks = %s', JSON.stringify(tasks));
94 | grunt.config('shell.exec.options.execOptions.cwd', package_path);
95 | grunt.config('shell.exec.command', tasks.join('&&'));
96 | grunt.task.run('shell');
97 | });
98 | };
--------------------------------------------------------------------------------
/Src/EngineIoClientDotNet.Tests/ClientTests/BinaryWebSocketTest.cs:
--------------------------------------------------------------------------------
1 | using Quobject.EngineIoClientDotNet.Client;
2 | using System.Collections.Concurrent;
3 | using System.Threading;
4 | using Xunit;
5 |
6 | namespace Quobject.EngineIoClientDotNet_Tests.ClientTests
7 | {
8 | public class BinaryWebSocketTest : Connection
9 | {
10 | private ManualResetEvent _manualResetEvent = null;
11 |
12 | [Fact]
13 | public void ReceiveBinaryData()
14 | {
15 | _manualResetEvent = new ManualResetEvent(false);
16 |
17 | var events = new ConcurrentQueue