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

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

BIN
Libraries/Raspberry.IO.dll Normal file

Binary file not shown.

153
Libraries/Raspberry.IO.xml Normal file
View File

@@ -0,0 +1,153 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Raspberry.IO</name>
</assembly>
<members>
<member name="T:Raspberry.IO.AnalogValue">
<summary>
Represents an analog value.
</summary>
</member>
<member name="M:Raspberry.IO.AnalogValue.#ctor(System.Decimal,System.Decimal)">
<summary>
Initializes a new instance of the <see cref="T:Raspberry.IO.AnalogValue"/> class.
</summary>
<param name="range">The total range (ie. maximum value).</param>
<param name="value">The value.</param>
</member>
<member name="P:Raspberry.IO.AnalogValue.Value">
<summary>
Gets or sets the discrete value.
</summary>
<value>
The discrete value.
</value>
</member>
<member name="P:Raspberry.IO.AnalogValue.Range">
<summary>
Gets or sets the total range.
</summary>
<value>
The total range, ie. the maximum value.
</value>
</member>
<member name="P:Raspberry.IO.AnalogValue.Relative">
<summary>
Gets the relative value.
</summary>
<value>
The relative value.
</value>
</member>
<member name="T:Raspberry.IO.BinaryPinExtensionMethods">
<summary>
Provides extension methods for binary pins.
</summary>
</member>
<member name="M:Raspberry.IO.BinaryPinExtensionMethods.Time(Raspberry.IO.IInputBinaryPin,System.Boolean,System.TimeSpan,System.TimeSpan)">
<summary>
Waits for a pin to reach the specified state, then measures the time it remains in this state.
</summary>
<param name="pin">The measure pin.</param>
<param name="waitForUp">if set to <c>true</c>, wait for the pin to be up.</param>
<param name="phase1Timeout">The first phase timeout.</param>
<param name="phase2Timeout">The second phase timeout.</param>
<returns>
The time the pin remains up, in milliseconds.
</returns>
</member>
<member name="T:Raspberry.IO.ByteExtensionMethods">
<summary>
Provides extension methods for byte and byte arrays.
</summary>
</member>
<member name="M:Raspberry.IO.ByteExtensionMethods.ToBitString(System.Collections.Generic.IEnumerable{System.Byte})">
<summary>
Converts a byte array/enumerable to a bit string.
</summary>
<param name="bytes">bytes to be converted.</param>
<returns>A bit string</returns>
</member>
<member name="T:Raspberry.IO.IInputAnalogPin">
<summary>
Provides an interface for input, analog pin.
</summary>
</member>
<member name="M:Raspberry.IO.IInputAnalogPin.Read">
<summary>
Reads the value of the pin.
</summary>
<returns>The value.</returns>
</member>
<member name="T:Raspberry.IO.IInputBinaryPin">
<summary>
Provides an interface for input, binary pins.
</summary>
</member>
<member name="M:Raspberry.IO.IInputBinaryPin.Read">
<summary>
Reads the state of the pin.
</summary>
<returns><c>true</c> if the pin is in high state; otherwise, <c>false</c>.</returns>
</member>
<member name="M:Raspberry.IO.IInputBinaryPin.Wait(System.Boolean,System.TimeSpan)">
<summary>
Waits for the specified pin to be in the specified state.
</summary>
<param name="waitForUp">if set to <c>true</c> waits for the pin to be up. Default value is <c>true</c>.</param>
<param name="timeout">The timeout. Default value is <see cref="F:System.TimeSpan.Zero"/>.</param>
<remarks>If <c>timeout</c> is set to <see cref="F:System.TimeSpan.Zero"/>, a default timeout is used instead.</remarks>
</member>
<member name="T:Raspberry.IO.IInputOutputBinaryPin">
<summary>
Provides an interface for bidirectional binary pins.
</summary>
</member>
<member name="T:Raspberry.IO.IOutputBinaryPin">
<summary>
Provides an interface for output, binary pins.
</summary>
</member>
<member name="M:Raspberry.IO.IOutputBinaryPin.Write(System.Boolean)">
<summary>
Writes the value of the pin.
</summary>
<param name="state">if set to <c>true</c>, pin is set to high state.</param>
</member>
<member name="M:Raspberry.IO.IInputOutputBinaryPin.AsInput">
<summary>
Prepares the pin to act as an input.
</summary>
</member>
<member name="M:Raspberry.IO.IInputOutputBinaryPin.AsOutput">
<summary>
Prepares the pin to act as an output.
</summary>
</member>
<member name="T:Raspberry.IO.IOutputAnalogPin">
<summary>
Provides an interface for output, analog pin.
</summary>
</member>
<member name="M:Raspberry.IO.IOutputAnalogPin.Write(Raspberry.IO.AnalogValue)">
<summary>
Writes the specified value to the pin.
</summary>
<param name="value">The value.</param>
</member>
<member name="T:Raspberry.IO.StringExtensionMethods">
<summary>
Provides extension methods for strings.
</summary>
</member>
<member name="M:Raspberry.IO.StringExtensionMethods.BitStringToArray(System.String,System.Boolean)">
<summary>
Converts a bit string in MSBF order (most significant bit first) to a byte array.
</summary>
<param name="bitString">A bit string (e.g. "00101111").</param>
<param name="prefixWithZero">If <c>true</c> the bit string will be prefixed with '0' if it is not divisible by 8.</param>
<returns>An array starting with the most significant byte.</returns>
</member>
</members>
</doc>

BIN
Libraries/Raspberry.System.dll Executable file

Binary file not shown.

344
Libraries/Raspberry.System.xml Executable file
View File

@@ -0,0 +1,344 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Raspberry.System</name>
</assembly>
<members>
<member name="T:Raspberry.Board">
<summary>
Represents the Raspberry Pi mainboard.
</summary>
<remarks>Version and revisions are based on <see cref="!:http://raspberryalphaomega.org.uk/2013/02/06/automatic-raspberry-pi-board-revision-detection-model-a-b1-and-b2/"/>.</remarks>
</member>
<member name="P:Raspberry.Board.Current">
<summary>
Gets the current mainboard configuration.
</summary>
</member>
<member name="P:Raspberry.Board.IsRaspberryPi">
<summary>
Gets a value indicating whether this instance is a Raspberry Pi.
</summary>
<value>
<c>true</c> if this instance is a Raspberry Pi; otherwise, <c>false</c>.
</value>
</member>
<member name="P:Raspberry.Board.ProcessorName">
<summary>
Gets the processor name.
</summary>
<value>
The name of the processor.
</value>
</member>
<member name="P:Raspberry.Board.Processor">
<summary>
Gets the processor.
</summary>
<value>
The processor.
</value>
</member>
<member name="P:Raspberry.Board.Firmware">
<summary>
Gets the board firmware version.
</summary>
</member>
<member name="P:Raspberry.Board.SerialNumber">
<summary>
Gets the serial number.
</summary>
</member>
<member name="P:Raspberry.Board.IsOverclocked">
<summary>
Gets a value indicating whether Raspberry Pi board is overclocked.
</summary>
<value>
<c>true</c> if Raspberry Pi is overclocked; otherwise, <c>false</c>.
</value>
</member>
<member name="P:Raspberry.Board.Model">
<summary>
Gets the model.
</summary>
<value>
The model.
</value>
</member>
<member name="P:Raspberry.Board.ConnectorPinout">
<summary>
Gets the connector revision.
</summary>
<value>
The connector revision.
</value>
<remarks>See <see cref="!:http://raspi.tv/2014/rpi-gpio-quick-reference-updated-for-raspberry-pi-b"/> for more information.</remarks>
</member>
<member name="T:Raspberry.ConnectorPinout">
<summary>
The Raspberry Pi connector pinout revision.
</summary>
</member>
<member name="F:Raspberry.ConnectorPinout.Unknown">
<summary>
Connector pinout is unknown.
</summary>
</member>
<member name="F:Raspberry.ConnectorPinout.Rev1">
<summary>
The first revision, as of Model B rev1.
</summary>
</member>
<member name="F:Raspberry.ConnectorPinout.Rev2">
<summary>
The second revision, as of Model B rev2.
</summary>
</member>
<member name="F:Raspberry.ConnectorPinout.Plus">
<summary>
The third revision, as of Model B+.
</summary>
</member>
<member name="T:Raspberry.Model">
<summary>
The Rasperry Pi model.
</summary>
</member>
<member name="F:Raspberry.Model.Unknown">
<summary>
Unknown model.
</summary>
</member>
<member name="F:Raspberry.Model.A">
<summary>
Model A.
</summary>
</member>
<member name="F:Raspberry.Model.APlus">
<summary>
Model A+.
</summary>
</member>
<member name="F:Raspberry.Model.BRev1">
<summary>
Model B rev1.
</summary>
</member>
<member name="F:Raspberry.Model.BRev2">
<summary>
Model B rev2.
</summary>
</member>
<member name="F:Raspberry.Model.BPlus">
<summary>
Model B+.
</summary>
</member>
<member name="F:Raspberry.Model.ComputeModule">
<summary>
Compute module.
</summary>
</member>
<member name="F:Raspberry.Model.B2">
<summary>
Pi 2 Model B.
</summary>
</member>
<member name="F:Raspberry.Model.Zero">
<summary>
Pi Zero.
</summary>
</member>
<member name="F:Raspberry.Model.B3">
<summary>
Pi 3 Model B.
</summary>
</member>
<member name="F:Raspberry.Model.Pi4">
<summary>
Pi 4
</summary>
</member>
<member name="T:Raspberry.ModelExtensionMethods">
<summary>
Provides extension methods for <see cref="T:Raspberry.Model"/>.
</summary>
</member>
<member name="M:Raspberry.ModelExtensionMethods.GetDisplayName(Raspberry.Model)">
<summary>
Gets the model display name.
</summary>
<param name="model">The model.</param>
<returns>The display name, if known; otherwise, <c>null</c>.</returns>
</member>
<member name="T:Raspberry.Processor">
<summary>
The Raspberry Pi processor.
</summary>
</member>
<member name="F:Raspberry.Processor.Unknown">
<summary>
Processor is unknown.
</summary>
</member>
<member name="F:Raspberry.Processor.Bcm2708">
<summary>
Processor is a BCM2708.
</summary>
</member>
<member name="F:Raspberry.Processor.Bcm2709">
<summary>
Processor is a BCM2709.
</summary>
</member>
<member name="F:Raspberry.Processor.Bcm2711">
<summary>
Processor is BCM2711
</summary>
</member>
<member name="F:Raspberry.Processor.Bcm2835">
<summary>
Processor is BCM2835
</summary>
</member>
<member name="T:Raspberry.Timers.HighResolutionTimer">
<summary>
Represents a high-resolution timer.
</summary>
</member>
<member name="M:Raspberry.Timers.HighResolutionTimer.#ctor">
<summary>
Initializes a new instance of the <see cref="T:Raspberry.Timers.HighResolutionTimer"/> class.
</summary>
</member>
<member name="P:Raspberry.Timers.HighResolutionTimer.Interval">
<summary>
Gets or sets the interval.
</summary>
<value>
The interval.
</value>
</member>
<member name="P:Raspberry.Timers.HighResolutionTimer.Action">
<summary>
Gets or sets the action.
</summary>
<value>
The action.
</value>
</member>
<member name="M:Raspberry.Timers.HighResolutionTimer.Sleep(System.TimeSpan)">
<summary>
Sleeps the specified delay.
</summary>
<param name="delay">The delay.</param>
</member>
<member name="M:Raspberry.Timers.HighResolutionTimer.Start(System.TimeSpan)">
<summary>
Starts this instance.
</summary>
<param name="startDelay">The delay before the first occurence, in milliseconds.</param>
</member>
<member name="M:Raspberry.Timers.HighResolutionTimer.Stop">
<summary>
Stops this instance.
</summary>
</member>
<member name="T:Raspberry.Timers.ITimer">
<summary>
Provides an interface for a timer.
</summary>
</member>
<member name="P:Raspberry.Timers.ITimer.Interval">
<summary>
Gets or sets the interval.
</summary>
<value>
The interval.
</value>
</member>
<member name="P:Raspberry.Timers.ITimer.Action">
<summary>
Gets or sets the action.
</summary>
<value>
The action.
</value>
</member>
<member name="M:Raspberry.Timers.ITimer.Start(System.TimeSpan)">
<summary>
Starts this instance.
</summary>
<param name="startDelay">The delay before the first occurence.</param>
</member>
<member name="M:Raspberry.Timers.ITimer.Stop">
<summary>
Stops this instance.
</summary>
</member>
<member name="T:Raspberry.Timers.StandardTimer">
<summary>
Represents a timer.
</summary>
</member>
<member name="P:Raspberry.Timers.StandardTimer.Interval">
<summary>
Gets or sets the interval, in milliseconds.
</summary>
<value>
The interval, in milliseconds.
</value>
</member>
<member name="P:Raspberry.Timers.StandardTimer.Action">
<summary>
Gets or sets the action.
</summary>
<value>
The action.
</value>
</member>
<member name="M:Raspberry.Timers.StandardTimer.Start(System.TimeSpan)">
<summary>
Starts this instance.
</summary>
<param name="startDelay">The delay before the first occurence, in milliseconds.</param>
</member>
<member name="M:Raspberry.Timers.StandardTimer.Stop">
<summary>
Stops this instance.
</summary>
</member>
<member name="T:Raspberry.Timers.Timer">
<summary>
Provides access to timing features.
</summary>
</member>
<member name="M:Raspberry.Timers.Timer.Create">
<summary>
Creates a timer.
</summary>
<returns>The timer.</returns>
<remarks>
The created timer is the most suitable for the current platform.
</remarks>
</member>
<member name="M:Raspberry.Timers.Timer.Sleep(System.TimeSpan)">
<summary>
Sleeps during the specified time.
</summary>
<param name="time">The time.</param>
</member>
<member name="T:Raspberry.Timers.TimeSpanUtility">
<summary>
Provides utilities for <see cref="T:System.TimeSpan"/>.
</summary>
</member>
<member name="M:Raspberry.Timers.TimeSpanUtility.FromMicroseconds(System.Double)">
<summary>
Creates a timespan from a number of microseconds.
</summary>
<param name="microseconds">The microseconds.</param>
<returns></returns>
</member>
</members>
</doc>

45
NightScout.sln Normal file
View File

@@ -0,0 +1,45 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NightScoutAlert", "NightScout\NightScoutAlert.csproj", "{D74FA0D0-8487-47F3-AB25-A65D221A2F47}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NightscoutLibrary", "NightscoutLibrary\NightscoutLibrary.csproj", "{59DC2B0B-2D94-4841-A181-D3E1124BA5F2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SocketIoClientDotNet.net40", "ThirdParty\SocketIoClientDotNet\Src\SocketIoClientDotNet.net40\SocketIoClientDotNet.net40.csproj", "{53AE4914-A35B-406C-91ED-7E3D9C950F45}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EngineIoClientDotNet.net40", "ThirdParty\EngineIoClientDotNet\Src\EngineIoClientDotNet.net40\EngineIoClientDotNet.net40.csproj", "{833DBCA1-0B01-4477-9937-A8E50E426EE5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{F192A46E-2493-41A3-9698-CE5BEED70178}"
ProjectSection(SolutionItems) = preProject
.nuget\packages.config = .nuget\packages.config
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D74FA0D0-8487-47F3-AB25-A65D221A2F47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D74FA0D0-8487-47F3-AB25-A65D221A2F47}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D74FA0D0-8487-47F3-AB25-A65D221A2F47}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D74FA0D0-8487-47F3-AB25-A65D221A2F47}.Release|Any CPU.Build.0 = Release|Any CPU
{59DC2B0B-2D94-4841-A181-D3E1124BA5F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{59DC2B0B-2D94-4841-A181-D3E1124BA5F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{59DC2B0B-2D94-4841-A181-D3E1124BA5F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{59DC2B0B-2D94-4841-A181-D3E1124BA5F2}.Release|Any CPU.Build.0 = Release|Any CPU
{53AE4914-A35B-406C-91ED-7E3D9C950F45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53AE4914-A35B-406C-91ED-7E3D9C950F45}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53AE4914-A35B-406C-91ED-7E3D9C950F45}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53AE4914-A35B-406C-91ED-7E3D9C950F45}.Release|Any CPU.Build.0 = Release|Any CPU
{833DBCA1-0B01-4477-9937-A8E50E426EE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{833DBCA1-0B01-4477-9937-A8E50E426EE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{833DBCA1-0B01-4477-9937-A8E50E426EE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{833DBCA1-0B01-4477-9937-A8E50E426EE5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NightScout
{
public abstract class Alerter : IAlerter
{
public abstract void StartAlert();
public abstract void StartStaleDataAlert();
public abstract void StartUrgentAlert();
public abstract void StopAlerts();
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NightScout
{
public class ConsoleAlerter : IAlerter
{
public void StartAlert()
{
Console.WriteLine("Alerting");
}
public void StartUrgentAlert()
{
Console.WriteLine("Urgent Alerting");
}
public void StartStaleDataAlert()
{
Console.WriteLine("Stale Data Alerting");
}
public void StopAlerts()
{
Console.WriteLine("Alerts stopped");
}
}
}

View File

@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime;
using System.Text;
using System.Threading.Tasks;
namespace NightScout
{
public class MultiAlerter : IAlerter
{
public List<IAlerter> Alerters { get; set; }
public MultiAlerter(IEnumerable<IAlerter> alerters)
{
Alerters = new List<IAlerter>(alerters);
}
public void StartAlert()
{
Alerters.ForEach(a =>
{
try
{
a.StartAlert();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
});
}
public void StartUrgentAlert()
{
Alerters.ForEach(a =>
{
try
{
a.StartUrgentAlert();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
});
}
public void StartStaleDataAlert()
{
Alerters.ForEach(a =>
{
try
{
a.StartStaleDataAlert();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
});
}
public void StopAlerts()
{
Alerters.ForEach(a =>
{
try
{
a.StopAlerts();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
});
}
}
}

View File

@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NightScout.Interfaces;
namespace NightScout
{
public class RaspberryPiAudioAlert : IAlerter
{
public String PlayerCommandLine { get; set; }
public String KillCommand { get; set; }
public String AlertFileName { get; set; }
protected IRaspberryPiButtonSource ButtonSource;
private Boolean playing = false;
public RaspberryPiAudioAlert()
{
this.PlayerCommandLine = "\"mpg123 -q {0}\"";
this.KillCommand = "pkill mpg123";
this.AlertFileName = "~/ratm.mp3";
}
public RaspberryPiAudioAlert(String playerCommandline)
: base()
{
this.PlayerCommandLine = playerCommandline;
}
public RaspberryPiAudioAlert(String playerCommandline, IRaspberryPiButtonSource buttonSource)
: this(playerCommandline)
{
this.ButtonSource = buttonSource;
this.ButtonSource.ButtonStateChange += ButtonSource_ButtonStateChange;
}
public RaspberryPiAudioAlert(IRaspberryPiButtonSource buttonSource)
: this()
{
this.ButtonSource = buttonSource;
this.ButtonSource.ButtonStateChange += ButtonSource_ButtonStateChange;
}
private void ButtonSource_ButtonStateChange(bool obj)
{
Console.WriteLine("Button state change: {0}", obj);
if(obj)
StopAlerts();
}
public void StartAlert()
{
if (!playing)
{
playing = true;
Process.Start("/bin/bash", String.Format("-c {0}", String.Format(PlayerCommandLine,AlertFileName )));
}
}
public void StartUrgentAlert()
{
StartAlert();
}
public void StartStaleDataAlert()
{
StartAlert();
}
public void StopAlerts()
{
Process.Start("/bin/bash", "-c \"pkill mpg123\"");
playing = false;
}
}
}

67
NightScout/App.config Normal file
View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
</startup>
<appSettings>
<add key="ButtonSourceEnabled" value="false"/>
<add key="NightscoutEndpoint" value="" />
<add key="NightscoutCredentials" value="" />
</appSettings>
<log4net>
<appender name="RootRollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="NightScout.log" />
<param name="AppendToFile" value="true" />
<param name="MaxSizeRollBackups" value="62" />
<param name="RollingStyle" value="Date" />
<datePattern value="yyyy-MM-dd" />
<param name="StaticLogFileName" value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="Header" value="*****************************************************&#xD;&#xA;* NightScout Alerter&#xD;&#xA;* &#xD;&#xA;* started...&#xD;&#xA;" />
<param name="Footer" value="...End of server logging.&#xD;&#xA;" />
<param name="ConversionPattern" value="%d [%t] %-5p %-30.37c{2} - %m%n" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="RootRollingLogFileAppender" />
</root>
</log4net>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="WebSocket4Net" publicKeyToken="eb4e154b696bf72a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-0.15.2.11" newVersion="0.15.2.11" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SuperSocket.ClientEngine" publicKeyToken="ee9af13f57f00acc" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-0.10.0.0" newVersion="0.10.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,10 @@
namespace NightScout
{
public interface IAlerter
{
void StartAlert();
void StartUrgentAlert();
void StartStaleDataAlert();
void StopAlerts();
}
}

View File

@@ -0,0 +1,19 @@
using System;
using Newtonsoft.Json.Linq;
namespace NightScout
{
public interface INightscoutDataSource
{
event Action Connected;
event Action<Object> DataUpdate;
event Action<Object> SocketError;
event Action<Object> Alarm;
event Action<Object> UrgentAlarm;
event Action<Object> ClearAlarm;
event Action StaleDataAlarm;
void Emit(String eventName, String data);
void Emit(String eventName, JObject data);
void Authorize();
}
}

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NightScout.Interfaces
{
public interface IRaspberryPiButtonSource
{
event Action<Boolean> ButtonStateChange;
}
}

View File

@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.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>{D74FA0D0-8487-47F3-AB25-A65D221A2F47}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NightScout</RootNamespace>
<AssemblyName>NightScout</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<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' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<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="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.8\lib\net40-full\log4net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.11.0.1\lib\net40\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Raspberry.IO, Version=2.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Libraries\Raspberry.IO.dll</HintPath>
</Reference>
<Reference Include="Raspberry.IO.GeneralPurpose, Version=2.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Libraries\Raspberry.IO.GeneralPurpose.dll</HintPath>
</Reference>
<Reference Include="Raspberry.IO.Interop, Version=2.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Libraries\Raspberry.IO.Interop.dll</HintPath>
</Reference>
<Reference Include="Raspberry.System, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Libraries\Raspberry.System.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<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" />
</ItemGroup>
<ItemGroup>
<Compile Include="Alerters\Alerter.cs" />
<Compile Include="Alerters\ConsoleAlerter.cs" />
<Compile Include="Interfaces\IAlerter.cs" />
<Compile Include="Interfaces\INightscoutDataSource.cs" />
<Compile Include="Interfaces\IRaspberryPiButtonSource.cs" />
<Compile Include="Alerters\MultiAlerter.cs" />
<Compile Include="NightscoutAlerter.cs" />
<Compile Include="Alerters\RaspberryPiAudioAlert.cs" />
<Compile Include="RaspberryPIButtonSource.cs" />
<Compile Include="SocketIONightscoutDataSource.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NightscoutLibrary\NightscoutLibrary.csproj">
<Project>{59dc2b0b-2d94-4841-a181-d3e1124ba5f2}</Project>
<Name>NightscoutLibrary</Name>
</ProjectReference>
<ProjectReference Include="..\ThirdParty\EngineIoClientDotNet\Src\EngineIoClientDotNet.net40\EngineIoClientDotNet.net40.csproj">
<Project>{833dbca1-0b01-4477-9937-a8e50e426ee5}</Project>
<Name>EngineIoClientDotNet.net40</Name>
</ProjectReference>
<ProjectReference Include="..\ThirdParty\SocketIoClientDotNet\Src\SocketIoClientDotNet.net40\SocketIoClientDotNet.net40.csproj">
<Project>{53ae4914-a35b-406c-91ed-7e3d9c950f45}</Project>
<Name>SocketIoClientDotNet.net40</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,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NightScout
{
public class NightscoutAlerter
{
public INightscoutDataSource DataSource { get; set; }
public IAlerter Alerter { get; set; }
public DateTime LastDataUpdateReceived { get; set; }
public NightscoutAlerter(INightscoutDataSource dataSource, IAlerter alerter)
{
DataSource = dataSource;
Alerter = alerter;
SetupEvents();
}
private void SetupEvents()
{
DataSource.Connected += () => DataSource.Authorize();
DataSource.Alarm += (alarm) => Alerter.StartAlert();
DataSource.UrgentAlarm += (alarm) => Alerter.StartUrgentAlert();
DataSource.ClearAlarm += (alarm) => Alerter.StopAlerts();
DataSource.StaleDataAlarm += () => Alerter.StartStaleDataAlert();
//DataSource.DataUpdate += DataSource_DataUpdate;
}
void DataSource_DataUpdate(object obj)
{
Console.WriteLine(obj);
}
}
}

136
NightScout/Program.cs Normal file
View File

@@ -0,0 +1,136 @@
using System;
using System.Configuration;
using System.Linq;
using System.Threading;
using log4net;
using NightScout;
using NightscoutLibrary.Configuration;
using Quobject.SocketIoClientDotNet.Client;
namespace NightScoutAlert
{
internal class Program
{
private static void Main(string[] args)
{
if (args.Any(arg => arg.Equals("--test-audio")))
{
Console.WriteLine("Starting audio test...");
RaspberryPiAudioAlert alerter = new RaspberryPiAudioAlert();
alerter.StartAlert();
Thread.Sleep(3000);
alerter.StopAlerts();
return;
}
Quobject.EngineIoClientDotNet.Modules.LogManager.Enabled = true;
//NightscoutTestConfiguration configuration = new NightscoutTestConfiguration();
//MonoCompatibleNightscoutAlertConfiguration configuration = new MonoCompatibleNightscoutAlertConfiguration("http://nightscout.chrispr.org:8082", "ThisIsATerribleAuthSystem");
String nightscoutEndpoint = ConfigurationManager.AppSettings["NightscoutEndpoint"];
String nightscoutCredentials = ConfigurationManager.AppSettings["NightscoutCredentials"];
if (String.IsNullOrEmpty(nightscoutEndpoint) || String.IsNullOrEmpty(nightscoutCredentials))
{
Console.WriteLine("The nightscout endpoint and credentials must be filled into the App.config");
return;
}
MonoCompatibleNightscoutAlertConfiguration configuration = new MonoCompatibleNightscoutAlertConfiguration(nightscoutEndpoint, nightscoutCredentials);
RaspberryPIButtonSource buttonSource = null;
try
{
if (!String.IsNullOrEmpty(ConfigurationManager.AppSettings["ButtonSourceEnabled"]) &&
Boolean.Parse(ConfigurationManager.AppSettings["ButtonSourceEnabled"]))
{
buttonSource = new RaspberryPIButtonSource(1);
Console.WriteLine("Button source made");
}
}
catch (Exception)
{}
NightscoutDataSource dataSource =null;
RaspberryPiAudioAlert audioAlerter = null;
if (buttonSource != null)
{
dataSource = new NightscoutDataSource(configuration,
log4net.LogManager.GetLogger("NightscoutAlert"), buttonSource);
audioAlerter = new RaspberryPiAudioAlert(buttonSource);
}
else
{
dataSource = new NightscoutDataSource(configuration,
log4net.LogManager.GetLogger("NightscoutAlert"));
audioAlerter = new RaspberryPiAudioAlert();
}
ILog log = log4net.LogManager.GetLogger("NightscoutAlertMain");
log.Debug("Log started");
ConsoleAlerter consoleAlerter = new ConsoleAlerter();
//
NightscoutAlerter nightscoutAlerter = new NightscoutAlerter(dataSource,
new MultiAlerter(new IAlerter[] {consoleAlerter, audioAlerter, buttonSource}));
//var socket = IO.Socket(configuration.NightscoutBaseURL);
//socket.On(Socket.EVENT_CONNECT, () =>
//{
// Console.WriteLine("Connected...");
// JObject authRequest = new JObject();
// authRequest.Add("client", "web");
// socket.Emit("authorize", authRequest);
//});
//socket.On(Socket.EVENT_ERROR, (obj) =>
//{
// Console.WriteLine(obj.ToString());
//});
//socket.On("dataUpdate", (data) =>
//{
// Console.WriteLine(data);
//});
//socket.On("alarm", (data) =>
//{
// Console.WriteLine(data.ToString());
//});
//socket.On(Socket.EVENT_MESSAGE, (data) =>
//{
// Console.WriteLine(data.ToString());
//});
//socket.On("urgent_alarm", (data) =>
//{
// Console.WriteLine(data.ToString());
//});
//socket.On("clear_alarm", (data) =>
//{
// Console.WriteLine(data.ToString());
//});
Console.WriteLine("Started");
Console.ReadLine();
}
}
class NightscoutTestConfiguration : INightscoutAlertConfiguration
{
public String NightscoutBaseURL
{
//get { return "http://straylight.chrispr.lan:8082"; }
get { return "http://192.168.1.100:8082"; }
set
{throw new NotImplementedException();}
}
public string APISecretKey
{
get { return "ThisIsATerribleAuthSystem"; }
set
{throw new NotImplementedException();}
}
}
}

View File

@@ -0,0 +1,38 @@
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("NightScout")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NightScout")]
[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("5d91c91b-21c0-428c-9937-74115daa2861")]
// 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")]
[assembly: log4net.Config.XmlConfigurator(Watch = true)]

View File

@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NightScout.Interfaces;
using Raspberry.IO.GeneralPurpose;
using Raspberry.IO.GeneralPurpose.Behaviors;
namespace NightScout
{
public class RaspberryPIButtonSource : IRaspberryPiButtonSource, IAlerter
{
public event Action<bool> ButtonStateChange;
protected IGpioConnectionDriver PinDriver;
protected GpioOutputBinaryPin ButtonLEDPin;
private static readonly object ledLock = new object();
public RaspberryPIButtonSource(Int32 pinNumber)
: this(pinNumber, new FileGpioConnectionDriver())
{ }
public RaspberryPIButtonSource(Int32 pinNumber, IGpioConnectionDriver driver)
{
//Attempt to monitor the pin
//pinConfiguration = ConnectorPin.P1Pin11.Input().Name("Switch");
//pinConfiguration.Reversed = true;
//pinConfiguration.OnStatusChanged(PinChangeHandler);
//if(pinConfiguration == null)
// Console.WriteLine("null");
//PinDriver = new FileGpioConnectionDriver();
PinDriver = driver;
//var settings = new GpioConnectionSettings { Driver = pinConnectionDriver };
Console.WriteLine("Making new GPIO connection");
//pinConnection = new GpioConnection(settings,pinConfiguration);
//pinConnectionDriver.Allocate(ProcessorPin.Pin17, PinDirection.Input);
//var pinDriver = pinConnectionDriver.In(ConnectorPin.P1Pin11);
var buttonPin = PinDriver.In(ConnectorPin.P1Pin16);
ButtonLEDPin = PinDriver.Out(ConnectorPin.P1Pin22);
Task.Factory.StartNew(() =>
{
Boolean savedState = false;
while (true)
{
//Pin 11 is inverse (always high unless button is pressed)
Boolean state = !(buttonPin.Read());
if (savedState != state)
{
PinChangeHandler(state);
savedState = state;
}
Thread.Sleep(100);
}
});
//Console.WriteLine("Made");
//pinConnection.PinStatusChanged += pinConnection_PinStatusChanged;
}
private void PinChangeHandler(Boolean state)
{
if (ButtonStateChange != null)
ButtonStateChange(state);
}
public void StartAlert()
{
lock (ledLock)
{
ButtonLEDPin.Write(true);
}
}
public void StartUrgentAlert()
{
lock (ledLock)
{
ButtonLEDPin.Write(true);
}
}
public void StartStaleDataAlert()
{
lock (ledLock)
{
ButtonLEDPin.Write(true);
}
}
public void StopAlerts()
{
lock (ledLock)
{
ButtonLEDPin.Write(false);
}
}
}
}

View File

@@ -0,0 +1,219 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Odbc;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using NightScout.Interfaces;
using NightscoutLibrary.Configuration;
using Quobject.EngineIoClientDotNet.Client.Transports;
using Quobject.SocketIoClientDotNet.Client;
namespace NightScout
{
public class NightscoutDataSource : INightscoutDataSource
{
public Socket Socket { get; set; }
public Manager Manager { get; set; }
public log4net.ILog Logger { get; set; }
public IRaspberryPiButtonSource ButtonSource { get; set; }
public INightscoutAlertConfiguration NightscoutAlertConfiguration { get; set; }
public event Action Connected;
public event Action<Object> DataUpdate;
public event Action<Object> SocketError;
public event Action<Object> Alarm;
public event Action<Object> UrgentAlarm;
public event Action<Object> ClearAlarm;
public event Action StaleDataAlarm;
private DateTime lastDataUpdate = DateTime.Now;
private DateTime lastSgvReading = DateTime.Now;
public NightscoutDataSource(INightscoutAlertConfiguration configuration, log4net.ILog logger)
{
Logger = logger;
NightscoutAlertConfiguration = configuration;
ResetManagerAndConnect();
PrepareSocketEvents();
}
public NightscoutDataSource(INightscoutAlertConfiguration configuration, log4net.ILog logger, IRaspberryPiButtonSource buttonSource)
: this(configuration, logger)
{
ButtonSource = buttonSource;
ButtonSource.ButtonStateChange += ButtonSource_ButtonStateChange;
}
public void Emit(String eventName, String data)
{
Socket.Emit(eventName, data);
}
public void Emit(String eventName, JObject data)
{
Socket.Emit(eventName,data);
}
public virtual void Authorize()
{
JObject authRequest = new JObject {{"client", "web"}};
Socket.Emit("authorize", authRequest);
}
public virtual void ClearAlerts()
{
Logger.Info("Sending Clear Alerts Message");
Socket.Emit("ack", 2, "default", 45 * 60 * 1000);
Logger.Debug("Sent ack");
}
protected virtual void OnConnect()
{
Logger.Info("Connected to Socket.IO endpoint");
if (Connected != null)
Connected();
}
protected virtual void OnDataUpdate(object data)
{
Logger.DebugFormat("Data Update: {0}", data);
if (DataUpdate != null)
DataUpdate(data);
//Update lastUpdated
JObject dataUpdate = JObject.Parse(data.ToString());
if (dataUpdate["lastUpdated"] != null)
{ //lastUpdated is in ms
Int32 lastUpdatedUnixTime = (Int32)(dataUpdate["lastUpdated"].ToObject<Int64>() / 1000);
lastDataUpdate = UnixTimeStampToDateTime(lastUpdatedUnixTime);
Logger.InfoFormat("Last data update reset to {0}", lastDataUpdate);
}
if (dataUpdate["sgvs"] != null)
{
var sgvs = dataUpdate["sgvs"].Children();
var newestSSgv =
sgvs.Where(sgv => sgv["mills"] != null).OrderByDescending(sgv => sgv["mills"].Value<Int64>()).First();
Int64 sgvReadTime = newestSSgv["mills"].Value<Int64>();
DateTime reading = UnixTimeStampToDateTime(sgvReadTime / 1000);;
if (reading > lastSgvReading)
lastSgvReading = reading;
if(newestSSgv["mgdl"] != null)
Logger.InfoFormat("New sgv read of {0} mg/dl on {1}", newestSSgv["mgdl"], lastSgvReading);
}
}
protected virtual void OnSocketError(object error)
{
//Socket.Close();
Logger.InfoFormat("Socket Error: {0}", error);
if (SocketError != null)
SocketError(error);
}
protected virtual void OnAlarm(object alarm)
{
Logger.InfoFormat("Alarm: {0}", alarm);
if (Alarm != null)
Alarm(alarm);
}
protected virtual void OnUrgentAlarm(object alarm)
{
Logger.InfoFormat("Urgent Alarm: {0}", alarm);
if (UrgentAlarm != null)
UrgentAlarm(alarm);
}
protected virtual void OnClearAlarm(object alarm)
{
Logger.InfoFormat("Clear Alarm: {0}", alarm);
if (ClearAlarm != null)
ClearAlarm(alarm);
}
protected virtual void OnStaleDataAlarm()
{
if (StaleDataAlarm != null)
StaleDataAlarm();
}
protected void ResetManagerAndConnect()
{
//, DisablePing = true, Transports = new List<string>() { "polling" }
Options options;
options = new IO.Options();
Manager = new Manager(new Uri(NightscoutAlertConfiguration.NightscoutBaseURL), options);
Socket = Manager.Socket("/"); //IO.Socket(configuration.NightscoutBaseURL, options);
}
private void HeartbeatThread()
{
while (true)
{
//30 minutes - (currentTime - lastDataUpdate)
const double millisecondsToSleep = (5*60*1000); //(30*60*1000) - (DateTime.Now - lastDataUpdate).TotalMilliseconds;
Thread.Sleep((Int32)millisecondsToSleep);
if ((DateTime.Now - lastDataUpdate).TotalMinutes >= 20)
{ //forcefully reset data connection
Logger.Info("Data update timeout, closing socket");
Manager.EngineSocket.Close();
lastDataUpdate = DateTime.Now;
}
if ((DateTime.Now - lastSgvReading).TotalMinutes >= 30)
{ //Stale data alarm
OnStaleDataAlarm();
Logger.Info("Data stale alarm");
lastSgvReading = DateTime.Now;
}
}
}
private void PrepareSocketEvents()
{
Socket.On(Socket.EVENT_CONNECT, OnConnect);
Socket.On(Socket.EVENT_ERROR, OnSocketError);
Socket.On("dataUpdate", OnDataUpdate);
Socket.On("alarm", OnAlarm);
Socket.On("urgent_alarm", OnUrgentAlarm);
Socket.On("clear_alarm", OnClearAlarm);
Manager.On(Manager.EVENT_CONNECT_ERROR, (err) => Logger.InfoFormat("EVENT_CONNECT_ERROR: {0}",err));
Manager.On(Manager.EVENT_ERROR, (err) => Logger.InfoFormat("EVENT_ERROR: {0}", err));
Manager.On(Manager.EVENT_RECONNECT_ERROR, (err) => Logger.InfoFormat("EVENT_RECONNECT_ERROR: {0}", err));
Manager.On(Manager.EVENT_RECONNECT_FAILED, () => Logger.Info("EVENT_RECONNECT_FAILED"));
Manager.On(Manager.EVENT_CLOSE, (reason) => Logger.InfoFormat("EVENT_CLOSE: {0}", reason));
Task.Factory.StartNew(HeartbeatThread,TaskCreationOptions.LongRunning);
}
private void ButtonSource_ButtonStateChange(bool obj)
{
if (obj)
{ //Button pressed, STOP active alerts
ClearAlerts();
}
}
private static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
{
// Unix timestamp is seconds past epoch
System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime();
return dtDateTime;
}
}
}

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="log4net" version="2.0.8" targetFramework="net40" />
<package id="Newtonsoft.Json" version="11.0.1" targetFramework="net40" />
</packages>

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NightscoutLibrary.Configuration
{
public interface INightscoutAlertConfiguration
{
String NightscoutBaseURL { get; set; }
String APISecretKey { get; set; }
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
namespace NightscoutLibrary.Configuration
{
public class MonoCompatibleNightscoutAlertConfiguration : INightscoutAlertConfiguration
{
private String _nightscoutBaseURL;
public string APISecretKey { get; set; }
public MonoCompatibleNightscoutAlertConfiguration(String NightscoutBaseURL, String APISecretKey)
{
this.NightscoutBaseURL = NightscoutBaseURL;
this.APISecretKey = APISecretKey;
}
public string NightscoutBaseURL
{
get { return _nightscoutBaseURL; }
set
{
_nightscoutBaseURL = value;
ResolveHostnameFromURL();
}
}
private void ResolveHostnameFromURL()
{ //Convert any hostname notation into ip-address form to avoid Websocket4Net mono issue regarding hostnames
Uri nightscoutUri = new Uri(_nightscoutBaseURL);
String nightscoutHost = nightscoutUri.DnsSafeHost;
var hostInfo = Dns.GetHostEntry(nightscoutHost);
if(hostInfo.AddressList == null || !hostInfo.AddressList.Any())
throw new ApplicationException("An error occurred while resolving the Nightscout server address");
IPAddress address = hostInfo.AddressList.First();
_nightscoutBaseURL = _nightscoutBaseURL.Replace(nightscoutHost, address.ToString());
}
}
}

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.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>{59DC2B0B-2D94-4841-A181-D3E1124BA5F2}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NightscoutLibrary</RootNamespace>
<AssemblyName>NightscoutLibrary</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<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="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" />
</ItemGroup>
<ItemGroup>
<Compile Include="Configuration\INightscoutAlertConfiguration.cs" />
<Compile Include="Configuration\MonoCompatibleNightscoutAlertConfiguration.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</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,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("NightscoutLibrary")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NightscoutLibrary")]
[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("c985f211-e334-4198-b47a-98f5dc15cc60")]
// 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,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;
}
}
}

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