added stuff
parent
06fc05ee04
commit
f1b7a6de0f
@ -1,14 +1,14 @@
|
|||||||
## Ignore build results and temporary files.
|
## Ignore build results and temporary files.
|
||||||
|
|
||||||
Backup*
|
Backup*
|
||||||
_UpgradeReport_Files
|
_UpgradeReport_Files
|
||||||
bin
|
bin
|
||||||
obj
|
obj
|
||||||
|
|
||||||
*.mdb
|
*.mdb
|
||||||
*.pdb
|
*.pdb
|
||||||
*.pidb
|
*.pidb
|
||||||
*.suo
|
*.suo
|
||||||
*.user
|
*.user
|
||||||
*.userprefs
|
*.userprefs
|
||||||
UpgradeLog*.*
|
UpgradeLog*.*
|
||||||
|
|||||||
@ -0,0 +1,13 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Rider ignored files
|
||||||
|
/.idea.websocket-sharp.iml
|
||||||
|
/contentModel.xml
|
||||||
|
/projectSettingsUpdater.xml
|
||||||
|
/modules.xml
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/../../../../../../../../:\Users\cover\RiderProjects\websocket-sharp\.idea\.idea.websocket-sharp\.idea/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||||
|
</project>
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ContentModelUserStore">
|
||||||
|
<attachedFolders />
|
||||||
|
<explicitIncludes />
|
||||||
|
<explicitExcludes />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="RIDER_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$/../.." />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/TestServer2" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@ -1,26 +1,26 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
// Information about this assembly is defined by the following attributes.
|
// Information about this assembly is defined by the following attributes.
|
||||||
// Change them to the values specific to your project.
|
// Change them to the values specific to your project.
|
||||||
|
|
||||||
[assembly: AssemblyTitle("Example")]
|
[assembly: AssemblyTitle("Example")]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription("")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("")]
|
||||||
[assembly: AssemblyProduct("")]
|
[assembly: AssemblyProduct("")]
|
||||||
[assembly: AssemblyCopyright("sta.blockhead")]
|
[assembly: AssemblyCopyright("sta.blockhead")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||||
|
|
||||||
[assembly: AssemblyVersion("1.0.*")]
|
[assembly: AssemblyVersion("1.0.*")]
|
||||||
|
|
||||||
// The following attributes are used to specify the signing key for the assembly,
|
// The following attributes are used to specify the signing key for the assembly,
|
||||||
// if desired. See the Mono documentation for more information about signing.
|
// if desired. See the Mono documentation for more information about signing.
|
||||||
|
|
||||||
//[assembly: AssemblyDelaySign(false)]
|
//[assembly: AssemblyDelaySign(false)]
|
||||||
//[assembly: AssemblyKeyFile("")]
|
//[assembly: AssemblyKeyFile("")]
|
||||||
|
|||||||
@ -1,71 +1,78 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
<ProductVersion>9.0.21022</ProductVersion>
|
<ProductVersion>9.0.21022</ProductVersion>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
<ProjectGuid>{52805AEC-EFB1-4F42-BB8E-3ED4E692C568}</ProjectGuid>
|
<ProjectGuid>{52805AEC-EFB1-4F42-BB8E-3ED4E692C568}</ProjectGuid>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RootNamespace>Example</RootNamespace>
|
<RootNamespace>Example</RootNamespace>
|
||||||
<AssemblyName>example</AssemblyName>
|
<AssemblyName>example</AssemblyName>
|
||||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Debug</OutputPath>
|
<OutputPath>bin\Debug</OutputPath>
|
||||||
<DefineConstants>DEBUG</DefineConstants>
|
<DefineConstants>DEBUG</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Release</OutputPath>
|
<OutputPath>bin\Release</OutputPath>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
||||||
<DefineConstants>DEBUG,UBUNTU</DefineConstants>
|
<DefineConstants>DEBUG,UBUNTU</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
||||||
<DefineConstants>UBUNTU</DefineConstants>
|
<DefineConstants>UBUNTU</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
|
||||||
<Reference Include="notify-sharp, Version=0.4.0.0, Culture=neutral, PublicKeyToken=2df29c54e245917a">
|
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net35\Newtonsoft.Json.dll</HintPath>
|
||||||
<Package>notify-sharp</Package>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System" />
|
||||||
</ItemGroup>
|
<Reference Include="notify-sharp, Version=0.4.0.0, Culture=neutral, PublicKeyToken=2df29c54e245917a">
|
||||||
<ItemGroup>
|
<Package>notify-sharp</Package>
|
||||||
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
</Reference>
|
||||||
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
<Reference Include="System.Core" />
|
||||||
<Name>websocket-sharp</Name>
|
</ItemGroup>
|
||||||
</ProjectReference>
|
<ItemGroup>
|
||||||
</ItemGroup>
|
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
||||||
<ItemGroup>
|
<Name>websocket-sharp</Name>
|
||||||
<Compile Include="Program.cs" />
|
</ProjectReference>
|
||||||
<Compile Include="AssemblyInfo.cs" />
|
</ItemGroup>
|
||||||
<Compile Include="Notifier.cs" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<Compile Include="NotificationMessage.cs" />
|
<ItemGroup>
|
||||||
</ItemGroup>
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Notifier.cs" />
|
||||||
|
<Compile Include="NotificationMessage.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@ -1,24 +1,24 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Example
|
namespace Example
|
||||||
{
|
{
|
||||||
internal class NotificationMessage
|
internal class NotificationMessage
|
||||||
{
|
{
|
||||||
public string Body {
|
public string Body {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Icon {
|
public string Icon {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Summary {
|
public string Summary {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString ()
|
public override string ToString ()
|
||||||
{
|
{
|
||||||
return String.Format ("{0}: {1}", Summary, Body);
|
return String.Format ("{0}: {1}", Summary, Body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,81 +1,81 @@
|
|||||||
#if UBUNTU
|
#if UBUNTU
|
||||||
using Notifications;
|
using Notifications;
|
||||||
#endif
|
#endif
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Example
|
namespace Example
|
||||||
{
|
{
|
||||||
internal class Notifier : IDisposable
|
internal class Notifier : IDisposable
|
||||||
{
|
{
|
||||||
private volatile bool _enabled;
|
private volatile bool _enabled;
|
||||||
private ManualResetEvent _exited;
|
private ManualResetEvent _exited;
|
||||||
private Queue<NotificationMessage> _queue;
|
private Queue<NotificationMessage> _queue;
|
||||||
private object _sync;
|
private object _sync;
|
||||||
|
|
||||||
public Notifier ()
|
public Notifier ()
|
||||||
{
|
{
|
||||||
_enabled = true;
|
_enabled = true;
|
||||||
_exited = new ManualResetEvent (false);
|
_exited = new ManualResetEvent (false);
|
||||||
_queue = new Queue<NotificationMessage> ();
|
_queue = new Queue<NotificationMessage> ();
|
||||||
_sync = ((ICollection) _queue).SyncRoot;
|
_sync = ((ICollection) _queue).SyncRoot;
|
||||||
|
|
||||||
ThreadPool.QueueUserWorkItem (
|
ThreadPool.QueueUserWorkItem (
|
||||||
state => {
|
state => {
|
||||||
while (_enabled || Count > 0) {
|
while (_enabled || Count > 0) {
|
||||||
var msg = dequeue ();
|
var msg = dequeue ();
|
||||||
if (msg != null) {
|
if (msg != null) {
|
||||||
#if UBUNTU
|
#if UBUNTU
|
||||||
var nf = new Notification (msg.Summary, msg.Body, msg.Icon);
|
var nf = new Notification (msg.Summary, msg.Body, msg.Icon);
|
||||||
nf.AddHint ("append", "allowed");
|
nf.AddHint ("append", "allowed");
|
||||||
nf.Show ();
|
nf.Show ();
|
||||||
#else
|
#else
|
||||||
Console.WriteLine (msg);
|
Console.WriteLine (msg);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Thread.Sleep (500);
|
Thread.Sleep (500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_exited.Set ();
|
_exited.Set ();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Count {
|
public int Count {
|
||||||
get {
|
get {
|
||||||
lock (_sync)
|
lock (_sync)
|
||||||
return _queue.Count;
|
return _queue.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private NotificationMessage dequeue ()
|
private NotificationMessage dequeue ()
|
||||||
{
|
{
|
||||||
lock (_sync)
|
lock (_sync)
|
||||||
return _queue.Count > 0 ? _queue.Dequeue () : null;
|
return _queue.Count > 0 ? _queue.Dequeue () : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close ()
|
public void Close ()
|
||||||
{
|
{
|
||||||
_enabled = false;
|
_enabled = false;
|
||||||
_exited.WaitOne ();
|
_exited.WaitOne ();
|
||||||
_exited.Close ();
|
_exited.Close ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Notify (NotificationMessage message)
|
public void Notify (NotificationMessage message)
|
||||||
{
|
{
|
||||||
lock (_sync) {
|
lock (_sync) {
|
||||||
if (_enabled)
|
if (_enabled)
|
||||||
_queue.Enqueue (message);
|
_queue.Enqueue (message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDisposable.Dispose ()
|
void IDisposable.Dispose ()
|
||||||
{
|
{
|
||||||
Close ();
|
Close ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,128 +1,128 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using WebSocketSharp;
|
using WebSocketSharp;
|
||||||
using WebSocketSharp.Net;
|
using WebSocketSharp.Net;
|
||||||
|
|
||||||
namespace Example
|
namespace Example
|
||||||
{
|
{
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
public static void Main (string[] args)
|
public static void Main (string[] args)
|
||||||
{
|
{
|
||||||
// Create a new instance of the WebSocket class.
|
// Create a new instance of the WebSocket class.
|
||||||
//
|
//
|
||||||
// The WebSocket class inherits the System.IDisposable interface, so you can
|
// The WebSocket class inherits the System.IDisposable interface, so you can
|
||||||
// use the using statement. And the WebSocket connection will be closed with
|
// use the using statement. And the WebSocket connection will be closed with
|
||||||
// close status 1001 (going away) when the control leaves the using block.
|
// close status 1001 (going away) when the control leaves the using block.
|
||||||
//
|
//
|
||||||
// If you would like to connect to the server with the secure connection,
|
// If you would like to connect to the server with the secure connection,
|
||||||
// you should create a new instance with a wss scheme WebSocket URL.
|
// you should create a new instance with a wss scheme WebSocket URL.
|
||||||
|
|
||||||
using (var nf = new Notifier ())
|
using (var nf = new Notifier ())
|
||||||
using (var ws = new WebSocket ("ws://echo.websocket.org"))
|
using (var ws = new WebSocket ("ws://echo.websocket.org"))
|
||||||
//using (var ws = new WebSocket ("wss://echo.websocket.org"))
|
//using (var ws = new WebSocket ("wss://echo.websocket.org"))
|
||||||
//using (var ws = new WebSocket ("ws://localhost:4649/Echo"))
|
//using (var ws = new WebSocket ("ws://localhost:4649/Echo"))
|
||||||
//using (var ws = new WebSocket ("wss://localhost:5963/Echo"))
|
//using (var ws = new WebSocket ("wss://localhost:5963/Echo"))
|
||||||
//using (var ws = new WebSocket ("ws://localhost:4649/Echo?name=nobita"))
|
//using (var ws = new WebSocket ("ws://localhost:4649/Echo?name=nobita"))
|
||||||
//using (var ws = new WebSocket ("wss://localhost:5963/Echo?name=nobita"))
|
//using (var ws = new WebSocket ("wss://localhost:5963/Echo?name=nobita"))
|
||||||
//using (var ws = new WebSocket ("ws://localhost:4649/Chat"))
|
//using (var ws = new WebSocket ("ws://localhost:4649/Chat"))
|
||||||
//using (var ws = new WebSocket ("wss://localhost:5963/Chat"))
|
//using (var ws = new WebSocket ("wss://localhost:5963/Chat"))
|
||||||
//using (var ws = new WebSocket ("ws://localhost:4649/Chat?name=nobita"))
|
//using (var ws = new WebSocket ("ws://localhost:4649/Chat?name=nobita"))
|
||||||
//using (var ws = new WebSocket ("wss://localhost:5963/Chat?name=nobita"))
|
//using (var ws = new WebSocket ("wss://localhost:5963/Chat?name=nobita"))
|
||||||
{
|
{
|
||||||
// Set the WebSocket events.
|
// Set the WebSocket events.
|
||||||
|
|
||||||
ws.OnOpen += (sender, e) => ws.Send ("Hi, there!");
|
ws.OnOpen += (sender, e) => ws.Send ("Hi, there!");
|
||||||
|
|
||||||
ws.OnMessage += (sender, e) =>
|
ws.OnMessage += (sender, e) =>
|
||||||
nf.Notify (
|
nf.Notify (
|
||||||
new NotificationMessage {
|
new NotificationMessage {
|
||||||
Summary = "WebSocket Message",
|
Summary = "WebSocket Message",
|
||||||
Body = !e.IsPing ? e.Data : "Received a ping.",
|
Body = !e.IsPing ? e.Data : "Received a ping.",
|
||||||
Icon = "notification-message-im"
|
Icon = "notification-message-im"
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
ws.OnError += (sender, e) =>
|
ws.OnError += (sender, e) =>
|
||||||
nf.Notify (
|
nf.Notify (
|
||||||
new NotificationMessage {
|
new NotificationMessage {
|
||||||
Summary = "WebSocket Error",
|
Summary = "WebSocket Error",
|
||||||
Body = e.Message,
|
Body = e.Message,
|
||||||
Icon = "notification-message-im"
|
Icon = "notification-message-im"
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
ws.OnClose += (sender, e) =>
|
ws.OnClose += (sender, e) =>
|
||||||
nf.Notify (
|
nf.Notify (
|
||||||
new NotificationMessage {
|
new NotificationMessage {
|
||||||
Summary = String.Format ("WebSocket Close ({0})", e.Code),
|
Summary = String.Format ("WebSocket Close ({0})", e.Code),
|
||||||
Body = e.Reason,
|
Body = e.Reason,
|
||||||
Icon = "notification-message-im"
|
Icon = "notification-message-im"
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
// To change the logging level.
|
// To change the logging level.
|
||||||
ws.Log.Level = LogLevel.Trace;
|
ws.Log.Level = LogLevel.Trace;
|
||||||
|
|
||||||
// To change the wait time for the response to the Ping or Close.
|
// To change the wait time for the response to the Ping or Close.
|
||||||
//ws.WaitTime = TimeSpan.FromSeconds (10);
|
//ws.WaitTime = TimeSpan.FromSeconds (10);
|
||||||
|
|
||||||
// To emit a WebSocket.OnMessage event when receives a ping.
|
// To emit a WebSocket.OnMessage event when receives a ping.
|
||||||
//ws.EmitOnPing = true;
|
//ws.EmitOnPing = true;
|
||||||
#endif
|
#endif
|
||||||
// To enable the Per-message Compression extension.
|
// To enable the Per-message Compression extension.
|
||||||
//ws.Compression = CompressionMethod.Deflate;
|
//ws.Compression = CompressionMethod.Deflate;
|
||||||
|
|
||||||
// To validate the server certificate.
|
// To validate the server certificate.
|
||||||
/*
|
/*
|
||||||
ws.SslConfiguration.ServerCertificateValidationCallback =
|
ws.SslConfiguration.ServerCertificateValidationCallback =
|
||||||
(sender, certificate, chain, sslPolicyErrors) => {
|
(sender, certificate, chain, sslPolicyErrors) => {
|
||||||
ws.Log.Debug (
|
ws.Log.Debug (
|
||||||
String.Format (
|
String.Format (
|
||||||
"Certificate:\n- Issuer: {0}\n- Subject: {1}",
|
"Certificate:\n- Issuer: {0}\n- Subject: {1}",
|
||||||
certificate.Issuer,
|
certificate.Issuer,
|
||||||
certificate.Subject
|
certificate.Subject
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return true; // If the server certificate is valid.
|
return true; // If the server certificate is valid.
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// To send the credentials for the HTTP Authentication (Basic/Digest).
|
// To send the credentials for the HTTP Authentication (Basic/Digest).
|
||||||
//ws.SetCredentials ("nobita", "password", false);
|
//ws.SetCredentials ("nobita", "password", false);
|
||||||
|
|
||||||
// To send the Origin header.
|
// To send the Origin header.
|
||||||
//ws.Origin = "http://localhost:4649";
|
//ws.Origin = "http://localhost:4649";
|
||||||
|
|
||||||
// To send the cookies.
|
// To send the cookies.
|
||||||
//ws.SetCookie (new Cookie ("name", "nobita"));
|
//ws.SetCookie (new Cookie ("name", "nobita"));
|
||||||
//ws.SetCookie (new Cookie ("roles", "\"idiot, gunfighter\""));
|
//ws.SetCookie (new Cookie ("roles", "\"idiot, gunfighter\""));
|
||||||
|
|
||||||
// To connect through the HTTP Proxy server.
|
// To connect through the HTTP Proxy server.
|
||||||
//ws.SetProxy ("http://localhost:3128", "nobita", "password");
|
//ws.SetProxy ("http://localhost:3128", "nobita", "password");
|
||||||
|
|
||||||
// To enable the redirection.
|
// To enable the redirection.
|
||||||
//ws.EnableRedirection = true;
|
//ws.EnableRedirection = true;
|
||||||
|
|
||||||
// Connect to the server.
|
// Connect to the server.
|
||||||
ws.Connect ();
|
ws.Connect ();
|
||||||
|
|
||||||
// Connect to the server asynchronously.
|
// Connect to the server asynchronously.
|
||||||
//ws.ConnectAsync ();
|
//ws.ConnectAsync ();
|
||||||
|
|
||||||
Console.WriteLine ("\nType 'exit' to exit.\n");
|
Console.WriteLine ("\nType 'exit' to exit.\n");
|
||||||
while (true) {
|
while (true) {
|
||||||
Thread.Sleep (1000);
|
Thread.Sleep (1000);
|
||||||
Console.Write ("> ");
|
Console.Write ("> ");
|
||||||
var msg = Console.ReadLine ();
|
var msg = Console.ReadLine ();
|
||||||
if (msg == "exit")
|
if (msg == "exit")
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Send a text message.
|
// Send a text message.
|
||||||
ws.Send (msg);
|
ws.Send (msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net35" />
|
||||||
|
</packages>
|
||||||
@ -1,26 +1,26 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
// Information about this assembly is defined by the following attributes.
|
// Information about this assembly is defined by the following attributes.
|
||||||
// Change them to the values specific to your project.
|
// Change them to the values specific to your project.
|
||||||
|
|
||||||
[assembly: AssemblyTitle("Example1")]
|
[assembly: AssemblyTitle("Example1")]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription("")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("")]
|
||||||
[assembly: AssemblyProduct("")]
|
[assembly: AssemblyProduct("")]
|
||||||
[assembly: AssemblyCopyright("sta.blockhead")]
|
[assembly: AssemblyCopyright("sta.blockhead")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||||
|
|
||||||
[assembly: AssemblyVersion("1.0.*")]
|
[assembly: AssemblyVersion("1.0.*")]
|
||||||
|
|
||||||
// The following attributes are used to specify the signing key for the assembly,
|
// The following attributes are used to specify the signing key for the assembly,
|
||||||
// if desired. See the Mono documentation for more information about signing.
|
// if desired. See the Mono documentation for more information about signing.
|
||||||
|
|
||||||
//[assembly: AssemblyDelaySign(false)]
|
//[assembly: AssemblyDelaySign(false)]
|
||||||
//[assembly: AssemblyKeyFile("")]
|
//[assembly: AssemblyKeyFile("")]
|
||||||
|
|||||||
@ -1,192 +1,192 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using WebSocketSharp;
|
using WebSocketSharp;
|
||||||
|
|
||||||
namespace Example1
|
namespace Example1
|
||||||
{
|
{
|
||||||
internal class AudioStreamer : IDisposable
|
internal class AudioStreamer : IDisposable
|
||||||
{
|
{
|
||||||
private Dictionary<uint, Queue> _audioBox;
|
private Dictionary<uint, Queue> _audioBox;
|
||||||
private uint? _id;
|
private uint? _id;
|
||||||
private string _name;
|
private string _name;
|
||||||
private Notifier _notifier;
|
private Notifier _notifier;
|
||||||
private Timer _timer;
|
private Timer _timer;
|
||||||
private WebSocket _websocket;
|
private WebSocket _websocket;
|
||||||
|
|
||||||
public AudioStreamer (string url)
|
public AudioStreamer (string url)
|
||||||
{
|
{
|
||||||
_websocket = new WebSocket (url);
|
_websocket = new WebSocket (url);
|
||||||
|
|
||||||
_audioBox = new Dictionary<uint, Queue> ();
|
_audioBox = new Dictionary<uint, Queue> ();
|
||||||
_id = null;
|
_id = null;
|
||||||
_notifier = new Notifier ();
|
_notifier = new Notifier ();
|
||||||
_timer = new Timer (sendHeartbeat, null, -1, -1);
|
_timer = new Timer (sendHeartbeat, null, -1, -1);
|
||||||
|
|
||||||
configure ();
|
configure ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configure ()
|
private void configure ()
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
_websocket.Log.Level = LogLevel.Trace;
|
_websocket.Log.Level = LogLevel.Trace;
|
||||||
#endif
|
#endif
|
||||||
_websocket.OnOpen += (sender, e) =>
|
_websocket.OnOpen += (sender, e) =>
|
||||||
_websocket.Send (createTextMessage ("connection", String.Empty));
|
_websocket.Send (createTextMessage ("connection", String.Empty));
|
||||||
|
|
||||||
_websocket.OnMessage += (sender, e) => {
|
_websocket.OnMessage += (sender, e) => {
|
||||||
if (e.IsText) {
|
if (e.IsText) {
|
||||||
_notifier.Notify (processTextMessage (e.Data));
|
_notifier.Notify (processTextMessage (e.Data));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.IsBinary) {
|
if (e.IsBinary) {
|
||||||
processBinaryMessage (e.RawData);
|
processBinaryMessage (e.RawData);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_websocket.OnError += (sender, e) =>
|
_websocket.OnError += (sender, e) =>
|
||||||
_notifier.Notify (
|
_notifier.Notify (
|
||||||
new NotificationMessage {
|
new NotificationMessage {
|
||||||
Summary = "AudioStreamer (error)",
|
Summary = "AudioStreamer (error)",
|
||||||
Body = e.Message,
|
Body = e.Message,
|
||||||
Icon = "notification-message-im"
|
Icon = "notification-message-im"
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
_websocket.OnClose += (sender, e) =>
|
_websocket.OnClose += (sender, e) =>
|
||||||
_notifier.Notify (
|
_notifier.Notify (
|
||||||
new NotificationMessage {
|
new NotificationMessage {
|
||||||
Summary = "AudioStreamer (disconnect)",
|
Summary = "AudioStreamer (disconnect)",
|
||||||
Body = String.Format ("code: {0} reason: {1}", e.Code, e.Reason),
|
Body = String.Format ("code: {0} reason: {1}", e.Code, e.Reason),
|
||||||
Icon = "notification-message-im"
|
Icon = "notification-message-im"
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] createBinaryMessage (float[,] bufferArray)
|
private byte[] createBinaryMessage (float[,] bufferArray)
|
||||||
{
|
{
|
||||||
return new BinaryMessage {
|
return new BinaryMessage {
|
||||||
UserID = (uint) _id,
|
UserID = (uint) _id,
|
||||||
ChannelNumber = (byte) bufferArray.GetLength (0),
|
ChannelNumber = (byte) bufferArray.GetLength (0),
|
||||||
BufferLength = (uint) bufferArray.GetLength (1),
|
BufferLength = (uint) bufferArray.GetLength (1),
|
||||||
BufferArray = bufferArray
|
BufferArray = bufferArray
|
||||||
}
|
}
|
||||||
.ToArray ();
|
.ToArray ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private string createTextMessage (string type, string message)
|
private string createTextMessage (string type, string message)
|
||||||
{
|
{
|
||||||
return new TextMessage {
|
return new TextMessage {
|
||||||
UserID = _id,
|
UserID = _id,
|
||||||
Name = _name,
|
Name = _name,
|
||||||
Type = type,
|
Type = type,
|
||||||
Message = message
|
Message = message
|
||||||
}
|
}
|
||||||
.ToString ();
|
.ToString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processBinaryMessage (byte[] data)
|
private void processBinaryMessage (byte[] data)
|
||||||
{
|
{
|
||||||
var msg = BinaryMessage.Parse (data);
|
var msg = BinaryMessage.Parse (data);
|
||||||
|
|
||||||
var id = msg.UserID;
|
var id = msg.UserID;
|
||||||
if (id == _id)
|
if (id == _id)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Queue queue;
|
Queue queue;
|
||||||
if (_audioBox.TryGetValue (id, out queue)) {
|
if (_audioBox.TryGetValue (id, out queue)) {
|
||||||
queue.Enqueue (msg.BufferArray);
|
queue.Enqueue (msg.BufferArray);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
queue = Queue.Synchronized (new Queue ());
|
queue = Queue.Synchronized (new Queue ());
|
||||||
queue.Enqueue (msg.BufferArray);
|
queue.Enqueue (msg.BufferArray);
|
||||||
_audioBox.Add (id, queue);
|
_audioBox.Add (id, queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NotificationMessage processTextMessage (string data)
|
private NotificationMessage processTextMessage (string data)
|
||||||
{
|
{
|
||||||
var json = JObject.Parse (data);
|
var json = JObject.Parse (data);
|
||||||
var id = (uint) json["user_id"];
|
var id = (uint) json["user_id"];
|
||||||
var name = (string) json["name"];
|
var name = (string) json["name"];
|
||||||
var type = (string) json["type"];
|
var type = (string) json["type"];
|
||||||
|
|
||||||
string body;
|
string body;
|
||||||
if (type == "message") {
|
if (type == "message") {
|
||||||
body = String.Format ("{0}: {1}", name, (string) json["message"]);
|
body = String.Format ("{0}: {1}", name, (string) json["message"]);
|
||||||
}
|
}
|
||||||
else if (type == "start_music") {
|
else if (type == "start_music") {
|
||||||
body = String.Format ("{0}: Started playing music!", name);
|
body = String.Format ("{0}: Started playing music!", name);
|
||||||
}
|
}
|
||||||
else if (type == "connection") {
|
else if (type == "connection") {
|
||||||
var users = (JArray) json["message"];
|
var users = (JArray) json["message"];
|
||||||
var buff = new StringBuilder ("Now keeping connections:");
|
var buff = new StringBuilder ("Now keeping connections:");
|
||||||
foreach (JToken user in users) {
|
foreach (JToken user in users) {
|
||||||
buff.AppendFormat (
|
buff.AppendFormat (
|
||||||
"\n- user_id: {0} name: {1}", (uint) user["user_id"], (string) user["name"]
|
"\n- user_id: {0} name: {1}", (uint) user["user_id"], (string) user["name"]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
body = buff.ToString ();
|
body = buff.ToString ();
|
||||||
}
|
}
|
||||||
else if (type == "connected") {
|
else if (type == "connected") {
|
||||||
_id = id;
|
_id = id;
|
||||||
_timer.Change (30000, 30000);
|
_timer.Change (30000, 30000);
|
||||||
|
|
||||||
body = String.Format ("user_id: {0} name: {1}", id, name);
|
body = String.Format ("user_id: {0} name: {1}", id, name);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
body = "Received unknown type message.";
|
body = "Received unknown type message.";
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NotificationMessage {
|
return new NotificationMessage {
|
||||||
Summary = String.Format ("AudioStreamer ({0})", type),
|
Summary = String.Format ("AudioStreamer ({0})", type),
|
||||||
Body = body,
|
Body = body,
|
||||||
Icon = "notification-message-im"
|
Icon = "notification-message-im"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendHeartbeat (object state)
|
private void sendHeartbeat (object state)
|
||||||
{
|
{
|
||||||
_websocket.Send (createTextMessage ("heartbeat", String.Empty));
|
_websocket.Send (createTextMessage ("heartbeat", String.Empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close ()
|
public void Close ()
|
||||||
{
|
{
|
||||||
Disconnect ();
|
Disconnect ();
|
||||||
_timer.Dispose ();
|
_timer.Dispose ();
|
||||||
_notifier.Close ();
|
_notifier.Close ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Connect (string username)
|
public void Connect (string username)
|
||||||
{
|
{
|
||||||
_name = username;
|
_name = username;
|
||||||
_websocket.Connect ();
|
_websocket.Connect ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Disconnect ()
|
public void Disconnect ()
|
||||||
{
|
{
|
||||||
_timer.Change (-1, -1);
|
_timer.Change (-1, -1);
|
||||||
_websocket.Close (CloseStatusCode.Away);
|
_websocket.Close (CloseStatusCode.Away);
|
||||||
_audioBox.Clear ();
|
_audioBox.Clear ();
|
||||||
_id = null;
|
_id = null;
|
||||||
_name = null;
|
_name = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write (string message)
|
public void Write (string message)
|
||||||
{
|
{
|
||||||
_websocket.Send (createTextMessage ("message", message));
|
_websocket.Send (createTextMessage ("message", message));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDisposable.Dispose ()
|
void IDisposable.Dispose ()
|
||||||
{
|
{
|
||||||
Close ();
|
Close ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,74 +1,74 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using WebSocketSharp;
|
using WebSocketSharp;
|
||||||
|
|
||||||
namespace Example1
|
namespace Example1
|
||||||
{
|
{
|
||||||
internal class BinaryMessage
|
internal class BinaryMessage
|
||||||
{
|
{
|
||||||
public uint UserID {
|
public uint UserID {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte ChannelNumber {
|
public byte ChannelNumber {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint BufferLength {
|
public uint BufferLength {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float[,] BufferArray {
|
public float[,] BufferArray {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BinaryMessage Parse (byte[] data)
|
public static BinaryMessage Parse (byte[] data)
|
||||||
{
|
{
|
||||||
var id = data.SubArray (0, 4).To<uint> (ByteOrder.Big);
|
var id = data.SubArray (0, 4).To<uint> (ByteOrder.Big);
|
||||||
var num = data.SubArray (4, 1)[0];
|
var num = data.SubArray (4, 1)[0];
|
||||||
var len = data.SubArray (5, 4).To<uint> (ByteOrder.Big);
|
var len = data.SubArray (5, 4).To<uint> (ByteOrder.Big);
|
||||||
var arr = new float[num, len];
|
var arr = new float[num, len];
|
||||||
|
|
||||||
var offset = 9;
|
var offset = 9;
|
||||||
((uint) num).Times (
|
((uint) num).Times (
|
||||||
i =>
|
i =>
|
||||||
len.Times (
|
len.Times (
|
||||||
j => {
|
j => {
|
||||||
arr[i, j] = data.SubArray (offset, 4).To<float> (ByteOrder.Big);
|
arr[i, j] = data.SubArray (offset, 4).To<float> (ByteOrder.Big);
|
||||||
offset += 4;
|
offset += 4;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return new BinaryMessage {
|
return new BinaryMessage {
|
||||||
UserID = id,
|
UserID = id,
|
||||||
ChannelNumber = num,
|
ChannelNumber = num,
|
||||||
BufferLength = len,
|
BufferLength = len,
|
||||||
BufferArray = arr
|
BufferArray = arr
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] ToArray ()
|
public byte[] ToArray ()
|
||||||
{
|
{
|
||||||
var buff = new List<byte> ();
|
var buff = new List<byte> ();
|
||||||
|
|
||||||
var id = UserID;
|
var id = UserID;
|
||||||
var num = ChannelNumber;
|
var num = ChannelNumber;
|
||||||
var len = BufferLength;
|
var len = BufferLength;
|
||||||
var arr = BufferArray;
|
var arr = BufferArray;
|
||||||
|
|
||||||
buff.AddRange (id.ToByteArray (ByteOrder.Big));
|
buff.AddRange (id.ToByteArray (ByteOrder.Big));
|
||||||
buff.Add (num);
|
buff.Add (num);
|
||||||
buff.AddRange (len.ToByteArray (ByteOrder.Big));
|
buff.AddRange (len.ToByteArray (ByteOrder.Big));
|
||||||
|
|
||||||
((uint) num).Times (
|
((uint) num).Times (
|
||||||
i =>
|
i =>
|
||||||
len.Times (
|
len.Times (
|
||||||
j => buff.AddRange (arr[i, j].ToByteArray (ByteOrder.Big))
|
j => buff.AddRange (arr[i, j].ToByteArray (ByteOrder.Big))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return buff.ToArray ();
|
return buff.ToArray ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,77 +1,81 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
<ProductVersion>9.0.21022</ProductVersion>
|
<ProductVersion>9.0.21022</ProductVersion>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
<ProjectGuid>{390E2568-57B7-4D17-91E5-C29336368CCF}</ProjectGuid>
|
<ProjectGuid>{390E2568-57B7-4D17-91E5-C29336368CCF}</ProjectGuid>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RootNamespace>Example</RootNamespace>
|
<RootNamespace>Example</RootNamespace>
|
||||||
<AssemblyName>example1</AssemblyName>
|
<AssemblyName>example1</AssemblyName>
|
||||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Debug</OutputPath>
|
<OutputPath>bin\Debug</OutputPath>
|
||||||
<DefineConstants>DEBUG;</DefineConstants>
|
<DefineConstants>DEBUG;</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Release</OutputPath>
|
<OutputPath>bin\Release</OutputPath>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
||||||
<DefineConstants>DEBUG;UBUNTU</DefineConstants>
|
<DefineConstants>DEBUG;UBUNTU</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
<DefineConstants>UBUNTU</DefineConstants>
|
<DefineConstants>UBUNTU</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
|
||||||
<Reference Include="notify-sharp, Version=0.4.0.0, Culture=neutral, PublicKeyToken=2df29c54e245917a">
|
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net35\Newtonsoft.Json.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>True</Private>
|
||||||
<Package>notify-sharp</Package>
|
</Reference>
|
||||||
</Reference>
|
<Reference Include="System" />
|
||||||
<Reference Include="Newtonsoft.Json, Version=3.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
|
<Reference Include="notify-sharp, Version=0.4.0.0, Culture=neutral, PublicKeyToken=2df29c54e245917a">
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
<Package>notify-sharp</Package>
|
||||||
</ItemGroup>
|
</Reference>
|
||||||
<ItemGroup>
|
</ItemGroup>
|
||||||
<Compile Include="AssemblyInfo.cs" />
|
<ItemGroup>
|
||||||
<Compile Include="AudioStreamer.cs" />
|
<Compile Include="AssemblyInfo.cs" />
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="AudioStreamer.cs" />
|
||||||
<Compile Include="TextMessage.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="NotificationMessage.cs" />
|
<Compile Include="TextMessage.cs" />
|
||||||
<Compile Include="Notifier.cs" />
|
<Compile Include="NotificationMessage.cs" />
|
||||||
<Compile Include="BinaryMessage.cs" />
|
<Compile Include="Notifier.cs" />
|
||||||
</ItemGroup>
|
<Compile Include="BinaryMessage.cs" />
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
<ItemGroup>
|
||||||
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
||||||
<Name>websocket-sharp</Name>
|
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
||||||
</ProjectReference>
|
<Name>websocket-sharp</Name>
|
||||||
</ItemGroup>
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@ -1,24 +1,24 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Example1
|
namespace Example1
|
||||||
{
|
{
|
||||||
internal class NotificationMessage
|
internal class NotificationMessage
|
||||||
{
|
{
|
||||||
public string Body {
|
public string Body {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Icon {
|
public string Icon {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Summary {
|
public string Summary {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString ()
|
public override string ToString ()
|
||||||
{
|
{
|
||||||
return String.Format ("{0}: {1}", Summary, Body);
|
return String.Format ("{0}: {1}", Summary, Body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,81 +1,81 @@
|
|||||||
#if UBUNTU
|
#if UBUNTU
|
||||||
using Notifications;
|
using Notifications;
|
||||||
#endif
|
#endif
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Example1
|
namespace Example1
|
||||||
{
|
{
|
||||||
internal class Notifier : IDisposable
|
internal class Notifier : IDisposable
|
||||||
{
|
{
|
||||||
private volatile bool _enabled;
|
private volatile bool _enabled;
|
||||||
private ManualResetEvent _exited;
|
private ManualResetEvent _exited;
|
||||||
private Queue<NotificationMessage> _queue;
|
private Queue<NotificationMessage> _queue;
|
||||||
private object _sync;
|
private object _sync;
|
||||||
|
|
||||||
public Notifier ()
|
public Notifier ()
|
||||||
{
|
{
|
||||||
_enabled = true;
|
_enabled = true;
|
||||||
_exited = new ManualResetEvent (false);
|
_exited = new ManualResetEvent (false);
|
||||||
_queue = new Queue<NotificationMessage> ();
|
_queue = new Queue<NotificationMessage> ();
|
||||||
_sync = ((ICollection) _queue).SyncRoot;
|
_sync = ((ICollection) _queue).SyncRoot;
|
||||||
|
|
||||||
ThreadPool.QueueUserWorkItem (
|
ThreadPool.QueueUserWorkItem (
|
||||||
state => {
|
state => {
|
||||||
while (_enabled || Count > 0) {
|
while (_enabled || Count > 0) {
|
||||||
var msg = dequeue ();
|
var msg = dequeue ();
|
||||||
if (msg != null) {
|
if (msg != null) {
|
||||||
#if UBUNTU
|
#if UBUNTU
|
||||||
var nf = new Notification (msg.Summary, msg.Body, msg.Icon);
|
var nf = new Notification (msg.Summary, msg.Body, msg.Icon);
|
||||||
nf.AddHint ("append", "allowed");
|
nf.AddHint ("append", "allowed");
|
||||||
nf.Show ();
|
nf.Show ();
|
||||||
#else
|
#else
|
||||||
Console.WriteLine (msg);
|
Console.WriteLine (msg);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Thread.Sleep (500);
|
Thread.Sleep (500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_exited.Set ();
|
_exited.Set ();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Count {
|
public int Count {
|
||||||
get {
|
get {
|
||||||
lock (_sync)
|
lock (_sync)
|
||||||
return _queue.Count;
|
return _queue.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private NotificationMessage dequeue ()
|
private NotificationMessage dequeue ()
|
||||||
{
|
{
|
||||||
lock (_sync)
|
lock (_sync)
|
||||||
return _queue.Count > 0 ? _queue.Dequeue () : null;
|
return _queue.Count > 0 ? _queue.Dequeue () : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close ()
|
public void Close ()
|
||||||
{
|
{
|
||||||
_enabled = false;
|
_enabled = false;
|
||||||
_exited.WaitOne ();
|
_exited.WaitOne ();
|
||||||
_exited.Close ();
|
_exited.Close ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Notify (NotificationMessage message)
|
public void Notify (NotificationMessage message)
|
||||||
{
|
{
|
||||||
lock (_sync) {
|
lock (_sync) {
|
||||||
if (_enabled)
|
if (_enabled)
|
||||||
_queue.Enqueue (message);
|
_queue.Enqueue (message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDisposable.Dispose ()
|
void IDisposable.Dispose ()
|
||||||
{
|
{
|
||||||
Close ();
|
Close ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,37 +1,37 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Example1
|
namespace Example1
|
||||||
{
|
{
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
public static void Main (string[] args)
|
public static void Main (string[] args)
|
||||||
{
|
{
|
||||||
// The AudioStreamer class provides a client (chat) for AudioStreamer
|
// The AudioStreamer class provides a client (chat) for AudioStreamer
|
||||||
// (https://github.com/agektmr/AudioStreamer).
|
// (https://github.com/agektmr/AudioStreamer).
|
||||||
|
|
||||||
using (var streamer = new AudioStreamer ("ws://localhost:3000/socket"))
|
using (var streamer = new AudioStreamer ("ws://localhost:3000/socket"))
|
||||||
{
|
{
|
||||||
string name;
|
string name;
|
||||||
do {
|
do {
|
||||||
Console.Write ("Input your name> ");
|
Console.Write ("Input your name> ");
|
||||||
name = Console.ReadLine ();
|
name = Console.ReadLine ();
|
||||||
}
|
}
|
||||||
while (name.Length == 0);
|
while (name.Length == 0);
|
||||||
|
|
||||||
streamer.Connect (name);
|
streamer.Connect (name);
|
||||||
|
|
||||||
Console.WriteLine ("\nType 'exit' to exit.\n");
|
Console.WriteLine ("\nType 'exit' to exit.\n");
|
||||||
while (true) {
|
while (true) {
|
||||||
Thread.Sleep (1000);
|
Thread.Sleep (1000);
|
||||||
Console.Write ("> ");
|
Console.Write ("> ");
|
||||||
var msg = Console.ReadLine ();
|
var msg = Console.ReadLine ();
|
||||||
if (msg == "exit")
|
if (msg == "exit")
|
||||||
break;
|
break;
|
||||||
|
|
||||||
streamer.Write (msg);
|
streamer.Write (msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,33 +1,33 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Example1
|
namespace Example1
|
||||||
{
|
{
|
||||||
internal class TextMessage
|
internal class TextMessage
|
||||||
{
|
{
|
||||||
[JsonProperty ("user_id")]
|
[JsonProperty ("user_id")]
|
||||||
public uint? UserID {
|
public uint? UserID {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonProperty ("name")]
|
[JsonProperty ("name")]
|
||||||
public string Name {
|
public string Name {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonProperty ("type")]
|
[JsonProperty ("type")]
|
||||||
public string Type {
|
public string Type {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonProperty ("message")]
|
[JsonProperty ("message")]
|
||||||
public string Message {
|
public string Message {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString ()
|
public override string ToString ()
|
||||||
{
|
{
|
||||||
return JsonConvert.SerializeObject (this);
|
return JsonConvert.SerializeObject (this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net35" />
|
||||||
|
</packages>
|
||||||
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<appSettings>
|
<appSettings>
|
||||||
<add key="CertFilePassword" value="password"/>
|
<add key="CertFilePassword" value="password"/>
|
||||||
<add key="ServerCertFile" value="/path/to/cert.pfx"/>
|
<add key="ServerCertFile" value="/path/to/cert.pfx"/>
|
||||||
</appSettings>
|
</appSettings>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@ -1,26 +1,26 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
// Information about this assembly is defined by the following attributes.
|
// Information about this assembly is defined by the following attributes.
|
||||||
// Change them to the values specific to your project.
|
// Change them to the values specific to your project.
|
||||||
|
|
||||||
[assembly: AssemblyTitle("Example2")]
|
[assembly: AssemblyTitle("Example2")]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription("")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("")]
|
||||||
[assembly: AssemblyProduct("")]
|
[assembly: AssemblyProduct("")]
|
||||||
[assembly: AssemblyCopyright("sta.blockhead")]
|
[assembly: AssemblyCopyright("sta.blockhead")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||||
|
|
||||||
[assembly: AssemblyVersion("1.0.*")]
|
[assembly: AssemblyVersion("1.0.*")]
|
||||||
|
|
||||||
// The following attributes are used to specify the signing key for the assembly,
|
// The following attributes are used to specify the signing key for the assembly,
|
||||||
// if desired. See the Mono documentation for more information about signing.
|
// if desired. See the Mono documentation for more information about signing.
|
||||||
|
|
||||||
//[assembly: AssemblyDelaySign(false)]
|
//[assembly: AssemblyDelaySign(false)]
|
||||||
//[assembly: AssemblyKeyFile("")]
|
//[assembly: AssemblyKeyFile("")]
|
||||||
|
|||||||
@ -1,50 +1,50 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using WebSocketSharp;
|
using WebSocketSharp;
|
||||||
using WebSocketSharp.Server;
|
using WebSocketSharp.Server;
|
||||||
|
|
||||||
namespace Example2
|
namespace Example2
|
||||||
{
|
{
|
||||||
public class Chat : WebSocketBehavior
|
public class Chat : WebSocketBehavior
|
||||||
{
|
{
|
||||||
private string _name;
|
private string _name;
|
||||||
private static int _number = 0;
|
private static int _number = 0;
|
||||||
private string _prefix;
|
private string _prefix;
|
||||||
|
|
||||||
public Chat ()
|
public Chat ()
|
||||||
: this (null)
|
: this (null)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public Chat (string prefix)
|
public Chat (string prefix)
|
||||||
{
|
{
|
||||||
_prefix = !prefix.IsNullOrEmpty () ? prefix : "anon#";
|
_prefix = !prefix.IsNullOrEmpty () ? prefix : "anon#";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string getName ()
|
private string getName ()
|
||||||
{
|
{
|
||||||
var name = Context.QueryString["name"];
|
var name = Context.QueryString["name"];
|
||||||
return !name.IsNullOrEmpty () ? name : _prefix + getNumber ();
|
return !name.IsNullOrEmpty () ? name : _prefix + getNumber ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getNumber ()
|
private static int getNumber ()
|
||||||
{
|
{
|
||||||
return Interlocked.Increment (ref _number);
|
return Interlocked.Increment (ref _number);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnClose (CloseEventArgs e)
|
protected override void OnClose (CloseEventArgs e)
|
||||||
{
|
{
|
||||||
Sessions.Broadcast (String.Format ("{0} got logged off...", _name));
|
Sessions.Broadcast (String.Format ("{0} got logged off...", _name));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnMessage (MessageEventArgs e)
|
protected override void OnMessage (MessageEventArgs e)
|
||||||
{
|
{
|
||||||
Sessions.Broadcast (String.Format ("{0}: {1}", _name, e.Data));
|
Sessions.Broadcast (String.Format ("{0}: {1}", _name, e.Data));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnOpen ()
|
protected override void OnOpen ()
|
||||||
{
|
{
|
||||||
_name = getName ();
|
_name = getName ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using WebSocketSharp;
|
using WebSocketSharp;
|
||||||
using WebSocketSharp.Server;
|
using WebSocketSharp.Server;
|
||||||
|
|
||||||
namespace Example2
|
namespace Example2
|
||||||
{
|
{
|
||||||
public class Echo : WebSocketBehavior
|
public class Echo : WebSocketBehavior
|
||||||
{
|
{
|
||||||
protected override void OnMessage (MessageEventArgs e)
|
protected override void OnMessage (MessageEventArgs e)
|
||||||
{
|
{
|
||||||
var name = Context.QueryString["name"];
|
var name = Context.QueryString["name"];
|
||||||
Send (!name.IsNullOrEmpty () ? String.Format ("\"{0}\" to {1}", e.Data, name) : e.Data);
|
Send (!name.IsNullOrEmpty () ? String.Format ("\"{0}\" to {1}", e.Data, name) : e.Data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,70 +1,75 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
<ProductVersion>9.0.21022</ProductVersion>
|
<ProductVersion>9.0.21022</ProductVersion>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
<ProjectGuid>{B81A24C8-25BB-42B2-AF99-1E1EACCE74C7}</ProjectGuid>
|
<ProjectGuid>{B81A24C8-25BB-42B2-AF99-1E1EACCE74C7}</ProjectGuid>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RootNamespace>Example2</RootNamespace>
|
<RootNamespace>Example2</RootNamespace>
|
||||||
<AssemblyName>example2</AssemblyName>
|
<AssemblyName>example2</AssemblyName>
|
||||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Debug</OutputPath>
|
<OutputPath>bin\Debug</OutputPath>
|
||||||
<DefineConstants>DEBUG;</DefineConstants>
|
<DefineConstants>DEBUG;</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Release</OutputPath>
|
<OutputPath>bin\Release</OutputPath>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
||||||
<DefineConstants>DEBUG;</DefineConstants>
|
<DefineConstants>DEBUG;</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
|
||||||
<Reference Include="System.Configuration" />
|
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net35\Newtonsoft.Json.dll</HintPath>
|
||||||
</ItemGroup>
|
<Private>True</Private>
|
||||||
<ItemGroup>
|
</Reference>
|
||||||
<Compile Include="AssemblyInfo.cs" />
|
<Reference Include="System" />
|
||||||
<Compile Include="Program.cs" />
|
<Reference Include="System.Configuration" />
|
||||||
<Compile Include="Echo.cs" />
|
</ItemGroup>
|
||||||
<Compile Include="Chat.cs" />
|
<ItemGroup>
|
||||||
</ItemGroup>
|
<Compile Include="AssemblyInfo.cs" />
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Compile Include="Program.cs" />
|
||||||
<ItemGroup>
|
<Compile Include="Echo.cs" />
|
||||||
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
<Compile Include="Chat.cs" />
|
||||||
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
</ItemGroup>
|
||||||
<Name>websocket-sharp</Name>
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
</ProjectReference>
|
<ItemGroup>
|
||||||
</ItemGroup>
|
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
||||||
<ItemGroup>
|
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
||||||
<None Include="App.config" />
|
<Name>websocket-sharp</Name>
|
||||||
</ItemGroup>
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="App.config" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@ -1,135 +1,135 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Configuration;
|
using System.Configuration;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using WebSocketSharp;
|
using WebSocketSharp;
|
||||||
using WebSocketSharp.Net;
|
using WebSocketSharp.Net;
|
||||||
using WebSocketSharp.Server;
|
using WebSocketSharp.Server;
|
||||||
|
|
||||||
namespace Example2
|
namespace Example2
|
||||||
{
|
{
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
public static void Main (string[] args)
|
public static void Main (string[] args)
|
||||||
{
|
{
|
||||||
// Create a new instance of the WebSocketServer class.
|
// Create a new instance of the WebSocketServer class.
|
||||||
//
|
//
|
||||||
// If you would like to provide the secure connection, you should
|
// If you would like to provide the secure connection, you should
|
||||||
// create a new instance with the 'secure' parameter set to true,
|
// create a new instance with the 'secure' parameter set to true,
|
||||||
// or a wss scheme WebSocket URL.
|
// or a wss scheme WebSocket URL.
|
||||||
|
|
||||||
var wssv = new WebSocketServer (4649);
|
var wssv = new WebSocketServer (4649);
|
||||||
//var wssv = new WebSocketServer (5963, true);
|
//var wssv = new WebSocketServer (5963, true);
|
||||||
|
|
||||||
//var wssv = new WebSocketServer (System.Net.IPAddress.Any, 4649);
|
//var wssv = new WebSocketServer (System.Net.IPAddress.Any, 4649);
|
||||||
//var wssv = new WebSocketServer (System.Net.IPAddress.Any, 5963, true);
|
//var wssv = new WebSocketServer (System.Net.IPAddress.Any, 5963, true);
|
||||||
|
|
||||||
//var wssv = new WebSocketServer (System.Net.IPAddress.IPv6Any, 4649);
|
//var wssv = new WebSocketServer (System.Net.IPAddress.IPv6Any, 4649);
|
||||||
//var wssv = new WebSocketServer (System.Net.IPAddress.IPv6Any, 5963, true);
|
//var wssv = new WebSocketServer (System.Net.IPAddress.IPv6Any, 5963, true);
|
||||||
|
|
||||||
//var wssv = new WebSocketServer ("ws://0.0.0.0:4649");
|
//var wssv = new WebSocketServer ("ws://0.0.0.0:4649");
|
||||||
//var wssv = new WebSocketServer ("wss://0.0.0.0:5963");
|
//var wssv = new WebSocketServer ("wss://0.0.0.0:5963");
|
||||||
|
|
||||||
//var wssv = new WebSocketServer ("ws://[::0]:4649");
|
//var wssv = new WebSocketServer ("ws://[::0]:4649");
|
||||||
//var wssv = new WebSocketServer ("wss://[::0]:5963");
|
//var wssv = new WebSocketServer ("wss://[::0]:5963");
|
||||||
|
|
||||||
//var wssv = new WebSocketServer (System.Net.IPAddress.Loopback, 4649);
|
//var wssv = new WebSocketServer (System.Net.IPAddress.Loopback, 4649);
|
||||||
//var wssv = new WebSocketServer (System.Net.IPAddress.Loopback, 5963, true);
|
//var wssv = new WebSocketServer (System.Net.IPAddress.Loopback, 5963, true);
|
||||||
|
|
||||||
//var wssv = new WebSocketServer (System.Net.IPAddress.IPv6Loopback, 4649);
|
//var wssv = new WebSocketServer (System.Net.IPAddress.IPv6Loopback, 4649);
|
||||||
//var wssv = new WebSocketServer (System.Net.IPAddress.IPv6Loopback, 5963, true);
|
//var wssv = new WebSocketServer (System.Net.IPAddress.IPv6Loopback, 5963, true);
|
||||||
|
|
||||||
//var wssv = new WebSocketServer ("ws://localhost:4649");
|
//var wssv = new WebSocketServer ("ws://localhost:4649");
|
||||||
//var wssv = new WebSocketServer ("wss://localhost:5963");
|
//var wssv = new WebSocketServer ("wss://localhost:5963");
|
||||||
|
|
||||||
//var wssv = new WebSocketServer ("ws://127.0.0.1:4649");
|
//var wssv = new WebSocketServer ("ws://127.0.0.1:4649");
|
||||||
//var wssv = new WebSocketServer ("wss://127.0.0.1:5963");
|
//var wssv = new WebSocketServer ("wss://127.0.0.1:5963");
|
||||||
|
|
||||||
//var wssv = new WebSocketServer ("ws://[::1]:4649");
|
//var wssv = new WebSocketServer ("ws://[::1]:4649");
|
||||||
//var wssv = new WebSocketServer ("wss://[::1]:5963");
|
//var wssv = new WebSocketServer ("wss://[::1]:5963");
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
// To change the logging level.
|
// To change the logging level.
|
||||||
wssv.Log.Level = LogLevel.Trace;
|
wssv.Log.Level = LogLevel.Trace;
|
||||||
|
|
||||||
// To change the wait time for the response to the WebSocket Ping or Close.
|
// To change the wait time for the response to the WebSocket Ping or Close.
|
||||||
//wssv.WaitTime = TimeSpan.FromSeconds (2);
|
//wssv.WaitTime = TimeSpan.FromSeconds (2);
|
||||||
|
|
||||||
// Not to remove the inactive sessions periodically.
|
// Not to remove the inactive sessions periodically.
|
||||||
//wssv.KeepClean = false;
|
//wssv.KeepClean = false;
|
||||||
#endif
|
#endif
|
||||||
// To provide the secure connection.
|
// To provide the secure connection.
|
||||||
/*
|
/*
|
||||||
var cert = ConfigurationManager.AppSettings["ServerCertFile"];
|
var cert = ConfigurationManager.AppSettings["ServerCertFile"];
|
||||||
var passwd = ConfigurationManager.AppSettings["CertFilePassword"];
|
var passwd = ConfigurationManager.AppSettings["CertFilePassword"];
|
||||||
wssv.SslConfiguration.ServerCertificate = new X509Certificate2 (cert, passwd);
|
wssv.SslConfiguration.ServerCertificate = new X509Certificate2 (cert, passwd);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// To provide the HTTP Authentication (Basic/Digest).
|
// To provide the HTTP Authentication (Basic/Digest).
|
||||||
/*
|
/*
|
||||||
wssv.AuthenticationSchemes = AuthenticationSchemes.Basic;
|
wssv.AuthenticationSchemes = AuthenticationSchemes.Basic;
|
||||||
wssv.Realm = "WebSocket Test";
|
wssv.Realm = "WebSocket Test";
|
||||||
wssv.UserCredentialsFinder = id => {
|
wssv.UserCredentialsFinder = id => {
|
||||||
var name = id.Name;
|
var name = id.Name;
|
||||||
|
|
||||||
// Return user name, password, and roles.
|
// Return user name, password, and roles.
|
||||||
return name == "nobita"
|
return name == "nobita"
|
||||||
? new NetworkCredential (name, "password", "gunfighter")
|
? new NetworkCredential (name, "password", "gunfighter")
|
||||||
: null; // If the user credentials aren't found.
|
: null; // If the user credentials aren't found.
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// To resolve to wait for socket in TIME_WAIT state.
|
// To resolve to wait for socket in TIME_WAIT state.
|
||||||
//wssv.ReuseAddress = true;
|
//wssv.ReuseAddress = true;
|
||||||
|
|
||||||
// Add the WebSocket services.
|
// Add the WebSocket services.
|
||||||
wssv.AddWebSocketService<Echo> ("/Echo");
|
wssv.AddWebSocketService<Echo> ("/Echo");
|
||||||
wssv.AddWebSocketService<Chat> ("/Chat");
|
wssv.AddWebSocketService<Chat> ("/Chat");
|
||||||
|
|
||||||
// Add the WebSocket service with initializing.
|
// Add the WebSocket service with initializing.
|
||||||
/*
|
/*
|
||||||
wssv.AddWebSocketService<Chat> (
|
wssv.AddWebSocketService<Chat> (
|
||||||
"/Chat",
|
"/Chat",
|
||||||
() =>
|
() =>
|
||||||
new Chat ("Anon#") {
|
new Chat ("Anon#") {
|
||||||
// To send the Sec-WebSocket-Protocol header that has a subprotocol name.
|
// To send the Sec-WebSocket-Protocol header that has a subprotocol name.
|
||||||
Protocol = "chat",
|
Protocol = "chat",
|
||||||
// To ignore the Sec-WebSocket-Extensions header.
|
// To ignore the Sec-WebSocket-Extensions header.
|
||||||
IgnoreExtensions = true,
|
IgnoreExtensions = true,
|
||||||
// To emit a WebSocket.OnMessage event when receives a ping.
|
// To emit a WebSocket.OnMessage event when receives a ping.
|
||||||
EmitOnPing = true,
|
EmitOnPing = true,
|
||||||
// To validate the Origin header.
|
// To validate the Origin header.
|
||||||
OriginValidator = val => {
|
OriginValidator = val => {
|
||||||
// Check the value of the Origin header, and return true if valid.
|
// Check the value of the Origin header, and return true if valid.
|
||||||
Uri origin;
|
Uri origin;
|
||||||
return !val.IsNullOrEmpty ()
|
return !val.IsNullOrEmpty ()
|
||||||
&& Uri.TryCreate (val, UriKind.Absolute, out origin)
|
&& Uri.TryCreate (val, UriKind.Absolute, out origin)
|
||||||
&& origin.Host == "localhost";
|
&& origin.Host == "localhost";
|
||||||
},
|
},
|
||||||
// To validate the cookies.
|
// To validate the cookies.
|
||||||
CookiesValidator = (req, res) => {
|
CookiesValidator = (req, res) => {
|
||||||
// Check the cookies in 'req', and set the cookies to send to
|
// Check the cookies in 'req', and set the cookies to send to
|
||||||
// the client with 'res' if necessary.
|
// the client with 'res' if necessary.
|
||||||
foreach (Cookie cookie in req) {
|
foreach (Cookie cookie in req) {
|
||||||
cookie.Expired = true;
|
cookie.Expired = true;
|
||||||
res.Add (cookie);
|
res.Add (cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true; // If valid.
|
return true; // If valid.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
wssv.Start ();
|
wssv.Start ();
|
||||||
if (wssv.IsListening) {
|
if (wssv.IsListening) {
|
||||||
Console.WriteLine ("Listening on port {0}, and providing WebSocket services:", wssv.Port);
|
Console.WriteLine ("Listening on port {0}, and providing WebSocket services:", wssv.Port);
|
||||||
foreach (var path in wssv.WebSocketServices.Paths)
|
foreach (var path in wssv.WebSocketServices.Paths)
|
||||||
Console.WriteLine ("- {0}", path);
|
Console.WriteLine ("- {0}", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine ("\nPress Enter key to stop the server...");
|
Console.WriteLine ("\nPress Enter key to stop the server...");
|
||||||
Console.ReadLine ();
|
Console.ReadLine ();
|
||||||
|
|
||||||
wssv.Stop ();
|
wssv.Stop ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net35" />
|
||||||
|
</packages>
|
||||||
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<appSettings>
|
<appSettings>
|
||||||
<add key="CertFilePassword" value="password"/>
|
<add key="CertFilePassword" value="password"/>
|
||||||
<add key="DocumentRootPath" value="../../Public"/>
|
<add key="DocumentRootPath" value="../../Public"/>
|
||||||
<add key="ServerCertFile" value="/path/to/cert.pfx"/>
|
<add key="ServerCertFile" value="/path/to/cert.pfx"/>
|
||||||
</appSettings>
|
</appSettings>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@ -1,26 +1,26 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
// Information about this assembly is defined by the following attributes.
|
// Information about this assembly is defined by the following attributes.
|
||||||
// Change them to the values specific to your project.
|
// Change them to the values specific to your project.
|
||||||
|
|
||||||
[assembly: AssemblyTitle("Example3")]
|
[assembly: AssemblyTitle("Example3")]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription("")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("")]
|
||||||
[assembly: AssemblyProduct("")]
|
[assembly: AssemblyProduct("")]
|
||||||
[assembly: AssemblyCopyright("sta.blockhead")]
|
[assembly: AssemblyCopyright("sta.blockhead")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||||
|
|
||||||
[assembly: AssemblyVersion("1.0.*")]
|
[assembly: AssemblyVersion("1.0.*")]
|
||||||
|
|
||||||
// The following attributes are used to specify the signing key for the assembly,
|
// The following attributes are used to specify the signing key for the assembly,
|
||||||
// if desired. See the Mono documentation for more information about signing.
|
// if desired. See the Mono documentation for more information about signing.
|
||||||
|
|
||||||
//[assembly: AssemblyDelaySign(false)]
|
//[assembly: AssemblyDelaySign(false)]
|
||||||
//[assembly: AssemblyKeyFile("")]
|
//[assembly: AssemblyKeyFile("")]
|
||||||
|
|||||||
@ -1,50 +1,50 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using WebSocketSharp;
|
using WebSocketSharp;
|
||||||
using WebSocketSharp.Server;
|
using WebSocketSharp.Server;
|
||||||
|
|
||||||
namespace Example3
|
namespace Example3
|
||||||
{
|
{
|
||||||
public class Chat : WebSocketBehavior
|
public class Chat : WebSocketBehavior
|
||||||
{
|
{
|
||||||
private string _name;
|
private string _name;
|
||||||
private static int _number = 0;
|
private static int _number = 0;
|
||||||
private string _prefix;
|
private string _prefix;
|
||||||
|
|
||||||
public Chat ()
|
public Chat ()
|
||||||
: this (null)
|
: this (null)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public Chat (string prefix)
|
public Chat (string prefix)
|
||||||
{
|
{
|
||||||
_prefix = !prefix.IsNullOrEmpty () ? prefix : "anon#";
|
_prefix = !prefix.IsNullOrEmpty () ? prefix : "anon#";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string getName ()
|
private string getName ()
|
||||||
{
|
{
|
||||||
var name = Context.QueryString["name"];
|
var name = Context.QueryString["name"];
|
||||||
return !name.IsNullOrEmpty () ? name : _prefix + getNumber ();
|
return !name.IsNullOrEmpty () ? name : _prefix + getNumber ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getNumber ()
|
private static int getNumber ()
|
||||||
{
|
{
|
||||||
return Interlocked.Increment (ref _number);
|
return Interlocked.Increment (ref _number);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnClose (CloseEventArgs e)
|
protected override void OnClose (CloseEventArgs e)
|
||||||
{
|
{
|
||||||
Sessions.Broadcast (String.Format ("{0} got logged off...", _name));
|
Sessions.Broadcast (String.Format ("{0} got logged off...", _name));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnMessage (MessageEventArgs e)
|
protected override void OnMessage (MessageEventArgs e)
|
||||||
{
|
{
|
||||||
Sessions.Broadcast (String.Format ("{0}: {1}", _name, e.Data));
|
Sessions.Broadcast (String.Format ("{0}: {1}", _name, e.Data));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnOpen ()
|
protected override void OnOpen ()
|
||||||
{
|
{
|
||||||
_name = getName ();
|
_name = getName ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using WebSocketSharp;
|
using WebSocketSharp;
|
||||||
using WebSocketSharp.Server;
|
using WebSocketSharp.Server;
|
||||||
|
|
||||||
namespace Example3
|
namespace Example3
|
||||||
{
|
{
|
||||||
public class Echo : WebSocketBehavior
|
public class Echo : WebSocketBehavior
|
||||||
{
|
{
|
||||||
protected override void OnMessage (MessageEventArgs e)
|
protected override void OnMessage (MessageEventArgs e)
|
||||||
{
|
{
|
||||||
var name = Context.QueryString["name"];
|
var name = Context.QueryString["name"];
|
||||||
Send (!name.IsNullOrEmpty () ? String.Format ("\"{0}\" to {1}", e.Data, name) : e.Data);
|
Send (!name.IsNullOrEmpty () ? String.Format ("\"{0}\" to {1}", e.Data, name) : e.Data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,76 +1,81 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
<ProductVersion>9.0.21022</ProductVersion>
|
<ProductVersion>9.0.21022</ProductVersion>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
<ProjectGuid>{C648BA25-77E5-4A40-A97F-D0AA37B9FB26}</ProjectGuid>
|
<ProjectGuid>{C648BA25-77E5-4A40-A97F-D0AA37B9FB26}</ProjectGuid>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RootNamespace>Example3</RootNamespace>
|
<RootNamespace>Example3</RootNamespace>
|
||||||
<AssemblyName>example3</AssemblyName>
|
<AssemblyName>example3</AssemblyName>
|
||||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Debug</OutputPath>
|
<OutputPath>bin\Debug</OutputPath>
|
||||||
<DefineConstants>DEBUG;</DefineConstants>
|
<DefineConstants>DEBUG;</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Release</OutputPath>
|
<OutputPath>bin\Release</OutputPath>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
||||||
<DefineConstants>DEBUG;</DefineConstants>
|
<DefineConstants>DEBUG;</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
|
||||||
<Reference Include="System.Configuration" />
|
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net35\Newtonsoft.Json.dll</HintPath>
|
||||||
</ItemGroup>
|
<Private>True</Private>
|
||||||
<ItemGroup>
|
</Reference>
|
||||||
<Compile Include="AssemblyInfo.cs" />
|
<Reference Include="System" />
|
||||||
<Compile Include="Program.cs" />
|
<Reference Include="System.Configuration" />
|
||||||
<Compile Include="Chat.cs" />
|
</ItemGroup>
|
||||||
<Compile Include="Echo.cs" />
|
<ItemGroup>
|
||||||
</ItemGroup>
|
<Compile Include="AssemblyInfo.cs" />
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Compile Include="Program.cs" />
|
||||||
<ItemGroup>
|
<Compile Include="Chat.cs" />
|
||||||
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
<Compile Include="Echo.cs" />
|
||||||
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
</ItemGroup>
|
||||||
<Name>websocket-sharp</Name>
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
</ProjectReference>
|
<ItemGroup>
|
||||||
</ItemGroup>
|
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
||||||
<ItemGroup>
|
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
||||||
<None Include="App.config" />
|
<Name>websocket-sharp</Name>
|
||||||
<None Include="Public\index.html" />
|
</ProjectReference>
|
||||||
<None Include="Public\Js\echotest.js" />
|
</ItemGroup>
|
||||||
</ItemGroup>
|
<ItemGroup>
|
||||||
<ItemGroup>
|
<None Include="App.config" />
|
||||||
<Folder Include="Public\" />
|
<None Include="packages.config" />
|
||||||
<Folder Include="Public\Js\" />
|
<None Include="Public\index.html" />
|
||||||
</ItemGroup>
|
<None Include="Public\Js\echotest.js" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Public\" />
|
||||||
|
<Folder Include="Public\Js\" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@ -1,167 +1,167 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Configuration;
|
using System.Configuration;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using WebSocketSharp;
|
using WebSocketSharp;
|
||||||
using WebSocketSharp.Net;
|
using WebSocketSharp.Net;
|
||||||
using WebSocketSharp.Server;
|
using WebSocketSharp.Server;
|
||||||
|
|
||||||
namespace Example3
|
namespace Example3
|
||||||
{
|
{
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
public static void Main (string[] args)
|
public static void Main (string[] args)
|
||||||
{
|
{
|
||||||
// Create a new instance of the HttpServer class.
|
// Create a new instance of the HttpServer class.
|
||||||
//
|
//
|
||||||
// If you would like to provide the secure connection, you should
|
// If you would like to provide the secure connection, you should
|
||||||
// create a new instance with the 'secure' parameter set to true,
|
// create a new instance with the 'secure' parameter set to true,
|
||||||
// or an https scheme HTTP URL.
|
// or an https scheme HTTP URL.
|
||||||
|
|
||||||
var httpsv = new HttpServer (4649);
|
var httpsv = new HttpServer (12346);
|
||||||
//var httpsv = new HttpServer (5963, true);
|
//var httpsv = new HttpServer (5963, true);
|
||||||
|
|
||||||
//var httpsv = new HttpServer (System.Net.IPAddress.Any, 4649);
|
//var httpsv = new HttpServer (System.Net.IPAddress.Any, 4649);
|
||||||
//var httpsv = new HttpServer (System.Net.IPAddress.Any, 5963, true);
|
//var httpsv = new HttpServer (System.Net.IPAddress.Any, 5963, true);
|
||||||
|
|
||||||
//var httpsv = new HttpServer (System.Net.IPAddress.IPv6Any, 4649);
|
//var httpsv = new HttpServer (System.Net.IPAddress.IPv6Any, 4649);
|
||||||
//var httpsv = new HttpServer (System.Net.IPAddress.IPv6Any, 5963, true);
|
//var httpsv = new HttpServer (System.Net.IPAddress.IPv6Any, 5963, true);
|
||||||
|
|
||||||
//var httpsv = new HttpServer ("http://0.0.0.0:4649");
|
//var httpsv = new HttpServer ("http://0.0.0.0:4649");
|
||||||
//var httpsv = new HttpServer ("https://0.0.0.0:5963");
|
//var httpsv = new HttpServer ("https://0.0.0.0:5963");
|
||||||
|
|
||||||
//var httpsv = new HttpServer ("http://[::0]:4649");
|
//var httpsv = new HttpServer ("http://[::0]:4649");
|
||||||
//var httpsv = new HttpServer ("https://[::0]:5963");
|
//var httpsv = new HttpServer ("https://[::0]:5963");
|
||||||
|
|
||||||
//var httpsv = new HttpServer (System.Net.IPAddress.Loopback, 4649);
|
//var httpsv = new HttpServer (System.Net.IPAddress.Loopback, 4649);
|
||||||
//var httpsv = new HttpServer (System.Net.IPAddress.Loopback, 5963, true);
|
//var httpsv = new HttpServer (System.Net.IPAddress.Loopback, 5963, true);
|
||||||
|
|
||||||
//var httpsv = new HttpServer (System.Net.IPAddress.IPv6Loopback, 4649);
|
//var httpsv = new HttpServer (System.Net.IPAddress.IPv6Loopback, 4649);
|
||||||
//var httpsv = new HttpServer (System.Net.IPAddress.IPv6Loopback, 5963, true);
|
//var httpsv = new HttpServer (System.Net.IPAddress.IPv6Loopback, 5963, true);
|
||||||
|
|
||||||
//var httpsv = new HttpServer ("http://localhost:4649");
|
//var httpsv = new HttpServer ("http://localhost:4649");
|
||||||
//var httpsv = new HttpServer ("https://localhost:5963");
|
//var httpsv = new HttpServer ("https://localhost:5963");
|
||||||
|
|
||||||
//var httpsv = new HttpServer ("http://127.0.0.1:4649");
|
//var httpsv = new HttpServer ("http://127.0.0.1:4649");
|
||||||
//var httpsv = new HttpServer ("https://127.0.0.1:5963");
|
//var httpsv = new HttpServer ("https://127.0.0.1:5963");
|
||||||
|
|
||||||
//var httpsv = new HttpServer ("http://[::1]:4649");
|
//var httpsv = new HttpServer ("http://[::1]:4649");
|
||||||
//var httpsv = new HttpServer ("https://[::1]:5963");
|
//var httpsv = new HttpServer ("https://[::1]:5963");
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
// To change the logging level.
|
// To change the logging level.
|
||||||
httpsv.Log.Level = LogLevel.Trace;
|
httpsv.Log.Level = LogLevel.Trace;
|
||||||
|
|
||||||
// To change the wait time for the response to the WebSocket Ping or Close.
|
// To change the wait time for the response to the WebSocket Ping or Close.
|
||||||
//httpsv.WaitTime = TimeSpan.FromSeconds (2);
|
//httpsv.WaitTime = TimeSpan.FromSeconds (2);
|
||||||
|
|
||||||
// Not to remove the inactive WebSocket sessions periodically.
|
// Not to remove the inactive WebSocket sessions periodically.
|
||||||
//httpsv.KeepClean = false;
|
//httpsv.KeepClean = false;
|
||||||
#endif
|
#endif
|
||||||
// To provide the secure connection.
|
// To provide the secure connection.
|
||||||
/*
|
/*
|
||||||
var cert = ConfigurationManager.AppSettings["ServerCertFile"];
|
var cert = ConfigurationManager.AppSettings["ServerCertFile"];
|
||||||
var passwd = ConfigurationManager.AppSettings["CertFilePassword"];
|
var passwd = ConfigurationManager.AppSettings["CertFilePassword"];
|
||||||
httpsv.SslConfiguration.ServerCertificate = new X509Certificate2 (cert, passwd);
|
httpsv.SslConfiguration.ServerCertificate = new X509Certificate2 (cert, passwd);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// To provide the HTTP Authentication (Basic/Digest).
|
// To provide the HTTP Authentication (Basic/Digest).
|
||||||
/*
|
/*
|
||||||
httpsv.AuthenticationSchemes = AuthenticationSchemes.Basic;
|
httpsv.AuthenticationSchemes = AuthenticationSchemes.Basic;
|
||||||
httpsv.Realm = "WebSocket Test";
|
httpsv.Realm = "WebSocket Test";
|
||||||
httpsv.UserCredentialsFinder = id => {
|
httpsv.UserCredentialsFinder = id => {
|
||||||
var name = id.Name;
|
var name = id.Name;
|
||||||
|
|
||||||
// Return user name, password, and roles.
|
// Return user name, password, and roles.
|
||||||
return name == "nobita"
|
return name == "nobita"
|
||||||
? new NetworkCredential (name, "password", "gunfighter")
|
? new NetworkCredential (name, "password", "gunfighter")
|
||||||
: null; // If the user credentials aren't found.
|
: null; // If the user credentials aren't found.
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// To resolve to wait for socket in TIME_WAIT state.
|
// To resolve to wait for socket in TIME_WAIT state.
|
||||||
//httpsv.ReuseAddress = true;
|
//httpsv.ReuseAddress = true;
|
||||||
|
|
||||||
// Set the document root path.
|
// Set the document root path.
|
||||||
httpsv.DocumentRootPath = ConfigurationManager.AppSettings["DocumentRootPath"];
|
httpsv.DocumentRootPath = ConfigurationManager.AppSettings["DocumentRootPath"];
|
||||||
|
|
||||||
// Set the HTTP GET request event.
|
// Set the HTTP GET request event.
|
||||||
httpsv.OnGet += (sender, e) => {
|
httpsv.OnGet += (sender, e) => {
|
||||||
var req = e.Request;
|
var req = e.Request;
|
||||||
var res = e.Response;
|
var res = e.Response;
|
||||||
|
|
||||||
var path = req.RawUrl;
|
var path = req.RawUrl;
|
||||||
if (path == "/")
|
if (path == "/")
|
||||||
path += "index.html";
|
path += "index.html";
|
||||||
|
|
||||||
byte[] contents;
|
byte[] contents;
|
||||||
if (!e.TryReadFile (path, out contents)) {
|
if (!e.TryReadFile (path, out contents)) {
|
||||||
res.StatusCode = (int) HttpStatusCode.NotFound;
|
res.StatusCode = (int) HttpStatusCode.NotFound;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.EndsWith (".html")) {
|
if (path.EndsWith (".html")) {
|
||||||
res.ContentType = "text/html";
|
res.ContentType = "text/html";
|
||||||
res.ContentEncoding = Encoding.UTF8;
|
res.ContentEncoding = Encoding.UTF8;
|
||||||
}
|
}
|
||||||
else if (path.EndsWith (".js")) {
|
else if (path.EndsWith (".js")) {
|
||||||
res.ContentType = "application/javascript";
|
res.ContentType = "application/javascript";
|
||||||
res.ContentEncoding = Encoding.UTF8;
|
res.ContentEncoding = Encoding.UTF8;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.ContentLength64 = contents.LongLength;
|
res.ContentLength64 = contents.LongLength;
|
||||||
res.Close (contents, true);
|
res.Close (contents, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add the WebSocket services.
|
// Add the WebSocket services.
|
||||||
httpsv.AddWebSocketService<Echo> ("/Echo");
|
httpsv.AddWebSocketService<Echo> ("/Echo");
|
||||||
httpsv.AddWebSocketService<Chat> ("/Chat");
|
httpsv.AddWebSocketService<Chat> ("/Chat");
|
||||||
|
|
||||||
// Add the WebSocket service with initializing.
|
// Add the WebSocket service with initializing.
|
||||||
/*
|
/*
|
||||||
httpsv.AddWebSocketService<Chat> (
|
httpsv.AddWebSocketService<Chat> (
|
||||||
"/Chat",
|
"/Chat",
|
||||||
() =>
|
() =>
|
||||||
new Chat ("Anon#") {
|
new Chat ("Anon#") {
|
||||||
// To send the Sec-WebSocket-Protocol header that has a subprotocol name.
|
// To send the Sec-WebSocket-Protocol header that has a subprotocol name.
|
||||||
Protocol = "chat",
|
Protocol = "chat",
|
||||||
// To ignore the Sec-WebSocket-Extensions header.
|
// To ignore the Sec-WebSocket-Extensions header.
|
||||||
IgnoreExtensions = true,
|
IgnoreExtensions = true,
|
||||||
// To emit a WebSocket.OnMessage event when receives a ping.
|
// To emit a WebSocket.OnMessage event when receives a ping.
|
||||||
EmitOnPing = true,
|
EmitOnPing = true,
|
||||||
// To validate the Origin header.
|
// To validate the Origin header.
|
||||||
OriginValidator = val => {
|
OriginValidator = val => {
|
||||||
// Check the value of the Origin header, and return true if valid.
|
// Check the value of the Origin header, and return true if valid.
|
||||||
Uri origin;
|
Uri origin;
|
||||||
return !val.IsNullOrEmpty ()
|
return !val.IsNullOrEmpty ()
|
||||||
&& Uri.TryCreate (val, UriKind.Absolute, out origin)
|
&& Uri.TryCreate (val, UriKind.Absolute, out origin)
|
||||||
&& origin.Host == "localhost";
|
&& origin.Host == "localhost";
|
||||||
},
|
},
|
||||||
// To validate the cookies.
|
// To validate the cookies.
|
||||||
CookiesValidator = (req, res) => {
|
CookiesValidator = (req, res) => {
|
||||||
// Check the cookies in 'req', and set the cookies to send to
|
// Check the cookies in 'req', and set the cookies to send to
|
||||||
// the client with 'res' if necessary.
|
// the client with 'res' if necessary.
|
||||||
foreach (Cookie cookie in req) {
|
foreach (Cookie cookie in req) {
|
||||||
cookie.Expired = true;
|
cookie.Expired = true;
|
||||||
res.Add (cookie);
|
res.Add (cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true; // If valid.
|
return true; // If valid.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
httpsv.Start ();
|
httpsv.Start ();
|
||||||
if (httpsv.IsListening) {
|
if (httpsv.IsListening) {
|
||||||
Console.WriteLine ("Listening on port {0}, and providing WebSocket services:", httpsv.Port);
|
Console.WriteLine ("Listening on port {0}, and providing WebSocket services:", httpsv.Port);
|
||||||
foreach (var path in httpsv.WebSocketServices.Paths)
|
foreach (var path in httpsv.WebSocketServices.Paths)
|
||||||
Console.WriteLine ("- {0}", path);
|
Console.WriteLine ("- {0}", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine ("\nPress Enter key to stop the server...");
|
Console.WriteLine ("\nPress Enter key to stop the server...");
|
||||||
Console.ReadLine ();
|
Console.ReadLine ();
|
||||||
|
|
||||||
httpsv.Stop ();
|
httpsv.Stop ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,68 +1,68 @@
|
|||||||
/*
|
/*
|
||||||
* echotest.js
|
* echotest.js
|
||||||
*
|
*
|
||||||
* Derived from Echo Test of WebSocket.org (http://www.websocket.org/echo.html).
|
* Derived from Echo Test of WebSocket.org (http://www.websocket.org/echo.html).
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012 Kaazing Corporation.
|
* Copyright (c) 2012 Kaazing Corporation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var url = "ws://localhost:4649/Echo";
|
var url = "ws://localhost:4649/Echo";
|
||||||
//var url = "wss://localhost:5963/Echo";
|
//var url = "wss://localhost:5963/Echo";
|
||||||
var output;
|
var output;
|
||||||
|
|
||||||
function init () {
|
function init () {
|
||||||
output = document.getElementById ("output");
|
output = document.getElementById ("output");
|
||||||
doWebSocket ();
|
doWebSocket ();
|
||||||
}
|
}
|
||||||
|
|
||||||
function doWebSocket () {
|
function doWebSocket () {
|
||||||
websocket = new WebSocket (url);
|
websocket = new WebSocket (url);
|
||||||
|
|
||||||
websocket.onopen = function (e) {
|
websocket.onopen = function (e) {
|
||||||
onOpen (e);
|
onOpen (e);
|
||||||
};
|
};
|
||||||
|
|
||||||
websocket.onmessage = function (e) {
|
websocket.onmessage = function (e) {
|
||||||
onMessage (e);
|
onMessage (e);
|
||||||
};
|
};
|
||||||
|
|
||||||
websocket.onerror = function (e) {
|
websocket.onerror = function (e) {
|
||||||
onError (e);
|
onError (e);
|
||||||
};
|
};
|
||||||
|
|
||||||
websocket.onclose = function (e) {
|
websocket.onclose = function (e) {
|
||||||
onClose (e);
|
onClose (e);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function onOpen (event) {
|
function onOpen (event) {
|
||||||
writeToScreen ("CONNECTED");
|
writeToScreen ("CONNECTED");
|
||||||
send ("WebSocket rocks");
|
send ("WebSocket rocks");
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMessage (event) {
|
function onMessage (event) {
|
||||||
writeToScreen ('<span style="color: blue;">RESPONSE: ' + event.data + '</span>');
|
writeToScreen ('<span style="color: blue;">RESPONSE: ' + event.data + '</span>');
|
||||||
websocket.close ();
|
websocket.close ();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onError (event) {
|
function onError (event) {
|
||||||
writeToScreen ('<span style="color: red;">ERROR: ' + event.data + '</span>');
|
writeToScreen ('<span style="color: red;">ERROR: ' + event.data + '</span>');
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClose (event) {
|
function onClose (event) {
|
||||||
writeToScreen ("DISCONNECTED");
|
writeToScreen ("DISCONNECTED");
|
||||||
}
|
}
|
||||||
|
|
||||||
function send (message) {
|
function send (message) {
|
||||||
writeToScreen ("SENT: " + message);
|
writeToScreen ("SENT: " + message);
|
||||||
websocket.send (message);
|
websocket.send (message);
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeToScreen (message) {
|
function writeToScreen (message) {
|
||||||
var pre = document.createElement ("p");
|
var pre = document.createElement ("p");
|
||||||
pre.style.wordWrap = "break-word";
|
pre.style.wordWrap = "break-word";
|
||||||
pre.innerHTML = message;
|
pre.innerHTML = message;
|
||||||
output.appendChild (pre);
|
output.appendChild (pre);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener ("load", init, false);
|
window.addEventListener ("load", init, false);
|
||||||
@ -1,12 +1,12 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>WebSocket Echo Test</title>
|
<title>WebSocket Echo Test</title>
|
||||||
<script type="text/javascript" src="/Js/echotest.js">
|
<script type="text/javascript" src="/Js/echotest.js">
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h2>WebSocket Echo Test</h2>
|
<h2>WebSocket Echo Test</h2>
|
||||||
<div id="output"></div>
|
<div id="output"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net35" />
|
||||||
|
</packages>
|
||||||
@ -1,21 +1,21 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2010-2021 sta.blockhead
|
Copyright (c) 2010-2021 sta.blockhead
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in
|
||||||
all copies or substantial portions of the Software.
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
|
|||||||
@ -0,0 +1,8 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<appSettings>
|
||||||
|
<add key="CertFilePassword" value="password"/>
|
||||||
|
<add key="DocumentRootPath" value="../../Public"/>
|
||||||
|
<add key="ServerCertFile" value="/path/to/cert.pfx"/>
|
||||||
|
</appSettings>
|
||||||
|
</configuration>
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* echotest.js
|
||||||
|
*
|
||||||
|
* Derived from Echo Test of WebSocket.org (http://www.websocket.org/echo.html).
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Kaazing Corporation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var url = "ws://localhost:4649/Echo";
|
||||||
|
//var url = "wss://localhost:5963/Echo";
|
||||||
|
var output;
|
||||||
|
|
||||||
|
function init () {
|
||||||
|
output = document.getElementById ("output");
|
||||||
|
doWebSocket ();
|
||||||
|
}
|
||||||
|
|
||||||
|
function doWebSocket () {
|
||||||
|
websocket = new WebSocket (url);
|
||||||
|
|
||||||
|
websocket.onopen = function (e) {
|
||||||
|
onOpen (e);
|
||||||
|
};
|
||||||
|
|
||||||
|
websocket.onmessage = function (e) {
|
||||||
|
onMessage (e);
|
||||||
|
};
|
||||||
|
|
||||||
|
websocket.onerror = function (e) {
|
||||||
|
onError (e);
|
||||||
|
};
|
||||||
|
|
||||||
|
websocket.onclose = function (e) {
|
||||||
|
onClose (e);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function onOpen (event) {
|
||||||
|
writeToScreen ("CONNECTED");
|
||||||
|
send ("WebSocket rocks");
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMessage (event) {
|
||||||
|
writeToScreen ('<span style="color: blue;">RESPONSE: ' + event.data + '</span>');
|
||||||
|
websocket.close ();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onError (event) {
|
||||||
|
writeToScreen ('<span style="color: red;">ERROR: ' + event.data + '</span>');
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClose (event) {
|
||||||
|
writeToScreen ("DISCONNECTED");
|
||||||
|
}
|
||||||
|
|
||||||
|
function send (message) {
|
||||||
|
writeToScreen ("SENT: " + message);
|
||||||
|
websocket.send (message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeToScreen (message) {
|
||||||
|
var pre = document.createElement ("p");
|
||||||
|
pre.style.wordWrap = "break-word";
|
||||||
|
pre.innerHTML = message;
|
||||||
|
output.appendChild (pre);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener ("load", init, false);
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>WebSocket Echo Test</title>
|
||||||
|
<script type="text/javascript" src="/Js/echotest.js">
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>WebSocket Echo Test</h2>
|
||||||
|
<div id="output"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Binary file not shown.
@ -0,0 +1,20 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2007 James Newton-King
|
||||||
|
|
||||||
|
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.
|
||||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 8.7 KiB |
@ -1,26 +1,26 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
// Information about this assembly is defined by the following attributes.
|
// Information about this assembly is defined by the following attributes.
|
||||||
// Change them to the values specific to your project.
|
// Change them to the values specific to your project.
|
||||||
|
|
||||||
[assembly: AssemblyTitle("websocket-sharp")]
|
[assembly: AssemblyTitle("websocket-sharp")]
|
||||||
[assembly: AssemblyDescription("A C# implementation of the WebSocket protocol client and server")]
|
[assembly: AssemblyDescription("A C# implementation of the WebSocket protocol client and server")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("")]
|
||||||
[assembly: AssemblyProduct("websocket-sharp.dll")]
|
[assembly: AssemblyProduct("websocket-sharp.dll")]
|
||||||
[assembly: AssemblyCopyright("sta.blockhead")]
|
[assembly: AssemblyCopyright("sta.blockhead")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||||
|
|
||||||
[assembly: AssemblyVersion("1.0.2.*")]
|
[assembly: AssemblyVersion("1.0.2.*")]
|
||||||
|
|
||||||
// The following attributes are used to specify the signing key for the assembly,
|
// The following attributes are used to specify the signing key for the assembly,
|
||||||
// if desired. See the Mono documentation for more information about signing.
|
// if desired. See the Mono documentation for more information about signing.
|
||||||
|
|
||||||
//[assembly: AssemblyDelaySign(false)]
|
//[assembly: AssemblyDelaySign(false)]
|
||||||
//[assembly: AssemblyKeyFile("")]
|
//[assembly: AssemblyKeyFile("")]
|
||||||
|
|||||||
@ -1,47 +1,47 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* ByteOrder.cs
|
* ByteOrder.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2015 sta.blockhead
|
* Copyright (c) 2012-2015 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the byte order.
|
/// Specifies the byte order.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum ByteOrder
|
public enum ByteOrder
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies Little-endian.
|
/// Specifies Little-endian.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Little,
|
Little,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies Big-endian.
|
/// Specifies Big-endian.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Big
|
Big
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,113 +1,113 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* CloseEventArgs.cs
|
* CloseEventArgs.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2019 sta.blockhead
|
* Copyright (c) 2012-2019 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the event data for the <see cref="WebSocket.OnClose"/> event.
|
/// Represents the event data for the <see cref="WebSocket.OnClose"/> event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// That event occurs when the WebSocket connection has been closed.
|
/// That event occurs when the WebSocket connection has been closed.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// If you would like to get the reason for the connection close, you should
|
/// If you would like to get the reason for the connection close, you should
|
||||||
/// access the <see cref="Code"/> or <see cref="Reason"/> property.
|
/// access the <see cref="Code"/> or <see cref="Reason"/> property.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class CloseEventArgs : EventArgs
|
public class CloseEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private bool _clean;
|
private bool _clean;
|
||||||
private PayloadData _payloadData;
|
private PayloadData _payloadData;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Constructors
|
#region Internal Constructors
|
||||||
|
|
||||||
internal CloseEventArgs (PayloadData payloadData, bool clean)
|
internal CloseEventArgs (PayloadData payloadData, bool clean)
|
||||||
{
|
{
|
||||||
_payloadData = payloadData;
|
_payloadData = payloadData;
|
||||||
_clean = clean;
|
_clean = clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal CloseEventArgs (ushort code, string reason, bool clean)
|
internal CloseEventArgs (ushort code, string reason, bool clean)
|
||||||
{
|
{
|
||||||
_payloadData = new PayloadData (code, reason);
|
_payloadData = new PayloadData (code, reason);
|
||||||
_clean = clean;
|
_clean = clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the status code for the connection close.
|
/// Gets the status code for the connection close.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// A <see cref="ushort"/> that represents the status code for
|
/// A <see cref="ushort"/> that represents the status code for
|
||||||
/// the connection close if present.
|
/// the connection close if present.
|
||||||
/// </value>
|
/// </value>
|
||||||
public ushort Code {
|
public ushort Code {
|
||||||
get {
|
get {
|
||||||
return _payloadData.Code;
|
return _payloadData.Code;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the reason for the connection close.
|
/// Gets the reason for the connection close.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// A <see cref="string"/> that represents the reason for
|
/// A <see cref="string"/> that represents the reason for
|
||||||
/// the connection close if present.
|
/// the connection close if present.
|
||||||
/// </value>
|
/// </value>
|
||||||
public string Reason {
|
public string Reason {
|
||||||
get {
|
get {
|
||||||
return _payloadData.Reason;
|
return _payloadData.Reason;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether the connection has been closed cleanly.
|
/// Gets a value indicating whether the connection has been closed cleanly.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// <c>true</c> if the connection has been closed cleanly; otherwise,
|
/// <c>true</c> if the connection has been closed cleanly; otherwise,
|
||||||
/// <c>false</c>.
|
/// <c>false</c>.
|
||||||
/// </value>
|
/// </value>
|
||||||
public bool WasClean {
|
public bool WasClean {
|
||||||
get {
|
get {
|
||||||
return _clean;
|
return _clean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,120 +1,120 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* CloseStatusCode.cs
|
* CloseStatusCode.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2016 sta.blockhead
|
* Copyright (c) 2012-2016 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates the status code for the WebSocket connection close.
|
/// Indicates the status code for the WebSocket connection close.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// The values of this enumeration are defined in
|
/// The values of this enumeration are defined in
|
||||||
/// <see href="http://tools.ietf.org/html/rfc6455#section-7.4">
|
/// <see href="http://tools.ietf.org/html/rfc6455#section-7.4">
|
||||||
/// Section 7.4</see> of RFC 6455.
|
/// Section 7.4</see> of RFC 6455.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// "Reserved value" cannot be sent as a status code in
|
/// "Reserved value" cannot be sent as a status code in
|
||||||
/// closing handshake by an endpoint.
|
/// closing handshake by an endpoint.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public enum CloseStatusCode : ushort
|
public enum CloseStatusCode : ushort
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1000. Indicates normal close.
|
/// Equivalent to close status 1000. Indicates normal close.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Normal = 1000,
|
Normal = 1000,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1001. Indicates that an endpoint is
|
/// Equivalent to close status 1001. Indicates that an endpoint is
|
||||||
/// going away.
|
/// going away.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Away = 1001,
|
Away = 1001,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1002. Indicates that an endpoint is
|
/// Equivalent to close status 1002. Indicates that an endpoint is
|
||||||
/// terminating the connection due to a protocol error.
|
/// terminating the connection due to a protocol error.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ProtocolError = 1002,
|
ProtocolError = 1002,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1003. Indicates that an endpoint is
|
/// Equivalent to close status 1003. Indicates that an endpoint is
|
||||||
/// terminating the connection because it has received a type of
|
/// terminating the connection because it has received a type of
|
||||||
/// data that it cannot accept.
|
/// data that it cannot accept.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
UnsupportedData = 1003,
|
UnsupportedData = 1003,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1004. Still undefined. A Reserved value.
|
/// Equivalent to close status 1004. Still undefined. A Reserved value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Undefined = 1004,
|
Undefined = 1004,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1005. Indicates that no status code was
|
/// Equivalent to close status 1005. Indicates that no status code was
|
||||||
/// actually present. A Reserved value.
|
/// actually present. A Reserved value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
NoStatus = 1005,
|
NoStatus = 1005,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1006. Indicates that the connection was
|
/// Equivalent to close status 1006. Indicates that the connection was
|
||||||
/// closed abnormally. A Reserved value.
|
/// closed abnormally. A Reserved value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Abnormal = 1006,
|
Abnormal = 1006,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1007. Indicates that an endpoint is
|
/// Equivalent to close status 1007. Indicates that an endpoint is
|
||||||
/// terminating the connection because it has received a message that
|
/// terminating the connection because it has received a message that
|
||||||
/// contains data that is not consistent with the type of the message.
|
/// contains data that is not consistent with the type of the message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
InvalidData = 1007,
|
InvalidData = 1007,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1008. Indicates that an endpoint is
|
/// Equivalent to close status 1008. Indicates that an endpoint is
|
||||||
/// terminating the connection because it has received a message that
|
/// terminating the connection because it has received a message that
|
||||||
/// violates its policy.
|
/// violates its policy.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
PolicyViolation = 1008,
|
PolicyViolation = 1008,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1009. Indicates that an endpoint is
|
/// Equivalent to close status 1009. Indicates that an endpoint is
|
||||||
/// terminating the connection because it has received a message that
|
/// terminating the connection because it has received a message that
|
||||||
/// is too big to process.
|
/// is too big to process.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
TooBig = 1009,
|
TooBig = 1009,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1010. Indicates that a client is
|
/// Equivalent to close status 1010. Indicates that a client is
|
||||||
/// terminating the connection because it has expected the server to
|
/// terminating the connection because it has expected the server to
|
||||||
/// negotiate one or more extension, but the server did not return
|
/// negotiate one or more extension, but the server did not return
|
||||||
/// them in the handshake response.
|
/// them in the handshake response.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
MandatoryExtension = 1010,
|
MandatoryExtension = 1010,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1011. Indicates that a server is
|
/// Equivalent to close status 1011. Indicates that a server is
|
||||||
/// terminating the connection because it has encountered an unexpected
|
/// terminating the connection because it has encountered an unexpected
|
||||||
/// condition that prevented it from fulfilling the request.
|
/// condition that prevented it from fulfilling the request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ServerError = 1011,
|
ServerError = 1011,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1015. Indicates that the connection was
|
/// Equivalent to close status 1015. Indicates that the connection was
|
||||||
/// closed due to a failure to perform a TLS handshake. A Reserved value.
|
/// closed due to a failure to perform a TLS handshake. A Reserved value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
TlsHandshakeFailure = 1015
|
TlsHandshakeFailure = 1015
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,52 +1,52 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* CompressionMethod.cs
|
* CompressionMethod.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2013-2017 sta.blockhead
|
* Copyright (c) 2013-2017 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the method for compression.
|
/// Specifies the method for compression.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The methods are defined in
|
/// The methods are defined in
|
||||||
/// <see href="https://tools.ietf.org/html/rfc7692">
|
/// <see href="https://tools.ietf.org/html/rfc7692">
|
||||||
/// Compression Extensions for WebSocket</see>.
|
/// Compression Extensions for WebSocket</see>.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public enum CompressionMethod : byte
|
public enum CompressionMethod : byte
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies no compression.
|
/// Specifies no compression.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
None,
|
None,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies DEFLATE.
|
/// Specifies DEFLATE.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Deflate
|
Deflate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,109 +1,109 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* ErrorEventArgs.cs
|
* ErrorEventArgs.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2016 sta.blockhead
|
* Copyright (c) 2012-2016 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Contributors
|
#region Contributors
|
||||||
/*
|
/*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* - Frank Razenberg <frank@zzattack.org>
|
* - Frank Razenberg <frank@zzattack.org>
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the event data for the <see cref="WebSocket.OnError"/> event.
|
/// Represents the event data for the <see cref="WebSocket.OnError"/> event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// That event occurs when the <see cref="WebSocket"/> gets an error.
|
/// That event occurs when the <see cref="WebSocket"/> gets an error.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// If you would like to get the error message, you should access
|
/// If you would like to get the error message, you should access
|
||||||
/// the <see cref="ErrorEventArgs.Message"/> property.
|
/// the <see cref="ErrorEventArgs.Message"/> property.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// And if the error is due to an exception, you can get it by accessing
|
/// And if the error is due to an exception, you can get it by accessing
|
||||||
/// the <see cref="ErrorEventArgs.Exception"/> property.
|
/// the <see cref="ErrorEventArgs.Exception"/> property.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class ErrorEventArgs : EventArgs
|
public class ErrorEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private Exception _exception;
|
private Exception _exception;
|
||||||
private string _message;
|
private string _message;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Constructors
|
#region Internal Constructors
|
||||||
|
|
||||||
internal ErrorEventArgs (string message)
|
internal ErrorEventArgs (string message)
|
||||||
: this (message, null)
|
: this (message, null)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
internal ErrorEventArgs (string message, Exception exception)
|
internal ErrorEventArgs (string message, Exception exception)
|
||||||
{
|
{
|
||||||
_message = message;
|
_message = message;
|
||||||
_exception = exception;
|
_exception = exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the exception that caused the error.
|
/// Gets the exception that caused the error.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// An <see cref="System.Exception"/> instance that represents the cause of
|
/// An <see cref="System.Exception"/> instance that represents the cause of
|
||||||
/// the error if it is due to an exception; otherwise, <see langword="null"/>.
|
/// the error if it is due to an exception; otherwise, <see langword="null"/>.
|
||||||
/// </value>
|
/// </value>
|
||||||
public Exception Exception {
|
public Exception Exception {
|
||||||
get {
|
get {
|
||||||
return _exception;
|
return _exception;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the error message.
|
/// Gets the error message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// A <see cref="string"/> that represents the error message.
|
/// A <see cref="string"/> that represents the error message.
|
||||||
/// </value>
|
/// </value>
|
||||||
public string Message {
|
public string Message {
|
||||||
get {
|
get {
|
||||||
return _message;
|
return _message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,51 +1,51 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* Fin.cs
|
* Fin.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2015 sta.blockhead
|
* Copyright (c) 2012-2015 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates whether a WebSocket frame is the final frame of a message.
|
/// Indicates whether a WebSocket frame is the final frame of a message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The values of this enumeration are defined in
|
/// The values of this enumeration are defined in
|
||||||
/// <see href="http://tools.ietf.org/html/rfc6455#section-5.2">Section 5.2</see> of RFC 6455.
|
/// <see href="http://tools.ietf.org/html/rfc6455#section-5.2">Section 5.2</see> of RFC 6455.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
internal enum Fin : byte
|
internal enum Fin : byte
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to numeric value 0. Indicates more frames of a message follow.
|
/// Equivalent to numeric value 0. Indicates more frames of a message follow.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
More = 0x0,
|
More = 0x0,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to numeric value 1. Indicates the final frame of a message.
|
/// Equivalent to numeric value 1. Indicates the final frame of a message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Final = 0x1
|
Final = 0x1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,208 +1,208 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* HttpBase.cs
|
* HttpBase.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2014 sta.blockhead
|
* Copyright (c) 2012-2014 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using WebSocketSharp.Net;
|
using WebSocketSharp.Net;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
internal abstract class HttpBase
|
internal abstract class HttpBase
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private NameValueCollection _headers;
|
private NameValueCollection _headers;
|
||||||
private const int _headersMaxLength = 8192;
|
private const int _headersMaxLength = 8192;
|
||||||
private Version _version;
|
private Version _version;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Fields
|
#region Internal Fields
|
||||||
|
|
||||||
internal byte[] EntityBodyData;
|
internal byte[] EntityBodyData;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Protected Fields
|
#region Protected Fields
|
||||||
|
|
||||||
protected const string CrLf = "\r\n";
|
protected const string CrLf = "\r\n";
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Protected Constructors
|
#region Protected Constructors
|
||||||
|
|
||||||
protected HttpBase (Version version, NameValueCollection headers)
|
protected HttpBase (Version version, NameValueCollection headers)
|
||||||
{
|
{
|
||||||
_version = version;
|
_version = version;
|
||||||
_headers = headers;
|
_headers = headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
public string EntityBody {
|
public string EntityBody {
|
||||||
get {
|
get {
|
||||||
if (EntityBodyData == null || EntityBodyData.LongLength == 0)
|
if (EntityBodyData == null || EntityBodyData.LongLength == 0)
|
||||||
return String.Empty;
|
return String.Empty;
|
||||||
|
|
||||||
Encoding enc = null;
|
Encoding enc = null;
|
||||||
|
|
||||||
var contentType = _headers["Content-Type"];
|
var contentType = _headers["Content-Type"];
|
||||||
if (contentType != null && contentType.Length > 0)
|
if (contentType != null && contentType.Length > 0)
|
||||||
enc = HttpUtility.GetEncoding (contentType);
|
enc = HttpUtility.GetEncoding (contentType);
|
||||||
|
|
||||||
return (enc ?? Encoding.UTF8).GetString (EntityBodyData);
|
return (enc ?? Encoding.UTF8).GetString (EntityBodyData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public NameValueCollection Headers {
|
public NameValueCollection Headers {
|
||||||
get {
|
get {
|
||||||
return _headers;
|
return _headers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Version ProtocolVersion {
|
public Version ProtocolVersion {
|
||||||
get {
|
get {
|
||||||
return _version;
|
return _version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Methods
|
#region Private Methods
|
||||||
|
|
||||||
private static byte[] readEntityBody (Stream stream, string length)
|
private static byte[] readEntityBody (Stream stream, string length)
|
||||||
{
|
{
|
||||||
long len;
|
long len;
|
||||||
if (!Int64.TryParse (length, out len))
|
if (!Int64.TryParse (length, out len))
|
||||||
throw new ArgumentException ("Cannot be parsed.", "length");
|
throw new ArgumentException ("Cannot be parsed.", "length");
|
||||||
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
throw new ArgumentOutOfRangeException ("length", "Less than zero.");
|
throw new ArgumentOutOfRangeException ("length", "Less than zero.");
|
||||||
|
|
||||||
return len > 1024
|
return len > 1024
|
||||||
? stream.ReadBytes (len, 1024)
|
? stream.ReadBytes (len, 1024)
|
||||||
: len > 0
|
: len > 0
|
||||||
? stream.ReadBytes ((int) len)
|
? stream.ReadBytes ((int) len)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string[] readHeaders (Stream stream, int maxLength)
|
private static string[] readHeaders (Stream stream, int maxLength)
|
||||||
{
|
{
|
||||||
var buff = new List<byte> ();
|
var buff = new List<byte> ();
|
||||||
var cnt = 0;
|
var cnt = 0;
|
||||||
Action<int> add = i => {
|
Action<int> add = i => {
|
||||||
if (i == -1)
|
if (i == -1)
|
||||||
throw new EndOfStreamException ("The header cannot be read from the data source.");
|
throw new EndOfStreamException ("The header cannot be read from the data source.");
|
||||||
|
|
||||||
buff.Add ((byte) i);
|
buff.Add ((byte) i);
|
||||||
cnt++;
|
cnt++;
|
||||||
};
|
};
|
||||||
|
|
||||||
var read = false;
|
var read = false;
|
||||||
while (cnt < maxLength) {
|
while (cnt < maxLength) {
|
||||||
if (stream.ReadByte ().EqualsWith ('\r', add) &&
|
if (stream.ReadByte ().EqualsWith ('\r', add) &&
|
||||||
stream.ReadByte ().EqualsWith ('\n', add) &&
|
stream.ReadByte ().EqualsWith ('\n', add) &&
|
||||||
stream.ReadByte ().EqualsWith ('\r', add) &&
|
stream.ReadByte ().EqualsWith ('\r', add) &&
|
||||||
stream.ReadByte ().EqualsWith ('\n', add)) {
|
stream.ReadByte ().EqualsWith ('\n', add)) {
|
||||||
read = true;
|
read = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!read)
|
if (!read)
|
||||||
throw new WebSocketException ("The length of header part is greater than the max length.");
|
throw new WebSocketException ("The length of header part is greater than the max length.");
|
||||||
|
|
||||||
return Encoding.UTF8.GetString (buff.ToArray ())
|
return Encoding.UTF8.GetString (buff.ToArray ())
|
||||||
.Replace (CrLf + " ", " ")
|
.Replace (CrLf + " ", " ")
|
||||||
.Replace (CrLf + "\t", " ")
|
.Replace (CrLf + "\t", " ")
|
||||||
.Split (new[] { CrLf }, StringSplitOptions.RemoveEmptyEntries);
|
.Split (new[] { CrLf }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Protected Methods
|
#region Protected Methods
|
||||||
|
|
||||||
protected static T Read<T> (Stream stream, Func<string[], T> parser, int millisecondsTimeout)
|
protected static T Read<T> (Stream stream, Func<string[], T> parser, int millisecondsTimeout)
|
||||||
where T : HttpBase
|
where T : HttpBase
|
||||||
{
|
{
|
||||||
var timeout = false;
|
var timeout = false;
|
||||||
var timer = new Timer (
|
var timer = new Timer (
|
||||||
state => {
|
state => {
|
||||||
timeout = true;
|
timeout = true;
|
||||||
stream.Close ();
|
stream.Close ();
|
||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
millisecondsTimeout,
|
millisecondsTimeout,
|
||||||
-1);
|
-1);
|
||||||
|
|
||||||
T http = null;
|
T http = null;
|
||||||
Exception exception = null;
|
Exception exception = null;
|
||||||
try {
|
try {
|
||||||
http = parser (readHeaders (stream, _headersMaxLength));
|
http = parser (readHeaders (stream, _headersMaxLength));
|
||||||
var contentLen = http.Headers["Content-Length"];
|
var contentLen = http.Headers["Content-Length"];
|
||||||
if (contentLen != null && contentLen.Length > 0)
|
if (contentLen != null && contentLen.Length > 0)
|
||||||
http.EntityBodyData = readEntityBody (stream, contentLen);
|
http.EntityBodyData = readEntityBody (stream, contentLen);
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
exception = ex;
|
exception = ex;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
timer.Change (-1, -1);
|
timer.Change (-1, -1);
|
||||||
timer.Dispose ();
|
timer.Dispose ();
|
||||||
}
|
}
|
||||||
|
|
||||||
var msg = timeout
|
var msg = timeout
|
||||||
? "A timeout has occurred while reading an HTTP request/response."
|
? "A timeout has occurred while reading an HTTP request/response."
|
||||||
: exception != null
|
: exception != null
|
||||||
? "An exception has occurred while reading an HTTP request/response."
|
? "An exception has occurred while reading an HTTP request/response."
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (msg != null)
|
if (msg != null)
|
||||||
throw new WebSocketException (msg, exception);
|
throw new WebSocketException (msg, exception);
|
||||||
|
|
||||||
return http;
|
return http;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
public byte[] ToByteArray ()
|
public byte[] ToByteArray ()
|
||||||
{
|
{
|
||||||
return Encoding.UTF8.GetBytes (ToString ());
|
return Encoding.UTF8.GetBytes (ToString ());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,217 +1,217 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* HttpRequest.cs
|
* HttpRequest.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2015 sta.blockhead
|
* Copyright (c) 2012-2015 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Contributors
|
#region Contributors
|
||||||
/*
|
/*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* - David Burhans
|
* - David Burhans
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using WebSocketSharp.Net;
|
using WebSocketSharp.Net;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
internal class HttpRequest : HttpBase
|
internal class HttpRequest : HttpBase
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private CookieCollection _cookies;
|
private CookieCollection _cookies;
|
||||||
private string _method;
|
private string _method;
|
||||||
private string _uri;
|
private string _uri;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Constructors
|
#region Private Constructors
|
||||||
|
|
||||||
private HttpRequest (string method, string uri, Version version, NameValueCollection headers)
|
private HttpRequest (string method, string uri, Version version, NameValueCollection headers)
|
||||||
: base (version, headers)
|
: base (version, headers)
|
||||||
{
|
{
|
||||||
_method = method;
|
_method = method;
|
||||||
_uri = uri;
|
_uri = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Constructors
|
#region Internal Constructors
|
||||||
|
|
||||||
internal HttpRequest (string method, string uri)
|
internal HttpRequest (string method, string uri)
|
||||||
: this (method, uri, HttpVersion.Version11, new NameValueCollection ())
|
: this (method, uri, HttpVersion.Version11, new NameValueCollection ())
|
||||||
{
|
{
|
||||||
Headers["User-Agent"] = "websocket-sharp/1.0";
|
Headers["User-Agent"] = "websocket-sharp/1.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
public AuthenticationResponse AuthenticationResponse {
|
public AuthenticationResponse AuthenticationResponse {
|
||||||
get {
|
get {
|
||||||
var res = Headers["Authorization"];
|
var res = Headers["Authorization"];
|
||||||
return res != null && res.Length > 0
|
return res != null && res.Length > 0
|
||||||
? AuthenticationResponse.Parse (res)
|
? AuthenticationResponse.Parse (res)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CookieCollection Cookies {
|
public CookieCollection Cookies {
|
||||||
get {
|
get {
|
||||||
if (_cookies == null)
|
if (_cookies == null)
|
||||||
_cookies = Headers.GetCookies (false);
|
_cookies = Headers.GetCookies (false);
|
||||||
|
|
||||||
return _cookies;
|
return _cookies;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string HttpMethod {
|
public string HttpMethod {
|
||||||
get {
|
get {
|
||||||
return _method;
|
return _method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsWebSocketRequest {
|
public bool IsWebSocketRequest {
|
||||||
get {
|
get {
|
||||||
return _method == "GET"
|
return _method == "GET"
|
||||||
&& ProtocolVersion > HttpVersion.Version10
|
&& ProtocolVersion > HttpVersion.Version10
|
||||||
&& Headers.Upgrades ("websocket");
|
&& Headers.Upgrades ("websocket");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string RequestUri {
|
public string RequestUri {
|
||||||
get {
|
get {
|
||||||
return _uri;
|
return _uri;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Methods
|
#region Internal Methods
|
||||||
|
|
||||||
internal static HttpRequest CreateConnectRequest (Uri uri)
|
internal static HttpRequest CreateConnectRequest (Uri uri)
|
||||||
{
|
{
|
||||||
var host = uri.DnsSafeHost;
|
var host = uri.DnsSafeHost;
|
||||||
var port = uri.Port;
|
var port = uri.Port;
|
||||||
var authority = String.Format ("{0}:{1}", host, port);
|
var authority = String.Format ("{0}:{1}", host, port);
|
||||||
var req = new HttpRequest ("CONNECT", authority);
|
var req = new HttpRequest ("CONNECT", authority);
|
||||||
req.Headers["Host"] = port == 80 ? host : authority;
|
req.Headers["Host"] = port == 80 ? host : authority;
|
||||||
|
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static HttpRequest CreateWebSocketRequest (Uri uri)
|
internal static HttpRequest CreateWebSocketRequest (Uri uri)
|
||||||
{
|
{
|
||||||
var req = new HttpRequest ("GET", uri.PathAndQuery);
|
var req = new HttpRequest ("GET", uri.PathAndQuery);
|
||||||
var headers = req.Headers;
|
var headers = req.Headers;
|
||||||
|
|
||||||
// Only includes a port number in the Host header value if it's non-default.
|
// Only includes a port number in the Host header value if it's non-default.
|
||||||
// See: https://tools.ietf.org/html/rfc6455#page-17
|
// See: https://tools.ietf.org/html/rfc6455#page-17
|
||||||
var port = uri.Port;
|
var port = uri.Port;
|
||||||
var schm = uri.Scheme;
|
var schm = uri.Scheme;
|
||||||
headers["Host"] = (port == 80 && schm == "ws") || (port == 443 && schm == "wss")
|
headers["Host"] = (port == 80 && schm == "ws") || (port == 443 && schm == "wss")
|
||||||
? uri.DnsSafeHost
|
? uri.DnsSafeHost
|
||||||
: uri.Authority;
|
: uri.Authority;
|
||||||
|
|
||||||
headers["Upgrade"] = "websocket";
|
headers["Upgrade"] = "websocket";
|
||||||
headers["Connection"] = "Upgrade";
|
headers["Connection"] = "Upgrade";
|
||||||
|
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal HttpResponse GetResponse (Stream stream, int millisecondsTimeout)
|
internal HttpResponse GetResponse (Stream stream, int millisecondsTimeout)
|
||||||
{
|
{
|
||||||
var buff = ToByteArray ();
|
var buff = ToByteArray ();
|
||||||
stream.Write (buff, 0, buff.Length);
|
stream.Write (buff, 0, buff.Length);
|
||||||
|
|
||||||
return Read<HttpResponse> (stream, HttpResponse.Parse, millisecondsTimeout);
|
return Read<HttpResponse> (stream, HttpResponse.Parse, millisecondsTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static HttpRequest Parse (string[] headerParts)
|
internal static HttpRequest Parse (string[] headerParts)
|
||||||
{
|
{
|
||||||
var requestLine = headerParts[0].Split (new[] { ' ' }, 3);
|
var requestLine = headerParts[0].Split (new[] { ' ' }, 3);
|
||||||
if (requestLine.Length != 3)
|
if (requestLine.Length != 3)
|
||||||
throw new ArgumentException ("Invalid request line: " + headerParts[0]);
|
throw new ArgumentException ("Invalid request line: " + headerParts[0]);
|
||||||
|
|
||||||
var headers = new WebHeaderCollection ();
|
var headers = new WebHeaderCollection ();
|
||||||
for (int i = 1; i < headerParts.Length; i++)
|
for (int i = 1; i < headerParts.Length; i++)
|
||||||
headers.InternalSet (headerParts[i], false);
|
headers.InternalSet (headerParts[i], false);
|
||||||
|
|
||||||
return new HttpRequest (
|
return new HttpRequest (
|
||||||
requestLine[0], requestLine[1], new Version (requestLine[2].Substring (5)), headers);
|
requestLine[0], requestLine[1], new Version (requestLine[2].Substring (5)), headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static HttpRequest Read (Stream stream, int millisecondsTimeout)
|
internal static HttpRequest Read (Stream stream, int millisecondsTimeout)
|
||||||
{
|
{
|
||||||
return Read<HttpRequest> (stream, Parse, millisecondsTimeout);
|
return Read<HttpRequest> (stream, Parse, millisecondsTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
public void SetCookies (CookieCollection cookies)
|
public void SetCookies (CookieCollection cookies)
|
||||||
{
|
{
|
||||||
if (cookies == null || cookies.Count == 0)
|
if (cookies == null || cookies.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var buff = new StringBuilder (64);
|
var buff = new StringBuilder (64);
|
||||||
foreach (var cookie in cookies.Sorted)
|
foreach (var cookie in cookies.Sorted)
|
||||||
if (!cookie.Expired)
|
if (!cookie.Expired)
|
||||||
buff.AppendFormat ("{0}; ", cookie.ToString ());
|
buff.AppendFormat ("{0}; ", cookie.ToString ());
|
||||||
|
|
||||||
var len = buff.Length;
|
var len = buff.Length;
|
||||||
if (len > 2) {
|
if (len > 2) {
|
||||||
buff.Length = len - 2;
|
buff.Length = len - 2;
|
||||||
Headers["Cookie"] = buff.ToString ();
|
Headers["Cookie"] = buff.ToString ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString ()
|
public override string ToString ()
|
||||||
{
|
{
|
||||||
var output = new StringBuilder (64);
|
var output = new StringBuilder (64);
|
||||||
output.AppendFormat ("{0} {1} HTTP/{2}{3}", _method, _uri, ProtocolVersion, CrLf);
|
output.AppendFormat ("{0} {1} HTTP/{2}{3}", _method, _uri, ProtocolVersion, CrLf);
|
||||||
|
|
||||||
var headers = Headers;
|
var headers = Headers;
|
||||||
foreach (var key in headers.AllKeys)
|
foreach (var key in headers.AllKeys)
|
||||||
output.AppendFormat ("{0}: {1}{2}", key, headers[key], CrLf);
|
output.AppendFormat ("{0}: {1}{2}", key, headers[key], CrLf);
|
||||||
|
|
||||||
output.Append (CrLf);
|
output.Append (CrLf);
|
||||||
|
|
||||||
var entity = EntityBody;
|
var entity = EntityBody;
|
||||||
if (entity.Length > 0)
|
if (entity.Length > 0)
|
||||||
output.Append (entity);
|
output.Append (entity);
|
||||||
|
|
||||||
return output.ToString ();
|
return output.ToString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,209 +1,209 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* HttpResponse.cs
|
* HttpResponse.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2014 sta.blockhead
|
* Copyright (c) 2012-2014 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using WebSocketSharp.Net;
|
using WebSocketSharp.Net;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
internal class HttpResponse : HttpBase
|
internal class HttpResponse : HttpBase
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private string _code;
|
private string _code;
|
||||||
private string _reason;
|
private string _reason;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Constructors
|
#region Private Constructors
|
||||||
|
|
||||||
private HttpResponse (string code, string reason, Version version, NameValueCollection headers)
|
private HttpResponse (string code, string reason, Version version, NameValueCollection headers)
|
||||||
: base (version, headers)
|
: base (version, headers)
|
||||||
{
|
{
|
||||||
_code = code;
|
_code = code;
|
||||||
_reason = reason;
|
_reason = reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Constructors
|
#region Internal Constructors
|
||||||
|
|
||||||
internal HttpResponse (HttpStatusCode code)
|
internal HttpResponse (HttpStatusCode code)
|
||||||
: this (code, code.GetDescription ())
|
: this (code, code.GetDescription ())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
internal HttpResponse (HttpStatusCode code, string reason)
|
internal HttpResponse (HttpStatusCode code, string reason)
|
||||||
: this (((int) code).ToString (), reason, HttpVersion.Version11, new NameValueCollection ())
|
: this (((int) code).ToString (), reason, HttpVersion.Version11, new NameValueCollection ())
|
||||||
{
|
{
|
||||||
Headers["Server"] = "websocket-sharp/1.0";
|
Headers["Server"] = "websocket-sharp/1.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
public CookieCollection Cookies {
|
public CookieCollection Cookies {
|
||||||
get {
|
get {
|
||||||
return Headers.GetCookies (true);
|
return Headers.GetCookies (true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasConnectionClose {
|
public bool HasConnectionClose {
|
||||||
get {
|
get {
|
||||||
var comparison = StringComparison.OrdinalIgnoreCase;
|
var comparison = StringComparison.OrdinalIgnoreCase;
|
||||||
return Headers.Contains ("Connection", "close", comparison);
|
return Headers.Contains ("Connection", "close", comparison);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsProxyAuthenticationRequired {
|
public bool IsProxyAuthenticationRequired {
|
||||||
get {
|
get {
|
||||||
return _code == "407";
|
return _code == "407";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsRedirect {
|
public bool IsRedirect {
|
||||||
get {
|
get {
|
||||||
return _code == "301" || _code == "302";
|
return _code == "301" || _code == "302";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsUnauthorized {
|
public bool IsUnauthorized {
|
||||||
get {
|
get {
|
||||||
return _code == "401";
|
return _code == "401";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsWebSocketResponse {
|
public bool IsWebSocketResponse {
|
||||||
get {
|
get {
|
||||||
return ProtocolVersion > HttpVersion.Version10
|
return ProtocolVersion > HttpVersion.Version10
|
||||||
&& _code == "101"
|
&& _code == "101"
|
||||||
&& Headers.Upgrades ("websocket");
|
&& Headers.Upgrades ("websocket");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Reason {
|
public string Reason {
|
||||||
get {
|
get {
|
||||||
return _reason;
|
return _reason;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string StatusCode {
|
public string StatusCode {
|
||||||
get {
|
get {
|
||||||
return _code;
|
return _code;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Methods
|
#region Internal Methods
|
||||||
|
|
||||||
internal static HttpResponse CreateCloseResponse (HttpStatusCode code)
|
internal static HttpResponse CreateCloseResponse (HttpStatusCode code)
|
||||||
{
|
{
|
||||||
var res = new HttpResponse (code);
|
var res = new HttpResponse (code);
|
||||||
res.Headers["Connection"] = "close";
|
res.Headers["Connection"] = "close";
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static HttpResponse CreateUnauthorizedResponse (string challenge)
|
internal static HttpResponse CreateUnauthorizedResponse (string challenge)
|
||||||
{
|
{
|
||||||
var res = new HttpResponse (HttpStatusCode.Unauthorized);
|
var res = new HttpResponse (HttpStatusCode.Unauthorized);
|
||||||
res.Headers["WWW-Authenticate"] = challenge;
|
res.Headers["WWW-Authenticate"] = challenge;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static HttpResponse CreateWebSocketResponse ()
|
internal static HttpResponse CreateWebSocketResponse ()
|
||||||
{
|
{
|
||||||
var res = new HttpResponse (HttpStatusCode.SwitchingProtocols);
|
var res = new HttpResponse (HttpStatusCode.SwitchingProtocols);
|
||||||
|
|
||||||
var headers = res.Headers;
|
var headers = res.Headers;
|
||||||
headers["Upgrade"] = "websocket";
|
headers["Upgrade"] = "websocket";
|
||||||
headers["Connection"] = "Upgrade";
|
headers["Connection"] = "Upgrade";
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static HttpResponse Parse (string[] headerParts)
|
internal static HttpResponse Parse (string[] headerParts)
|
||||||
{
|
{
|
||||||
var statusLine = headerParts[0].Split (new[] { ' ' }, 3);
|
var statusLine = headerParts[0].Split (new[] { ' ' }, 3);
|
||||||
if (statusLine.Length != 3)
|
if (statusLine.Length != 3)
|
||||||
throw new ArgumentException ("Invalid status line: " + headerParts[0]);
|
throw new ArgumentException ("Invalid status line: " + headerParts[0]);
|
||||||
|
|
||||||
var headers = new WebHeaderCollection ();
|
var headers = new WebHeaderCollection ();
|
||||||
for (int i = 1; i < headerParts.Length; i++)
|
for (int i = 1; i < headerParts.Length; i++)
|
||||||
headers.InternalSet (headerParts[i], true);
|
headers.InternalSet (headerParts[i], true);
|
||||||
|
|
||||||
return new HttpResponse (
|
return new HttpResponse (
|
||||||
statusLine[1], statusLine[2], new Version (statusLine[0].Substring (5)), headers);
|
statusLine[1], statusLine[2], new Version (statusLine[0].Substring (5)), headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static HttpResponse Read (Stream stream, int millisecondsTimeout)
|
internal static HttpResponse Read (Stream stream, int millisecondsTimeout)
|
||||||
{
|
{
|
||||||
return Read<HttpResponse> (stream, Parse, millisecondsTimeout);
|
return Read<HttpResponse> (stream, Parse, millisecondsTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
public void SetCookies (CookieCollection cookies)
|
public void SetCookies (CookieCollection cookies)
|
||||||
{
|
{
|
||||||
if (cookies == null || cookies.Count == 0)
|
if (cookies == null || cookies.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var headers = Headers;
|
var headers = Headers;
|
||||||
foreach (var cookie in cookies.Sorted)
|
foreach (var cookie in cookies.Sorted)
|
||||||
headers.Add ("Set-Cookie", cookie.ToResponseString ());
|
headers.Add ("Set-Cookie", cookie.ToResponseString ());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString ()
|
public override string ToString ()
|
||||||
{
|
{
|
||||||
var output = new StringBuilder (64);
|
var output = new StringBuilder (64);
|
||||||
output.AppendFormat ("HTTP/{0} {1} {2}{3}", ProtocolVersion, _code, _reason, CrLf);
|
output.AppendFormat ("HTTP/{0} {1} {2}{3}", ProtocolVersion, _code, _reason, CrLf);
|
||||||
|
|
||||||
var headers = Headers;
|
var headers = Headers;
|
||||||
foreach (var key in headers.AllKeys)
|
foreach (var key in headers.AllKeys)
|
||||||
output.AppendFormat ("{0}: {1}{2}", key, headers[key], CrLf);
|
output.AppendFormat ("{0}: {1}{2}", key, headers[key], CrLf);
|
||||||
|
|
||||||
output.Append (CrLf);
|
output.Append (CrLf);
|
||||||
|
|
||||||
var entity = EntityBody;
|
var entity = EntityBody;
|
||||||
if (entity.Length > 0)
|
if (entity.Length > 0)
|
||||||
output.Append (entity);
|
output.Append (entity);
|
||||||
|
|
||||||
return output.ToString ();
|
return output.ToString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,149 +1,149 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* LogData.cs
|
* LogData.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2013-2015 sta.blockhead
|
* Copyright (c) 2013-2015 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a log data used by the <see cref="Logger"/> class.
|
/// Represents a log data used by the <see cref="Logger"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class LogData
|
public class LogData
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private StackFrame _caller;
|
private StackFrame _caller;
|
||||||
private DateTime _date;
|
private DateTime _date;
|
||||||
private LogLevel _level;
|
private LogLevel _level;
|
||||||
private string _message;
|
private string _message;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Constructors
|
#region Internal Constructors
|
||||||
|
|
||||||
internal LogData (LogLevel level, StackFrame caller, string message)
|
internal LogData (LogLevel level, StackFrame caller, string message)
|
||||||
{
|
{
|
||||||
_level = level;
|
_level = level;
|
||||||
_caller = caller;
|
_caller = caller;
|
||||||
_message = message ?? String.Empty;
|
_message = message ?? String.Empty;
|
||||||
_date = DateTime.Now;
|
_date = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the information of the logging method caller.
|
/// Gets the information of the logging method caller.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// A <see cref="StackFrame"/> that provides the information of the logging method caller.
|
/// A <see cref="StackFrame"/> that provides the information of the logging method caller.
|
||||||
/// </value>
|
/// </value>
|
||||||
public StackFrame Caller {
|
public StackFrame Caller {
|
||||||
get {
|
get {
|
||||||
return _caller;
|
return _caller;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the date and time when the log data was created.
|
/// Gets the date and time when the log data was created.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// A <see cref="DateTime"/> that represents the date and time when the log data was created.
|
/// A <see cref="DateTime"/> that represents the date and time when the log data was created.
|
||||||
/// </value>
|
/// </value>
|
||||||
public DateTime Date {
|
public DateTime Date {
|
||||||
get {
|
get {
|
||||||
return _date;
|
return _date;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the logging level of the log data.
|
/// Gets the logging level of the log data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// One of the <see cref="LogLevel"/> enum values, indicates the logging level of the log data.
|
/// One of the <see cref="LogLevel"/> enum values, indicates the logging level of the log data.
|
||||||
/// </value>
|
/// </value>
|
||||||
public LogLevel Level {
|
public LogLevel Level {
|
||||||
get {
|
get {
|
||||||
return _level;
|
return _level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the message of the log data.
|
/// Gets the message of the log data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// A <see cref="string"/> that represents the message of the log data.
|
/// A <see cref="string"/> that represents the message of the log data.
|
||||||
/// </value>
|
/// </value>
|
||||||
public string Message {
|
public string Message {
|
||||||
get {
|
get {
|
||||||
return _message;
|
return _message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a <see cref="string"/> that represents the current <see cref="LogData"/>.
|
/// Returns a <see cref="string"/> that represents the current <see cref="LogData"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// A <see cref="string"/> that represents the current <see cref="LogData"/>.
|
/// A <see cref="string"/> that represents the current <see cref="LogData"/>.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public override string ToString ()
|
public override string ToString ()
|
||||||
{
|
{
|
||||||
var header = String.Format ("{0}|{1,-5}|", _date, _level);
|
var header = String.Format ("{0}|{1,-5}|", _date, _level);
|
||||||
var method = _caller.GetMethod ();
|
var method = _caller.GetMethod ();
|
||||||
var type = method.DeclaringType;
|
var type = method.DeclaringType;
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
var lineNum = _caller.GetFileLineNumber ();
|
var lineNum = _caller.GetFileLineNumber ();
|
||||||
var headerAndCaller =
|
var headerAndCaller =
|
||||||
String.Format ("{0}{1}.{2}:{3}|", header, type.Name, method.Name, lineNum);
|
String.Format ("{0}{1}.{2}:{3}|", header, type.Name, method.Name, lineNum);
|
||||||
#else
|
#else
|
||||||
var headerAndCaller = String.Format ("{0}{1}.{2}|", header, type.Name, method.Name);
|
var headerAndCaller = String.Format ("{0}{1}.{2}|", header, type.Name, method.Name);
|
||||||
#endif
|
#endif
|
||||||
var msgs = _message.Replace ("\r\n", "\n").TrimEnd ('\n').Split ('\n');
|
var msgs = _message.Replace ("\r\n", "\n").TrimEnd ('\n').Split ('\n');
|
||||||
if (msgs.Length <= 1)
|
if (msgs.Length <= 1)
|
||||||
return String.Format ("{0}{1}", headerAndCaller, _message);
|
return String.Format ("{0}{1}", headerAndCaller, _message);
|
||||||
|
|
||||||
var buff = new StringBuilder (String.Format ("{0}{1}\n", headerAndCaller, msgs[0]), 64);
|
var buff = new StringBuilder (String.Format ("{0}{1}\n", headerAndCaller, msgs[0]), 64);
|
||||||
|
|
||||||
var fmt = String.Format ("{{0,{0}}}{{1}}\n", header.Length);
|
var fmt = String.Format ("{{0,{0}}}{{1}}\n", header.Length);
|
||||||
for (var i = 1; i < msgs.Length; i++)
|
for (var i = 1; i < msgs.Length; i++)
|
||||||
buff.AppendFormat (fmt, "", msgs[i]);
|
buff.AppendFormat (fmt, "", msgs[i]);
|
||||||
|
|
||||||
buff.Length--;
|
buff.Length--;
|
||||||
return buff.ToString ();
|
return buff.ToString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,63 +1,63 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* LogLevel.cs
|
* LogLevel.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2013-2015 sta.blockhead
|
* Copyright (c) 2013-2015 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the logging level.
|
/// Specifies the logging level.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum LogLevel
|
public enum LogLevel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the bottom logging level.
|
/// Specifies the bottom logging level.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Trace,
|
Trace,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the 2nd logging level from the bottom.
|
/// Specifies the 2nd logging level from the bottom.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Debug,
|
Debug,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the 3rd logging level from the bottom.
|
/// Specifies the 3rd logging level from the bottom.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Info,
|
Info,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the 3rd logging level from the top.
|
/// Specifies the 3rd logging level from the top.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Warn,
|
Warn,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the 2nd logging level from the top.
|
/// Specifies the 2nd logging level from the top.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Error,
|
Error,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the top logging level.
|
/// Specifies the top logging level.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Fatal
|
Fatal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,330 +1,330 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* Logger.cs
|
* Logger.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2013-2015 sta.blockhead
|
* Copyright (c) 2013-2015 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides a set of methods and properties for logging.
|
/// Provides a set of methods and properties for logging.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// If you output a log with lower than the value of the <see cref="Logger.Level"/> property,
|
/// If you output a log with lower than the value of the <see cref="Logger.Level"/> property,
|
||||||
/// it cannot be outputted.
|
/// it cannot be outputted.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// The default output action writes a log to the standard output stream and the log file
|
/// The default output action writes a log to the standard output stream and the log file
|
||||||
/// if the <see cref="Logger.File"/> property has a valid path to it.
|
/// if the <see cref="Logger.File"/> property has a valid path to it.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// If you would like to use the custom output action, you should set
|
/// If you would like to use the custom output action, you should set
|
||||||
/// the <see cref="Logger.Output"/> property to any <c>Action<LogData, string></c>
|
/// the <see cref="Logger.Output"/> property to any <c>Action<LogData, string></c>
|
||||||
/// delegate.
|
/// delegate.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class Logger
|
public class Logger
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private volatile string _file;
|
private volatile string _file;
|
||||||
private volatile LogLevel _level;
|
private volatile LogLevel _level;
|
||||||
private Action<LogData, string> _output;
|
private Action<LogData, string> _output;
|
||||||
private object _sync;
|
private object _sync;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Constructors
|
#region Public Constructors
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Logger"/> class.
|
/// Initializes a new instance of the <see cref="Logger"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This constructor initializes the current logging level with <see cref="LogLevel.Error"/>.
|
/// This constructor initializes the current logging level with <see cref="LogLevel.Error"/>.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public Logger ()
|
public Logger ()
|
||||||
: this (LogLevel.Error, null, null)
|
: this (LogLevel.Error, null, null)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Logger"/> class with
|
/// Initializes a new instance of the <see cref="Logger"/> class with
|
||||||
/// the specified logging <paramref name="level"/>.
|
/// the specified logging <paramref name="level"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="level">
|
/// <param name="level">
|
||||||
/// One of the <see cref="LogLevel"/> enum values.
|
/// One of the <see cref="LogLevel"/> enum values.
|
||||||
/// </param>
|
/// </param>
|
||||||
public Logger (LogLevel level)
|
public Logger (LogLevel level)
|
||||||
: this (level, null, null)
|
: this (level, null, null)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Logger"/> class with
|
/// Initializes a new instance of the <see cref="Logger"/> class with
|
||||||
/// the specified logging <paramref name="level"/>, path to the log <paramref name="file"/>,
|
/// the specified logging <paramref name="level"/>, path to the log <paramref name="file"/>,
|
||||||
/// and <paramref name="output"/> action.
|
/// and <paramref name="output"/> action.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="level">
|
/// <param name="level">
|
||||||
/// One of the <see cref="LogLevel"/> enum values.
|
/// One of the <see cref="LogLevel"/> enum values.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="file">
|
/// <param name="file">
|
||||||
/// A <see cref="string"/> that represents the path to the log file.
|
/// A <see cref="string"/> that represents the path to the log file.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="output">
|
/// <param name="output">
|
||||||
/// An <c>Action<LogData, string></c> delegate that references the method(s) used to
|
/// An <c>Action<LogData, string></c> delegate that references the method(s) used to
|
||||||
/// output a log. A <see cref="string"/> parameter passed to this delegate is
|
/// output a log. A <see cref="string"/> parameter passed to this delegate is
|
||||||
/// <paramref name="file"/>.
|
/// <paramref name="file"/>.
|
||||||
/// </param>
|
/// </param>
|
||||||
public Logger (LogLevel level, string file, Action<LogData, string> output)
|
public Logger (LogLevel level, string file, Action<LogData, string> output)
|
||||||
{
|
{
|
||||||
_level = level;
|
_level = level;
|
||||||
_file = file;
|
_file = file;
|
||||||
_output = output ?? defaultOutput;
|
_output = output ?? defaultOutput;
|
||||||
_sync = new object ();
|
_sync = new object ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the current path to the log file.
|
/// Gets or sets the current path to the log file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// A <see cref="string"/> that represents the current path to the log file if any.
|
/// A <see cref="string"/> that represents the current path to the log file if any.
|
||||||
/// </value>
|
/// </value>
|
||||||
public string File {
|
public string File {
|
||||||
get {
|
get {
|
||||||
return _file;
|
return _file;
|
||||||
}
|
}
|
||||||
|
|
||||||
set {
|
set {
|
||||||
lock (_sync) {
|
lock (_sync) {
|
||||||
_file = value;
|
_file = value;
|
||||||
Warn (
|
Warn (
|
||||||
String.Format ("The current path to the log file has been changed to {0}.", _file));
|
String.Format ("The current path to the log file has been changed to {0}.", _file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the current logging level.
|
/// Gets or sets the current logging level.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// A log with lower than the value of this property cannot be outputted.
|
/// A log with lower than the value of this property cannot be outputted.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// One of the <see cref="LogLevel"/> enum values, specifies the current logging level.
|
/// One of the <see cref="LogLevel"/> enum values, specifies the current logging level.
|
||||||
/// </value>
|
/// </value>
|
||||||
public LogLevel Level {
|
public LogLevel Level {
|
||||||
get {
|
get {
|
||||||
return _level;
|
return _level;
|
||||||
}
|
}
|
||||||
|
|
||||||
set {
|
set {
|
||||||
lock (_sync) {
|
lock (_sync) {
|
||||||
_level = value;
|
_level = value;
|
||||||
Warn (String.Format ("The current logging level has been changed to {0}.", _level));
|
Warn (String.Format ("The current logging level has been changed to {0}.", _level));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the current output action used to output a log.
|
/// Gets or sets the current output action used to output a log.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// An <c>Action<LogData, string></c> delegate that references the method(s) used to
|
/// An <c>Action<LogData, string></c> delegate that references the method(s) used to
|
||||||
/// output a log. A <see cref="string"/> parameter passed to this delegate is the value of
|
/// output a log. A <see cref="string"/> parameter passed to this delegate is the value of
|
||||||
/// the <see cref="Logger.File"/> property.
|
/// the <see cref="Logger.File"/> property.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// If the value to set is <see langword="null"/>, the current output action is changed to
|
/// If the value to set is <see langword="null"/>, the current output action is changed to
|
||||||
/// the default output action.
|
/// the default output action.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </value>
|
/// </value>
|
||||||
public Action<LogData, string> Output {
|
public Action<LogData, string> Output {
|
||||||
get {
|
get {
|
||||||
return _output;
|
return _output;
|
||||||
}
|
}
|
||||||
|
|
||||||
set {
|
set {
|
||||||
lock (_sync) {
|
lock (_sync) {
|
||||||
_output = value ?? defaultOutput;
|
_output = value ?? defaultOutput;
|
||||||
Warn ("The current output action has been changed.");
|
Warn ("The current output action has been changed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Methods
|
#region Private Methods
|
||||||
|
|
||||||
private static void defaultOutput (LogData data, string path)
|
private static void defaultOutput (LogData data, string path)
|
||||||
{
|
{
|
||||||
var log = data.ToString ();
|
var log = data.ToString ();
|
||||||
Console.WriteLine (log);
|
Console.WriteLine (log);
|
||||||
if (path != null && path.Length > 0)
|
if (path != null && path.Length > 0)
|
||||||
writeToFile (log, path);
|
writeToFile (log, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void output (string message, LogLevel level)
|
private void output (string message, LogLevel level)
|
||||||
{
|
{
|
||||||
lock (_sync) {
|
lock (_sync) {
|
||||||
if (_level > level)
|
if (_level > level)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LogData data = null;
|
LogData data = null;
|
||||||
try {
|
try {
|
||||||
data = new LogData (level, new StackFrame (2, true), message);
|
data = new LogData (level, new StackFrame (2, true), message);
|
||||||
_output (data, _file);
|
_output (data, _file);
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
data = new LogData (LogLevel.Fatal, new StackFrame (0, true), ex.Message);
|
data = new LogData (LogLevel.Fatal, new StackFrame (0, true), ex.Message);
|
||||||
Console.WriteLine (data.ToString ());
|
Console.WriteLine (data.ToString ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void writeToFile (string value, string path)
|
private static void writeToFile (string value, string path)
|
||||||
{
|
{
|
||||||
using (var writer = new StreamWriter (path, true))
|
using (var writer = new StreamWriter (path, true))
|
||||||
using (var syncWriter = TextWriter.Synchronized (writer))
|
using (var syncWriter = TextWriter.Synchronized (writer))
|
||||||
syncWriter.WriteLine (value);
|
syncWriter.WriteLine (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Debug"/>.
|
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Debug"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// If the current logging level is higher than <see cref="LogLevel.Debug"/>,
|
/// If the current logging level is higher than <see cref="LogLevel.Debug"/>,
|
||||||
/// this method doesn't output <paramref name="message"/> as a log.
|
/// this method doesn't output <paramref name="message"/> as a log.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="message">
|
/// <param name="message">
|
||||||
/// A <see cref="string"/> that represents the message to output as a log.
|
/// A <see cref="string"/> that represents the message to output as a log.
|
||||||
/// </param>
|
/// </param>
|
||||||
public void Debug (string message)
|
public void Debug (string message)
|
||||||
{
|
{
|
||||||
if (_level > LogLevel.Debug)
|
if (_level > LogLevel.Debug)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
output (message, LogLevel.Debug);
|
output (message, LogLevel.Debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Error"/>.
|
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Error"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// If the current logging level is higher than <see cref="LogLevel.Error"/>,
|
/// If the current logging level is higher than <see cref="LogLevel.Error"/>,
|
||||||
/// this method doesn't output <paramref name="message"/> as a log.
|
/// this method doesn't output <paramref name="message"/> as a log.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="message">
|
/// <param name="message">
|
||||||
/// A <see cref="string"/> that represents the message to output as a log.
|
/// A <see cref="string"/> that represents the message to output as a log.
|
||||||
/// </param>
|
/// </param>
|
||||||
public void Error (string message)
|
public void Error (string message)
|
||||||
{
|
{
|
||||||
if (_level > LogLevel.Error)
|
if (_level > LogLevel.Error)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
output (message, LogLevel.Error);
|
output (message, LogLevel.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Fatal"/>.
|
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Fatal"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">
|
/// <param name="message">
|
||||||
/// A <see cref="string"/> that represents the message to output as a log.
|
/// A <see cref="string"/> that represents the message to output as a log.
|
||||||
/// </param>
|
/// </param>
|
||||||
public void Fatal (string message)
|
public void Fatal (string message)
|
||||||
{
|
{
|
||||||
output (message, LogLevel.Fatal);
|
output (message, LogLevel.Fatal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Info"/>.
|
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Info"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// If the current logging level is higher than <see cref="LogLevel.Info"/>,
|
/// If the current logging level is higher than <see cref="LogLevel.Info"/>,
|
||||||
/// this method doesn't output <paramref name="message"/> as a log.
|
/// this method doesn't output <paramref name="message"/> as a log.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="message">
|
/// <param name="message">
|
||||||
/// A <see cref="string"/> that represents the message to output as a log.
|
/// A <see cref="string"/> that represents the message to output as a log.
|
||||||
/// </param>
|
/// </param>
|
||||||
public void Info (string message)
|
public void Info (string message)
|
||||||
{
|
{
|
||||||
if (_level > LogLevel.Info)
|
if (_level > LogLevel.Info)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
output (message, LogLevel.Info);
|
output (message, LogLevel.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Trace"/>.
|
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Trace"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// If the current logging level is higher than <see cref="LogLevel.Trace"/>,
|
/// If the current logging level is higher than <see cref="LogLevel.Trace"/>,
|
||||||
/// this method doesn't output <paramref name="message"/> as a log.
|
/// this method doesn't output <paramref name="message"/> as a log.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="message">
|
/// <param name="message">
|
||||||
/// A <see cref="string"/> that represents the message to output as a log.
|
/// A <see cref="string"/> that represents the message to output as a log.
|
||||||
/// </param>
|
/// </param>
|
||||||
public void Trace (string message)
|
public void Trace (string message)
|
||||||
{
|
{
|
||||||
if (_level > LogLevel.Trace)
|
if (_level > LogLevel.Trace)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
output (message, LogLevel.Trace);
|
output (message, LogLevel.Trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Warn"/>.
|
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Warn"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// If the current logging level is higher than <see cref="LogLevel.Warn"/>,
|
/// If the current logging level is higher than <see cref="LogLevel.Warn"/>,
|
||||||
/// this method doesn't output <paramref name="message"/> as a log.
|
/// this method doesn't output <paramref name="message"/> as a log.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="message">
|
/// <param name="message">
|
||||||
/// A <see cref="string"/> that represents the message to output as a log.
|
/// A <see cref="string"/> that represents the message to output as a log.
|
||||||
/// </param>
|
/// </param>
|
||||||
public void Warn (string message)
|
public void Warn (string message)
|
||||||
{
|
{
|
||||||
if (_level > LogLevel.Warn)
|
if (_level > LogLevel.Warn)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
output (message, LogLevel.Warn);
|
output (message, LogLevel.Warn);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,51 +1,51 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* Mask.cs
|
* Mask.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2015 sta.blockhead
|
* Copyright (c) 2012-2015 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates whether the payload data of a WebSocket frame is masked.
|
/// Indicates whether the payload data of a WebSocket frame is masked.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The values of this enumeration are defined in
|
/// The values of this enumeration are defined in
|
||||||
/// <see href="http://tools.ietf.org/html/rfc6455#section-5.2">Section 5.2</see> of RFC 6455.
|
/// <see href="http://tools.ietf.org/html/rfc6455#section-5.2">Section 5.2</see> of RFC 6455.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
internal enum Mask : byte
|
internal enum Mask : byte
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to numeric value 0. Indicates not masked.
|
/// Equivalent to numeric value 0. Indicates not masked.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Off = 0x0,
|
Off = 0x0,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to numeric value 1. Indicates masked.
|
/// Equivalent to numeric value 1. Indicates masked.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
On = 0x1
|
On = 0x1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,183 +1,183 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* MessageEventArgs.cs
|
* MessageEventArgs.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2016 sta.blockhead
|
* Copyright (c) 2012-2016 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the event data for the <see cref="WebSocket.OnMessage"/> event.
|
/// Represents the event data for the <see cref="WebSocket.OnMessage"/> event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// That event occurs when the <see cref="WebSocket"/> receives
|
/// That event occurs when the <see cref="WebSocket"/> receives
|
||||||
/// a message or a ping if the <see cref="WebSocket.EmitOnPing"/>
|
/// a message or a ping if the <see cref="WebSocket.EmitOnPing"/>
|
||||||
/// property is set to <c>true</c>.
|
/// property is set to <c>true</c>.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// If you would like to get the message data, you should access
|
/// If you would like to get the message data, you should access
|
||||||
/// the <see cref="Data"/> or <see cref="RawData"/> property.
|
/// the <see cref="Data"/> or <see cref="RawData"/> property.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class MessageEventArgs : EventArgs
|
public class MessageEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private string _data;
|
private string _data;
|
||||||
private bool _dataSet;
|
private bool _dataSet;
|
||||||
private Opcode _opcode;
|
private Opcode _opcode;
|
||||||
private byte[] _rawData;
|
private byte[] _rawData;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Constructors
|
#region Internal Constructors
|
||||||
|
|
||||||
internal MessageEventArgs (WebSocketFrame frame)
|
internal MessageEventArgs (WebSocketFrame frame)
|
||||||
{
|
{
|
||||||
_opcode = frame.Opcode;
|
_opcode = frame.Opcode;
|
||||||
_rawData = frame.PayloadData.ApplicationData;
|
_rawData = frame.PayloadData.ApplicationData;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal MessageEventArgs (Opcode opcode, byte[] rawData)
|
internal MessageEventArgs (Opcode opcode, byte[] rawData)
|
||||||
{
|
{
|
||||||
if ((ulong) rawData.LongLength > PayloadData.MaxLength)
|
if ((ulong) rawData.LongLength > PayloadData.MaxLength)
|
||||||
throw new WebSocketException (CloseStatusCode.TooBig);
|
throw new WebSocketException (CloseStatusCode.TooBig);
|
||||||
|
|
||||||
_opcode = opcode;
|
_opcode = opcode;
|
||||||
_rawData = rawData;
|
_rawData = rawData;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Properties
|
#region Internal Properties
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the opcode for the message.
|
/// Gets the opcode for the message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// <see cref="Opcode.Text"/>, <see cref="Opcode.Binary"/>,
|
/// <see cref="Opcode.Text"/>, <see cref="Opcode.Binary"/>,
|
||||||
/// or <see cref="Opcode.Ping"/>.
|
/// or <see cref="Opcode.Ping"/>.
|
||||||
/// </value>
|
/// </value>
|
||||||
internal Opcode Opcode {
|
internal Opcode Opcode {
|
||||||
get {
|
get {
|
||||||
return _opcode;
|
return _opcode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the message data as a <see cref="string"/>.
|
/// Gets the message data as a <see cref="string"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// A <see cref="string"/> that represents the message data if its type is
|
/// A <see cref="string"/> that represents the message data if its type is
|
||||||
/// text or ping and if decoding it to a string has successfully done;
|
/// text or ping and if decoding it to a string has successfully done;
|
||||||
/// otherwise, <see langword="null"/>.
|
/// otherwise, <see langword="null"/>.
|
||||||
/// </value>
|
/// </value>
|
||||||
public string Data {
|
public string Data {
|
||||||
get {
|
get {
|
||||||
setData ();
|
setData ();
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether the message type is binary.
|
/// Gets a value indicating whether the message type is binary.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// <c>true</c> if the message type is binary; otherwise, <c>false</c>.
|
/// <c>true</c> if the message type is binary; otherwise, <c>false</c>.
|
||||||
/// </value>
|
/// </value>
|
||||||
public bool IsBinary {
|
public bool IsBinary {
|
||||||
get {
|
get {
|
||||||
return _opcode == Opcode.Binary;
|
return _opcode == Opcode.Binary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether the message type is ping.
|
/// Gets a value indicating whether the message type is ping.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// <c>true</c> if the message type is ping; otherwise, <c>false</c>.
|
/// <c>true</c> if the message type is ping; otherwise, <c>false</c>.
|
||||||
/// </value>
|
/// </value>
|
||||||
public bool IsPing {
|
public bool IsPing {
|
||||||
get {
|
get {
|
||||||
return _opcode == Opcode.Ping;
|
return _opcode == Opcode.Ping;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether the message type is text.
|
/// Gets a value indicating whether the message type is text.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// <c>true</c> if the message type is text; otherwise, <c>false</c>.
|
/// <c>true</c> if the message type is text; otherwise, <c>false</c>.
|
||||||
/// </value>
|
/// </value>
|
||||||
public bool IsText {
|
public bool IsText {
|
||||||
get {
|
get {
|
||||||
return _opcode == Opcode.Text;
|
return _opcode == Opcode.Text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the message data as an array of <see cref="byte"/>.
|
/// Gets the message data as an array of <see cref="byte"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// An array of <see cref="byte"/> that represents the message data.
|
/// An array of <see cref="byte"/> that represents the message data.
|
||||||
/// </value>
|
/// </value>
|
||||||
public byte[] RawData {
|
public byte[] RawData {
|
||||||
get {
|
get {
|
||||||
setData ();
|
setData ();
|
||||||
return _rawData;
|
return _rawData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Methods
|
#region Private Methods
|
||||||
|
|
||||||
private void setData ()
|
private void setData ()
|
||||||
{
|
{
|
||||||
if (_dataSet)
|
if (_dataSet)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_opcode == Opcode.Binary) {
|
if (_opcode == Opcode.Binary) {
|
||||||
_dataSet = true;
|
_dataSet = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string data;
|
string data;
|
||||||
if (_rawData.TryGetUTF8DecodedString (out data))
|
if (_rawData.TryGetUTF8DecodedString (out data))
|
||||||
_data = data;
|
_data = data;
|
||||||
|
|
||||||
_dataSet = true;
|
_dataSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,151 +1,151 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* AuthenticationBase.cs
|
* AuthenticationBase.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2014 sta.blockhead
|
* Copyright (c) 2014 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace WebSocketSharp.Net
|
namespace WebSocketSharp.Net
|
||||||
{
|
{
|
||||||
internal abstract class AuthenticationBase
|
internal abstract class AuthenticationBase
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private AuthenticationSchemes _scheme;
|
private AuthenticationSchemes _scheme;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Fields
|
#region Internal Fields
|
||||||
|
|
||||||
internal NameValueCollection Parameters;
|
internal NameValueCollection Parameters;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Protected Constructors
|
#region Protected Constructors
|
||||||
|
|
||||||
protected AuthenticationBase (AuthenticationSchemes scheme, NameValueCollection parameters)
|
protected AuthenticationBase (AuthenticationSchemes scheme, NameValueCollection parameters)
|
||||||
{
|
{
|
||||||
_scheme = scheme;
|
_scheme = scheme;
|
||||||
Parameters = parameters;
|
Parameters = parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
public string Algorithm {
|
public string Algorithm {
|
||||||
get {
|
get {
|
||||||
return Parameters["algorithm"];
|
return Parameters["algorithm"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Nonce {
|
public string Nonce {
|
||||||
get {
|
get {
|
||||||
return Parameters["nonce"];
|
return Parameters["nonce"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Opaque {
|
public string Opaque {
|
||||||
get {
|
get {
|
||||||
return Parameters["opaque"];
|
return Parameters["opaque"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Qop {
|
public string Qop {
|
||||||
get {
|
get {
|
||||||
return Parameters["qop"];
|
return Parameters["qop"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Realm {
|
public string Realm {
|
||||||
get {
|
get {
|
||||||
return Parameters["realm"];
|
return Parameters["realm"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthenticationSchemes Scheme {
|
public AuthenticationSchemes Scheme {
|
||||||
get {
|
get {
|
||||||
return _scheme;
|
return _scheme;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Methods
|
#region Internal Methods
|
||||||
|
|
||||||
internal static string CreateNonceValue ()
|
internal static string CreateNonceValue ()
|
||||||
{
|
{
|
||||||
var src = new byte[16];
|
var src = new byte[16];
|
||||||
var rand = new Random ();
|
var rand = new Random ();
|
||||||
rand.NextBytes (src);
|
rand.NextBytes (src);
|
||||||
|
|
||||||
var res = new StringBuilder (32);
|
var res = new StringBuilder (32);
|
||||||
foreach (var b in src)
|
foreach (var b in src)
|
||||||
res.Append (b.ToString ("x2"));
|
res.Append (b.ToString ("x2"));
|
||||||
|
|
||||||
return res.ToString ();
|
return res.ToString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static NameValueCollection ParseParameters (string value)
|
internal static NameValueCollection ParseParameters (string value)
|
||||||
{
|
{
|
||||||
var res = new NameValueCollection ();
|
var res = new NameValueCollection ();
|
||||||
foreach (var param in value.SplitHeaderValue (',')) {
|
foreach (var param in value.SplitHeaderValue (',')) {
|
||||||
var i = param.IndexOf ('=');
|
var i = param.IndexOf ('=');
|
||||||
var name = i > 0 ? param.Substring (0, i).Trim () : null;
|
var name = i > 0 ? param.Substring (0, i).Trim () : null;
|
||||||
var val = i < 0
|
var val = i < 0
|
||||||
? param.Trim ().Trim ('"')
|
? param.Trim ().Trim ('"')
|
||||||
: i < param.Length - 1
|
: i < param.Length - 1
|
||||||
? param.Substring (i + 1).Trim ().Trim ('"')
|
? param.Substring (i + 1).Trim ().Trim ('"')
|
||||||
: String.Empty;
|
: String.Empty;
|
||||||
|
|
||||||
res.Add (name, val);
|
res.Add (name, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract string ToBasicString ();
|
internal abstract string ToBasicString ();
|
||||||
|
|
||||||
internal abstract string ToDigestString ();
|
internal abstract string ToDigestString ();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
public override string ToString ()
|
public override string ToString ()
|
||||||
{
|
{
|
||||||
return _scheme == AuthenticationSchemes.Basic
|
return _scheme == AuthenticationSchemes.Basic
|
||||||
? ToBasicString ()
|
? ToBasicString ()
|
||||||
: _scheme == AuthenticationSchemes.Digest
|
: _scheme == AuthenticationSchemes.Digest
|
||||||
? ToDigestString ()
|
? ToDigestString ()
|
||||||
: String.Empty;
|
: String.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,146 +1,146 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* AuthenticationChallenge.cs
|
* AuthenticationChallenge.cs
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2013-2014 sta.blockhead
|
* Copyright (c) 2013-2014 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace WebSocketSharp.Net
|
namespace WebSocketSharp.Net
|
||||||
{
|
{
|
||||||
internal class AuthenticationChallenge : AuthenticationBase
|
internal class AuthenticationChallenge : AuthenticationBase
|
||||||
{
|
{
|
||||||
#region Private Constructors
|
#region Private Constructors
|
||||||
|
|
||||||
private AuthenticationChallenge (AuthenticationSchemes scheme, NameValueCollection parameters)
|
private AuthenticationChallenge (AuthenticationSchemes scheme, NameValueCollection parameters)
|
||||||
: base (scheme, parameters)
|
: base (scheme, parameters)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Constructors
|
#region Internal Constructors
|
||||||
|
|
||||||
internal AuthenticationChallenge (AuthenticationSchemes scheme, string realm)
|
internal AuthenticationChallenge (AuthenticationSchemes scheme, string realm)
|
||||||
: base (scheme, new NameValueCollection ())
|
: base (scheme, new NameValueCollection ())
|
||||||
{
|
{
|
||||||
Parameters["realm"] = realm;
|
Parameters["realm"] = realm;
|
||||||
if (scheme == AuthenticationSchemes.Digest) {
|
if (scheme == AuthenticationSchemes.Digest) {
|
||||||
Parameters["nonce"] = CreateNonceValue ();
|
Parameters["nonce"] = CreateNonceValue ();
|
||||||
Parameters["algorithm"] = "MD5";
|
Parameters["algorithm"] = "MD5";
|
||||||
Parameters["qop"] = "auth";
|
Parameters["qop"] = "auth";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
public string Domain {
|
public string Domain {
|
||||||
get {
|
get {
|
||||||
return Parameters["domain"];
|
return Parameters["domain"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Stale {
|
public string Stale {
|
||||||
get {
|
get {
|
||||||
return Parameters["stale"];
|
return Parameters["stale"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Methods
|
#region Internal Methods
|
||||||
|
|
||||||
internal static AuthenticationChallenge CreateBasicChallenge (string realm)
|
internal static AuthenticationChallenge CreateBasicChallenge (string realm)
|
||||||
{
|
{
|
||||||
return new AuthenticationChallenge (AuthenticationSchemes.Basic, realm);
|
return new AuthenticationChallenge (AuthenticationSchemes.Basic, realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static AuthenticationChallenge CreateDigestChallenge (string realm)
|
internal static AuthenticationChallenge CreateDigestChallenge (string realm)
|
||||||
{
|
{
|
||||||
return new AuthenticationChallenge (AuthenticationSchemes.Digest, realm);
|
return new AuthenticationChallenge (AuthenticationSchemes.Digest, realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static AuthenticationChallenge Parse (string value)
|
internal static AuthenticationChallenge Parse (string value)
|
||||||
{
|
{
|
||||||
var chal = value.Split (new[] { ' ' }, 2);
|
var chal = value.Split (new[] { ' ' }, 2);
|
||||||
if (chal.Length != 2)
|
if (chal.Length != 2)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var schm = chal[0].ToLower ();
|
var schm = chal[0].ToLower ();
|
||||||
return schm == "basic"
|
return schm == "basic"
|
||||||
? new AuthenticationChallenge (
|
? new AuthenticationChallenge (
|
||||||
AuthenticationSchemes.Basic, ParseParameters (chal[1]))
|
AuthenticationSchemes.Basic, ParseParameters (chal[1]))
|
||||||
: schm == "digest"
|
: schm == "digest"
|
||||||
? new AuthenticationChallenge (
|
? new AuthenticationChallenge (
|
||||||
AuthenticationSchemes.Digest, ParseParameters (chal[1]))
|
AuthenticationSchemes.Digest, ParseParameters (chal[1]))
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override string ToBasicString ()
|
internal override string ToBasicString ()
|
||||||
{
|
{
|
||||||
return String.Format ("Basic realm=\"{0}\"", Parameters["realm"]);
|
return String.Format ("Basic realm=\"{0}\"", Parameters["realm"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override string ToDigestString ()
|
internal override string ToDigestString ()
|
||||||
{
|
{
|
||||||
var output = new StringBuilder (128);
|
var output = new StringBuilder (128);
|
||||||
|
|
||||||
var domain = Parameters["domain"];
|
var domain = Parameters["domain"];
|
||||||
if (domain != null)
|
if (domain != null)
|
||||||
output.AppendFormat (
|
output.AppendFormat (
|
||||||
"Digest realm=\"{0}\", domain=\"{1}\", nonce=\"{2}\"",
|
"Digest realm=\"{0}\", domain=\"{1}\", nonce=\"{2}\"",
|
||||||
Parameters["realm"],
|
Parameters["realm"],
|
||||||
domain,
|
domain,
|
||||||
Parameters["nonce"]);
|
Parameters["nonce"]);
|
||||||
else
|
else
|
||||||
output.AppendFormat (
|
output.AppendFormat (
|
||||||
"Digest realm=\"{0}\", nonce=\"{1}\"", Parameters["realm"], Parameters["nonce"]);
|
"Digest realm=\"{0}\", nonce=\"{1}\"", Parameters["realm"], Parameters["nonce"]);
|
||||||
|
|
||||||
var opaque = Parameters["opaque"];
|
var opaque = Parameters["opaque"];
|
||||||
if (opaque != null)
|
if (opaque != null)
|
||||||
output.AppendFormat (", opaque=\"{0}\"", opaque);
|
output.AppendFormat (", opaque=\"{0}\"", opaque);
|
||||||
|
|
||||||
var stale = Parameters["stale"];
|
var stale = Parameters["stale"];
|
||||||
if (stale != null)
|
if (stale != null)
|
||||||
output.AppendFormat (", stale={0}", stale);
|
output.AppendFormat (", stale={0}", stale);
|
||||||
|
|
||||||
var algo = Parameters["algorithm"];
|
var algo = Parameters["algorithm"];
|
||||||
if (algo != null)
|
if (algo != null)
|
||||||
output.AppendFormat (", algorithm={0}", algo);
|
output.AppendFormat (", algorithm={0}", algo);
|
||||||
|
|
||||||
var qop = Parameters["qop"];
|
var qop = Parameters["qop"];
|
||||||
if (qop != null)
|
if (qop != null)
|
||||||
output.AppendFormat (", qop=\"{0}\"", qop);
|
output.AppendFormat (", qop=\"{0}\"", qop);
|
||||||
|
|
||||||
return output.ToString ();
|
return output.ToString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,323 +1,323 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* AuthenticationResponse.cs
|
* AuthenticationResponse.cs
|
||||||
*
|
*
|
||||||
* ParseBasicCredentials is derived from System.Net.HttpListenerContext.cs of Mono
|
* ParseBasicCredentials is derived from System.Net.HttpListenerContext.cs of Mono
|
||||||
* (http://www.mono-project.com).
|
* (http://www.mono-project.com).
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
|
* Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
|
||||||
* Copyright (c) 2013-2014 sta.blockhead
|
* Copyright (c) 2013-2014 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace WebSocketSharp.Net
|
namespace WebSocketSharp.Net
|
||||||
{
|
{
|
||||||
internal class AuthenticationResponse : AuthenticationBase
|
internal class AuthenticationResponse : AuthenticationBase
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private uint _nonceCount;
|
private uint _nonceCount;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Constructors
|
#region Private Constructors
|
||||||
|
|
||||||
private AuthenticationResponse (AuthenticationSchemes scheme, NameValueCollection parameters)
|
private AuthenticationResponse (AuthenticationSchemes scheme, NameValueCollection parameters)
|
||||||
: base (scheme, parameters)
|
: base (scheme, parameters)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Constructors
|
#region Internal Constructors
|
||||||
|
|
||||||
internal AuthenticationResponse (NetworkCredential credentials)
|
internal AuthenticationResponse (NetworkCredential credentials)
|
||||||
: this (AuthenticationSchemes.Basic, new NameValueCollection (), credentials, 0)
|
: this (AuthenticationSchemes.Basic, new NameValueCollection (), credentials, 0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
internal AuthenticationResponse (
|
internal AuthenticationResponse (
|
||||||
AuthenticationChallenge challenge, NetworkCredential credentials, uint nonceCount)
|
AuthenticationChallenge challenge, NetworkCredential credentials, uint nonceCount)
|
||||||
: this (challenge.Scheme, challenge.Parameters, credentials, nonceCount)
|
: this (challenge.Scheme, challenge.Parameters, credentials, nonceCount)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
internal AuthenticationResponse (
|
internal AuthenticationResponse (
|
||||||
AuthenticationSchemes scheme,
|
AuthenticationSchemes scheme,
|
||||||
NameValueCollection parameters,
|
NameValueCollection parameters,
|
||||||
NetworkCredential credentials,
|
NetworkCredential credentials,
|
||||||
uint nonceCount)
|
uint nonceCount)
|
||||||
: base (scheme, parameters)
|
: base (scheme, parameters)
|
||||||
{
|
{
|
||||||
Parameters["username"] = credentials.Username;
|
Parameters["username"] = credentials.Username;
|
||||||
Parameters["password"] = credentials.Password;
|
Parameters["password"] = credentials.Password;
|
||||||
Parameters["uri"] = credentials.Domain;
|
Parameters["uri"] = credentials.Domain;
|
||||||
_nonceCount = nonceCount;
|
_nonceCount = nonceCount;
|
||||||
if (scheme == AuthenticationSchemes.Digest)
|
if (scheme == AuthenticationSchemes.Digest)
|
||||||
initAsDigest ();
|
initAsDigest ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Properties
|
#region Internal Properties
|
||||||
|
|
||||||
internal uint NonceCount {
|
internal uint NonceCount {
|
||||||
get {
|
get {
|
||||||
return _nonceCount < UInt32.MaxValue
|
return _nonceCount < UInt32.MaxValue
|
||||||
? _nonceCount
|
? _nonceCount
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
public string Cnonce {
|
public string Cnonce {
|
||||||
get {
|
get {
|
||||||
return Parameters["cnonce"];
|
return Parameters["cnonce"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Nc {
|
public string Nc {
|
||||||
get {
|
get {
|
||||||
return Parameters["nc"];
|
return Parameters["nc"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Password {
|
public string Password {
|
||||||
get {
|
get {
|
||||||
return Parameters["password"];
|
return Parameters["password"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Response {
|
public string Response {
|
||||||
get {
|
get {
|
||||||
return Parameters["response"];
|
return Parameters["response"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Uri {
|
public string Uri {
|
||||||
get {
|
get {
|
||||||
return Parameters["uri"];
|
return Parameters["uri"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string UserName {
|
public string UserName {
|
||||||
get {
|
get {
|
||||||
return Parameters["username"];
|
return Parameters["username"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Methods
|
#region Private Methods
|
||||||
|
|
||||||
private static string createA1 (string username, string password, string realm)
|
private static string createA1 (string username, string password, string realm)
|
||||||
{
|
{
|
||||||
return String.Format ("{0}:{1}:{2}", username, realm, password);
|
return String.Format ("{0}:{1}:{2}", username, realm, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string createA1 (
|
private static string createA1 (
|
||||||
string username, string password, string realm, string nonce, string cnonce)
|
string username, string password, string realm, string nonce, string cnonce)
|
||||||
{
|
{
|
||||||
return String.Format (
|
return String.Format (
|
||||||
"{0}:{1}:{2}", hash (createA1 (username, password, realm)), nonce, cnonce);
|
"{0}:{1}:{2}", hash (createA1 (username, password, realm)), nonce, cnonce);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string createA2 (string method, string uri)
|
private static string createA2 (string method, string uri)
|
||||||
{
|
{
|
||||||
return String.Format ("{0}:{1}", method, uri);
|
return String.Format ("{0}:{1}", method, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string createA2 (string method, string uri, string entity)
|
private static string createA2 (string method, string uri, string entity)
|
||||||
{
|
{
|
||||||
return String.Format ("{0}:{1}:{2}", method, uri, hash (entity));
|
return String.Format ("{0}:{1}:{2}", method, uri, hash (entity));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string hash (string value)
|
private static string hash (string value)
|
||||||
{
|
{
|
||||||
var src = Encoding.UTF8.GetBytes (value);
|
var src = Encoding.UTF8.GetBytes (value);
|
||||||
var md5 = MD5.Create ();
|
var md5 = MD5.Create ();
|
||||||
var hashed = md5.ComputeHash (src);
|
var hashed = md5.ComputeHash (src);
|
||||||
|
|
||||||
var res = new StringBuilder (64);
|
var res = new StringBuilder (64);
|
||||||
foreach (var b in hashed)
|
foreach (var b in hashed)
|
||||||
res.Append (b.ToString ("x2"));
|
res.Append (b.ToString ("x2"));
|
||||||
|
|
||||||
return res.ToString ();
|
return res.ToString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initAsDigest ()
|
private void initAsDigest ()
|
||||||
{
|
{
|
||||||
var qops = Parameters["qop"];
|
var qops = Parameters["qop"];
|
||||||
if (qops != null) {
|
if (qops != null) {
|
||||||
if (qops.Split (',').Contains (qop => qop.Trim ().ToLower () == "auth")) {
|
if (qops.Split (',').Contains (qop => qop.Trim ().ToLower () == "auth")) {
|
||||||
Parameters["qop"] = "auth";
|
Parameters["qop"] = "auth";
|
||||||
Parameters["cnonce"] = CreateNonceValue ();
|
Parameters["cnonce"] = CreateNonceValue ();
|
||||||
Parameters["nc"] = String.Format ("{0:x8}", ++_nonceCount);
|
Parameters["nc"] = String.Format ("{0:x8}", ++_nonceCount);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Parameters["qop"] = null;
|
Parameters["qop"] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Parameters["method"] = "GET";
|
Parameters["method"] = "GET";
|
||||||
Parameters["response"] = CreateRequestDigest (Parameters);
|
Parameters["response"] = CreateRequestDigest (Parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Methods
|
#region Internal Methods
|
||||||
|
|
||||||
internal static string CreateRequestDigest (NameValueCollection parameters)
|
internal static string CreateRequestDigest (NameValueCollection parameters)
|
||||||
{
|
{
|
||||||
var user = parameters["username"];
|
var user = parameters["username"];
|
||||||
var pass = parameters["password"];
|
var pass = parameters["password"];
|
||||||
var realm = parameters["realm"];
|
var realm = parameters["realm"];
|
||||||
var nonce = parameters["nonce"];
|
var nonce = parameters["nonce"];
|
||||||
var uri = parameters["uri"];
|
var uri = parameters["uri"];
|
||||||
var algo = parameters["algorithm"];
|
var algo = parameters["algorithm"];
|
||||||
var qop = parameters["qop"];
|
var qop = parameters["qop"];
|
||||||
var cnonce = parameters["cnonce"];
|
var cnonce = parameters["cnonce"];
|
||||||
var nc = parameters["nc"];
|
var nc = parameters["nc"];
|
||||||
var method = parameters["method"];
|
var method = parameters["method"];
|
||||||
|
|
||||||
var a1 = algo != null && algo.ToLower () == "md5-sess"
|
var a1 = algo != null && algo.ToLower () == "md5-sess"
|
||||||
? createA1 (user, pass, realm, nonce, cnonce)
|
? createA1 (user, pass, realm, nonce, cnonce)
|
||||||
: createA1 (user, pass, realm);
|
: createA1 (user, pass, realm);
|
||||||
|
|
||||||
var a2 = qop != null && qop.ToLower () == "auth-int"
|
var a2 = qop != null && qop.ToLower () == "auth-int"
|
||||||
? createA2 (method, uri, parameters["entity"])
|
? createA2 (method, uri, parameters["entity"])
|
||||||
: createA2 (method, uri);
|
: createA2 (method, uri);
|
||||||
|
|
||||||
var secret = hash (a1);
|
var secret = hash (a1);
|
||||||
var data = qop != null
|
var data = qop != null
|
||||||
? String.Format ("{0}:{1}:{2}:{3}:{4}", nonce, nc, cnonce, qop, hash (a2))
|
? String.Format ("{0}:{1}:{2}:{3}:{4}", nonce, nc, cnonce, qop, hash (a2))
|
||||||
: String.Format ("{0}:{1}", nonce, hash (a2));
|
: String.Format ("{0}:{1}", nonce, hash (a2));
|
||||||
|
|
||||||
return hash (String.Format ("{0}:{1}", secret, data));
|
return hash (String.Format ("{0}:{1}", secret, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static AuthenticationResponse Parse (string value)
|
internal static AuthenticationResponse Parse (string value)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
var cred = value.Split (new[] { ' ' }, 2);
|
var cred = value.Split (new[] { ' ' }, 2);
|
||||||
if (cred.Length != 2)
|
if (cred.Length != 2)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var schm = cred[0].ToLower ();
|
var schm = cred[0].ToLower ();
|
||||||
return schm == "basic"
|
return schm == "basic"
|
||||||
? new AuthenticationResponse (
|
? new AuthenticationResponse (
|
||||||
AuthenticationSchemes.Basic, ParseBasicCredentials (cred[1]))
|
AuthenticationSchemes.Basic, ParseBasicCredentials (cred[1]))
|
||||||
: schm == "digest"
|
: schm == "digest"
|
||||||
? new AuthenticationResponse (
|
? new AuthenticationResponse (
|
||||||
AuthenticationSchemes.Digest, ParseParameters (cred[1]))
|
AuthenticationSchemes.Digest, ParseParameters (cred[1]))
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static NameValueCollection ParseBasicCredentials (string value)
|
internal static NameValueCollection ParseBasicCredentials (string value)
|
||||||
{
|
{
|
||||||
// Decode the basic-credentials (a Base64 encoded string).
|
// Decode the basic-credentials (a Base64 encoded string).
|
||||||
var userPass = Encoding.Default.GetString (Convert.FromBase64String (value));
|
var userPass = Encoding.Default.GetString (Convert.FromBase64String (value));
|
||||||
|
|
||||||
// The format is [<domain>\]<username>:<password>.
|
// The format is [<domain>\]<username>:<password>.
|
||||||
var i = userPass.IndexOf (':');
|
var i = userPass.IndexOf (':');
|
||||||
var user = userPass.Substring (0, i);
|
var user = userPass.Substring (0, i);
|
||||||
var pass = i < userPass.Length - 1 ? userPass.Substring (i + 1) : String.Empty;
|
var pass = i < userPass.Length - 1 ? userPass.Substring (i + 1) : String.Empty;
|
||||||
|
|
||||||
// Check if 'domain' exists.
|
// Check if 'domain' exists.
|
||||||
i = user.IndexOf ('\\');
|
i = user.IndexOf ('\\');
|
||||||
if (i > -1)
|
if (i > -1)
|
||||||
user = user.Substring (i + 1);
|
user = user.Substring (i + 1);
|
||||||
|
|
||||||
var res = new NameValueCollection ();
|
var res = new NameValueCollection ();
|
||||||
res["username"] = user;
|
res["username"] = user;
|
||||||
res["password"] = pass;
|
res["password"] = pass;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override string ToBasicString ()
|
internal override string ToBasicString ()
|
||||||
{
|
{
|
||||||
var userPass = String.Format ("{0}:{1}", Parameters["username"], Parameters["password"]);
|
var userPass = String.Format ("{0}:{1}", Parameters["username"], Parameters["password"]);
|
||||||
var cred = Convert.ToBase64String (Encoding.UTF8.GetBytes (userPass));
|
var cred = Convert.ToBase64String (Encoding.UTF8.GetBytes (userPass));
|
||||||
|
|
||||||
return "Basic " + cred;
|
return "Basic " + cred;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override string ToDigestString ()
|
internal override string ToDigestString ()
|
||||||
{
|
{
|
||||||
var output = new StringBuilder (256);
|
var output = new StringBuilder (256);
|
||||||
output.AppendFormat (
|
output.AppendFormat (
|
||||||
"Digest username=\"{0}\", realm=\"{1}\", nonce=\"{2}\", uri=\"{3}\", response=\"{4}\"",
|
"Digest username=\"{0}\", realm=\"{1}\", nonce=\"{2}\", uri=\"{3}\", response=\"{4}\"",
|
||||||
Parameters["username"],
|
Parameters["username"],
|
||||||
Parameters["realm"],
|
Parameters["realm"],
|
||||||
Parameters["nonce"],
|
Parameters["nonce"],
|
||||||
Parameters["uri"],
|
Parameters["uri"],
|
||||||
Parameters["response"]);
|
Parameters["response"]);
|
||||||
|
|
||||||
var opaque = Parameters["opaque"];
|
var opaque = Parameters["opaque"];
|
||||||
if (opaque != null)
|
if (opaque != null)
|
||||||
output.AppendFormat (", opaque=\"{0}\"", opaque);
|
output.AppendFormat (", opaque=\"{0}\"", opaque);
|
||||||
|
|
||||||
var algo = Parameters["algorithm"];
|
var algo = Parameters["algorithm"];
|
||||||
if (algo != null)
|
if (algo != null)
|
||||||
output.AppendFormat (", algorithm={0}", algo);
|
output.AppendFormat (", algorithm={0}", algo);
|
||||||
|
|
||||||
var qop = Parameters["qop"];
|
var qop = Parameters["qop"];
|
||||||
if (qop != null)
|
if (qop != null)
|
||||||
output.AppendFormat (
|
output.AppendFormat (
|
||||||
", qop={0}, cnonce=\"{1}\", nc={2}", qop, Parameters["cnonce"], Parameters["nc"]);
|
", qop={0}, cnonce=\"{1}\", nc={2}", qop, Parameters["cnonce"], Parameters["nc"]);
|
||||||
|
|
||||||
return output.ToString ();
|
return output.ToString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
public IIdentity ToIdentity ()
|
public IIdentity ToIdentity ()
|
||||||
{
|
{
|
||||||
var schm = Scheme;
|
var schm = Scheme;
|
||||||
return schm == AuthenticationSchemes.Basic
|
return schm == AuthenticationSchemes.Basic
|
||||||
? new HttpBasicIdentity (Parameters["username"], Parameters["password"]) as IIdentity
|
? new HttpBasicIdentity (Parameters["username"], Parameters["password"]) as IIdentity
|
||||||
: schm == AuthenticationSchemes.Digest
|
: schm == AuthenticationSchemes.Digest
|
||||||
? new HttpDigestIdentity (Parameters)
|
? new HttpDigestIdentity (Parameters)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,66 +1,66 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* AuthenticationSchemes.cs
|
* AuthenticationSchemes.cs
|
||||||
*
|
*
|
||||||
* This code is derived from AuthenticationSchemes.cs (System.Net) of Mono
|
* This code is derived from AuthenticationSchemes.cs (System.Net) of Mono
|
||||||
* (http://www.mono-project.com).
|
* (http://www.mono-project.com).
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
|
* Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
|
||||||
* Copyright (c) 2012-2016 sta.blockhead
|
* Copyright (c) 2012-2016 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Authors
|
#region Authors
|
||||||
/*
|
/*
|
||||||
* Authors:
|
* Authors:
|
||||||
* - Atsushi Enomoto <atsushi@ximian.com>
|
* - Atsushi Enomoto <atsushi@ximian.com>
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WebSocketSharp.Net
|
namespace WebSocketSharp.Net
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the scheme for authentication.
|
/// Specifies the scheme for authentication.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum AuthenticationSchemes
|
public enum AuthenticationSchemes
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// No authentication is allowed.
|
/// No authentication is allowed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
None,
|
None,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies digest authentication.
|
/// Specifies digest authentication.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Digest = 1,
|
Digest = 1,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies basic authentication.
|
/// Specifies basic authentication.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Basic = 8,
|
Basic = 8,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies anonymous authentication.
|
/// Specifies anonymous authentication.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Anonymous = 0x8000
|
Anonymous = 0x8000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,91 +1,91 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* Chunk.cs
|
* Chunk.cs
|
||||||
*
|
*
|
||||||
* This code is derived from ChunkStream.cs (System.Net) of Mono
|
* This code is derived from ChunkStream.cs (System.Net) of Mono
|
||||||
* (http://www.mono-project.com).
|
* (http://www.mono-project.com).
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2003 Ximian, Inc (http://www.ximian.com)
|
* Copyright (c) 2003 Ximian, Inc (http://www.ximian.com)
|
||||||
* Copyright (c) 2014-2015 sta.blockhead
|
* Copyright (c) 2014-2015 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Authors
|
#region Authors
|
||||||
/*
|
/*
|
||||||
* Authors:
|
* Authors:
|
||||||
* - Gonzalo Paniagua Javier <gonzalo@ximian.com>
|
* - Gonzalo Paniagua Javier <gonzalo@ximian.com>
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WebSocketSharp.Net
|
namespace WebSocketSharp.Net
|
||||||
{
|
{
|
||||||
internal class Chunk
|
internal class Chunk
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private byte[] _data;
|
private byte[] _data;
|
||||||
private int _offset;
|
private int _offset;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Constructors
|
#region Public Constructors
|
||||||
|
|
||||||
public Chunk (byte[] data)
|
public Chunk (byte[] data)
|
||||||
{
|
{
|
||||||
_data = data;
|
_data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
public int ReadLeft {
|
public int ReadLeft {
|
||||||
get {
|
get {
|
||||||
return _data.Length - _offset;
|
return _data.Length - _offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
public int Read (byte[] buffer, int offset, int count)
|
public int Read (byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
var left = _data.Length - _offset;
|
var left = _data.Length - _offset;
|
||||||
if (left == 0)
|
if (left == 0)
|
||||||
return left;
|
return left;
|
||||||
|
|
||||||
if (count > left)
|
if (count > left)
|
||||||
count = left;
|
count = left;
|
||||||
|
|
||||||
Buffer.BlockCopy (_data, _offset, buffer, offset, count);
|
Buffer.BlockCopy (_data, _offset, buffer, offset, count);
|
||||||
_offset += count;
|
_offset += count;
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,360 +1,360 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* ChunkStream.cs
|
* ChunkStream.cs
|
||||||
*
|
*
|
||||||
* This code is derived from ChunkStream.cs (System.Net) of Mono
|
* This code is derived from ChunkStream.cs (System.Net) of Mono
|
||||||
* (http://www.mono-project.com).
|
* (http://www.mono-project.com).
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2003 Ximian, Inc (http://www.ximian.com)
|
* Copyright (c) 2003 Ximian, Inc (http://www.ximian.com)
|
||||||
* Copyright (c) 2012-2015 sta.blockhead
|
* Copyright (c) 2012-2015 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Authors
|
#region Authors
|
||||||
/*
|
/*
|
||||||
* Authors:
|
* Authors:
|
||||||
* - Gonzalo Paniagua Javier <gonzalo@ximian.com>
|
* - Gonzalo Paniagua Javier <gonzalo@ximian.com>
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace WebSocketSharp.Net
|
namespace WebSocketSharp.Net
|
||||||
{
|
{
|
||||||
internal class ChunkStream
|
internal class ChunkStream
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private int _chunkRead;
|
private int _chunkRead;
|
||||||
private int _chunkSize;
|
private int _chunkSize;
|
||||||
private List<Chunk> _chunks;
|
private List<Chunk> _chunks;
|
||||||
private bool _gotIt;
|
private bool _gotIt;
|
||||||
private WebHeaderCollection _headers;
|
private WebHeaderCollection _headers;
|
||||||
private StringBuilder _saved;
|
private StringBuilder _saved;
|
||||||
private bool _sawCr;
|
private bool _sawCr;
|
||||||
private InputChunkState _state;
|
private InputChunkState _state;
|
||||||
private int _trailerState;
|
private int _trailerState;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Constructors
|
#region Public Constructors
|
||||||
|
|
||||||
public ChunkStream (WebHeaderCollection headers)
|
public ChunkStream (WebHeaderCollection headers)
|
||||||
{
|
{
|
||||||
_headers = headers;
|
_headers = headers;
|
||||||
_chunkSize = -1;
|
_chunkSize = -1;
|
||||||
_chunks = new List<Chunk> ();
|
_chunks = new List<Chunk> ();
|
||||||
_saved = new StringBuilder ();
|
_saved = new StringBuilder ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChunkStream (byte[] buffer, int offset, int count, WebHeaderCollection headers)
|
public ChunkStream (byte[] buffer, int offset, int count, WebHeaderCollection headers)
|
||||||
: this (headers)
|
: this (headers)
|
||||||
{
|
{
|
||||||
Write (buffer, offset, count);
|
Write (buffer, offset, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Properties
|
#region Internal Properties
|
||||||
|
|
||||||
internal WebHeaderCollection Headers {
|
internal WebHeaderCollection Headers {
|
||||||
get {
|
get {
|
||||||
return _headers;
|
return _headers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
public int ChunkLeft {
|
public int ChunkLeft {
|
||||||
get {
|
get {
|
||||||
return _chunkSize - _chunkRead;
|
return _chunkSize - _chunkRead;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool WantMore {
|
public bool WantMore {
|
||||||
get {
|
get {
|
||||||
return _state != InputChunkState.End;
|
return _state != InputChunkState.End;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Methods
|
#region Private Methods
|
||||||
|
|
||||||
private int read (byte[] buffer, int offset, int count)
|
private int read (byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
var nread = 0;
|
var nread = 0;
|
||||||
|
|
||||||
var cnt = _chunks.Count;
|
var cnt = _chunks.Count;
|
||||||
for (var i = 0; i < cnt; i++) {
|
for (var i = 0; i < cnt; i++) {
|
||||||
var chunk = _chunks[i];
|
var chunk = _chunks[i];
|
||||||
if (chunk == null)
|
if (chunk == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (chunk.ReadLeft == 0) {
|
if (chunk.ReadLeft == 0) {
|
||||||
_chunks[i] = null;
|
_chunks[i] = null;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
nread += chunk.Read (buffer, offset + nread, count - nread);
|
nread += chunk.Read (buffer, offset + nread, count - nread);
|
||||||
if (nread == count)
|
if (nread == count)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string removeChunkExtension (string value)
|
private static string removeChunkExtension (string value)
|
||||||
{
|
{
|
||||||
var idx = value.IndexOf (';');
|
var idx = value.IndexOf (';');
|
||||||
return idx > -1 ? value.Substring (0, idx) : value;
|
return idx > -1 ? value.Substring (0, idx) : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputChunkState seekCrLf (byte[] buffer, ref int offset, int length)
|
private InputChunkState seekCrLf (byte[] buffer, ref int offset, int length)
|
||||||
{
|
{
|
||||||
if (!_sawCr) {
|
if (!_sawCr) {
|
||||||
if (buffer[offset++] != 13)
|
if (buffer[offset++] != 13)
|
||||||
throwProtocolViolation ("CR is expected.");
|
throwProtocolViolation ("CR is expected.");
|
||||||
|
|
||||||
_sawCr = true;
|
_sawCr = true;
|
||||||
if (offset == length)
|
if (offset == length)
|
||||||
return InputChunkState.DataEnded;
|
return InputChunkState.DataEnded;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer[offset++] != 10)
|
if (buffer[offset++] != 10)
|
||||||
throwProtocolViolation ("LF is expected.");
|
throwProtocolViolation ("LF is expected.");
|
||||||
|
|
||||||
return InputChunkState.None;
|
return InputChunkState.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputChunkState setChunkSize (byte[] buffer, ref int offset, int length)
|
private InputChunkState setChunkSize (byte[] buffer, ref int offset, int length)
|
||||||
{
|
{
|
||||||
byte b = 0;
|
byte b = 0;
|
||||||
while (offset < length) {
|
while (offset < length) {
|
||||||
b = buffer[offset++];
|
b = buffer[offset++];
|
||||||
if (_sawCr) {
|
if (_sawCr) {
|
||||||
if (b != 10)
|
if (b != 10)
|
||||||
throwProtocolViolation ("LF is expected.");
|
throwProtocolViolation ("LF is expected.");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b == 13) {
|
if (b == 13) {
|
||||||
_sawCr = true;
|
_sawCr = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b == 10)
|
if (b == 10)
|
||||||
throwProtocolViolation ("LF is unexpected.");
|
throwProtocolViolation ("LF is unexpected.");
|
||||||
|
|
||||||
if (b == 32) // SP
|
if (b == 32) // SP
|
||||||
_gotIt = true;
|
_gotIt = true;
|
||||||
|
|
||||||
if (!_gotIt)
|
if (!_gotIt)
|
||||||
_saved.Append ((char) b);
|
_saved.Append ((char) b);
|
||||||
|
|
||||||
if (_saved.Length > 20)
|
if (_saved.Length > 20)
|
||||||
throwProtocolViolation ("The chunk size is too long.");
|
throwProtocolViolation ("The chunk size is too long.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_sawCr || b != 10)
|
if (!_sawCr || b != 10)
|
||||||
return InputChunkState.None;
|
return InputChunkState.None;
|
||||||
|
|
||||||
_chunkRead = 0;
|
_chunkRead = 0;
|
||||||
try {
|
try {
|
||||||
_chunkSize = Int32.Parse (
|
_chunkSize = Int32.Parse (
|
||||||
removeChunkExtension (_saved.ToString ()), NumberStyles.HexNumber);
|
removeChunkExtension (_saved.ToString ()), NumberStyles.HexNumber);
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
throwProtocolViolation ("The chunk size cannot be parsed.");
|
throwProtocolViolation ("The chunk size cannot be parsed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_chunkSize == 0) {
|
if (_chunkSize == 0) {
|
||||||
_trailerState = 2;
|
_trailerState = 2;
|
||||||
return InputChunkState.Trailer;
|
return InputChunkState.Trailer;
|
||||||
}
|
}
|
||||||
|
|
||||||
return InputChunkState.Data;
|
return InputChunkState.Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputChunkState setTrailer (byte[] buffer, ref int offset, int length)
|
private InputChunkState setTrailer (byte[] buffer, ref int offset, int length)
|
||||||
{
|
{
|
||||||
// Check if no trailer.
|
// Check if no trailer.
|
||||||
if (_trailerState == 2 && buffer[offset] == 13 && _saved.Length == 0) {
|
if (_trailerState == 2 && buffer[offset] == 13 && _saved.Length == 0) {
|
||||||
offset++;
|
offset++;
|
||||||
if (offset < length && buffer[offset] == 10) {
|
if (offset < length && buffer[offset] == 10) {
|
||||||
offset++;
|
offset++;
|
||||||
return InputChunkState.End;
|
return InputChunkState.End;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset--;
|
offset--;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (offset < length && _trailerState < 4) {
|
while (offset < length && _trailerState < 4) {
|
||||||
var b = buffer[offset++];
|
var b = buffer[offset++];
|
||||||
_saved.Append ((char) b);
|
_saved.Append ((char) b);
|
||||||
if (_saved.Length > 4196)
|
if (_saved.Length > 4196)
|
||||||
throwProtocolViolation ("The trailer is too long.");
|
throwProtocolViolation ("The trailer is too long.");
|
||||||
|
|
||||||
if (_trailerState == 1 || _trailerState == 3) {
|
if (_trailerState == 1 || _trailerState == 3) {
|
||||||
if (b != 10)
|
if (b != 10)
|
||||||
throwProtocolViolation ("LF is expected.");
|
throwProtocolViolation ("LF is expected.");
|
||||||
|
|
||||||
_trailerState++;
|
_trailerState++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b == 13) {
|
if (b == 13) {
|
||||||
_trailerState++;
|
_trailerState++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b == 10)
|
if (b == 10)
|
||||||
throwProtocolViolation ("LF is unexpected.");
|
throwProtocolViolation ("LF is unexpected.");
|
||||||
|
|
||||||
_trailerState = 0;
|
_trailerState = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_trailerState < 4)
|
if (_trailerState < 4)
|
||||||
return InputChunkState.Trailer;
|
return InputChunkState.Trailer;
|
||||||
|
|
||||||
_saved.Length -= 2;
|
_saved.Length -= 2;
|
||||||
var reader = new StringReader (_saved.ToString ());
|
var reader = new StringReader (_saved.ToString ());
|
||||||
|
|
||||||
string line;
|
string line;
|
||||||
while ((line = reader.ReadLine ()) != null && line.Length > 0)
|
while ((line = reader.ReadLine ()) != null && line.Length > 0)
|
||||||
_headers.Add (line);
|
_headers.Add (line);
|
||||||
|
|
||||||
return InputChunkState.End;
|
return InputChunkState.End;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void throwProtocolViolation (string message)
|
private static void throwProtocolViolation (string message)
|
||||||
{
|
{
|
||||||
throw new WebException (message, null, WebExceptionStatus.ServerProtocolViolation, null);
|
throw new WebException (message, null, WebExceptionStatus.ServerProtocolViolation, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void write (byte[] buffer, ref int offset, int length)
|
private void write (byte[] buffer, ref int offset, int length)
|
||||||
{
|
{
|
||||||
if (_state == InputChunkState.End)
|
if (_state == InputChunkState.End)
|
||||||
throwProtocolViolation ("The chunks were ended.");
|
throwProtocolViolation ("The chunks were ended.");
|
||||||
|
|
||||||
if (_state == InputChunkState.None) {
|
if (_state == InputChunkState.None) {
|
||||||
_state = setChunkSize (buffer, ref offset, length);
|
_state = setChunkSize (buffer, ref offset, length);
|
||||||
if (_state == InputChunkState.None)
|
if (_state == InputChunkState.None)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_saved.Length = 0;
|
_saved.Length = 0;
|
||||||
_sawCr = false;
|
_sawCr = false;
|
||||||
_gotIt = false;
|
_gotIt = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_state == InputChunkState.Data && offset < length) {
|
if (_state == InputChunkState.Data && offset < length) {
|
||||||
_state = writeData (buffer, ref offset, length);
|
_state = writeData (buffer, ref offset, length);
|
||||||
if (_state == InputChunkState.Data)
|
if (_state == InputChunkState.Data)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_state == InputChunkState.DataEnded && offset < length) {
|
if (_state == InputChunkState.DataEnded && offset < length) {
|
||||||
_state = seekCrLf (buffer, ref offset, length);
|
_state = seekCrLf (buffer, ref offset, length);
|
||||||
if (_state == InputChunkState.DataEnded)
|
if (_state == InputChunkState.DataEnded)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_sawCr = false;
|
_sawCr = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_state == InputChunkState.Trailer && offset < length) {
|
if (_state == InputChunkState.Trailer && offset < length) {
|
||||||
_state = setTrailer (buffer, ref offset, length);
|
_state = setTrailer (buffer, ref offset, length);
|
||||||
if (_state == InputChunkState.Trailer)
|
if (_state == InputChunkState.Trailer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_saved.Length = 0;
|
_saved.Length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset < length)
|
if (offset < length)
|
||||||
write (buffer, ref offset, length);
|
write (buffer, ref offset, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputChunkState writeData (byte[] buffer, ref int offset, int length)
|
private InputChunkState writeData (byte[] buffer, ref int offset, int length)
|
||||||
{
|
{
|
||||||
var cnt = length - offset;
|
var cnt = length - offset;
|
||||||
var left = _chunkSize - _chunkRead;
|
var left = _chunkSize - _chunkRead;
|
||||||
if (cnt > left)
|
if (cnt > left)
|
||||||
cnt = left;
|
cnt = left;
|
||||||
|
|
||||||
var data = new byte[cnt];
|
var data = new byte[cnt];
|
||||||
Buffer.BlockCopy (buffer, offset, data, 0, cnt);
|
Buffer.BlockCopy (buffer, offset, data, 0, cnt);
|
||||||
_chunks.Add (new Chunk (data));
|
_chunks.Add (new Chunk (data));
|
||||||
|
|
||||||
offset += cnt;
|
offset += cnt;
|
||||||
_chunkRead += cnt;
|
_chunkRead += cnt;
|
||||||
|
|
||||||
return _chunkRead == _chunkSize ? InputChunkState.DataEnded : InputChunkState.Data;
|
return _chunkRead == _chunkSize ? InputChunkState.DataEnded : InputChunkState.Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Methods
|
#region Internal Methods
|
||||||
|
|
||||||
internal void ResetBuffer ()
|
internal void ResetBuffer ()
|
||||||
{
|
{
|
||||||
_chunkRead = 0;
|
_chunkRead = 0;
|
||||||
_chunkSize = -1;
|
_chunkSize = -1;
|
||||||
_chunks.Clear ();
|
_chunks.Clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal int WriteAndReadBack (byte[] buffer, int offset, int writeCount, int readCount)
|
internal int WriteAndReadBack (byte[] buffer, int offset, int writeCount, int readCount)
|
||||||
{
|
{
|
||||||
Write (buffer, offset, writeCount);
|
Write (buffer, offset, writeCount);
|
||||||
return Read (buffer, offset, readCount);
|
return Read (buffer, offset, readCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
public int Read (byte[] buffer, int offset, int count)
|
public int Read (byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return read (buffer, offset, count);
|
return read (buffer, offset, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write (byte[] buffer, int offset, int count)
|
public void Write (byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
write (buffer, ref offset, offset + count);
|
write (buffer, ref offset, offset + count);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,213 +1,213 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* ChunkedRequestStream.cs
|
* ChunkedRequestStream.cs
|
||||||
*
|
*
|
||||||
* This code is derived from ChunkedInputStream.cs (System.Net) of Mono
|
* This code is derived from ChunkedInputStream.cs (System.Net) of Mono
|
||||||
* (http://www.mono-project.com).
|
* (http://www.mono-project.com).
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
|
* Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
|
||||||
* Copyright (c) 2012-2015 sta.blockhead
|
* Copyright (c) 2012-2015 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Authors
|
#region Authors
|
||||||
/*
|
/*
|
||||||
* Authors:
|
* Authors:
|
||||||
* - Gonzalo Paniagua Javier <gonzalo@novell.com>
|
* - Gonzalo Paniagua Javier <gonzalo@novell.com>
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace WebSocketSharp.Net
|
namespace WebSocketSharp.Net
|
||||||
{
|
{
|
||||||
internal class ChunkedRequestStream : RequestStream
|
internal class ChunkedRequestStream : RequestStream
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private const int _bufferLength = 8192;
|
private const int _bufferLength = 8192;
|
||||||
private HttpListenerContext _context;
|
private HttpListenerContext _context;
|
||||||
private ChunkStream _decoder;
|
private ChunkStream _decoder;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
private bool _noMoreData;
|
private bool _noMoreData;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Constructors
|
#region Internal Constructors
|
||||||
|
|
||||||
internal ChunkedRequestStream (
|
internal ChunkedRequestStream (
|
||||||
Stream stream, byte[] buffer, int offset, int count, HttpListenerContext context)
|
Stream stream, byte[] buffer, int offset, int count, HttpListenerContext context)
|
||||||
: base (stream, buffer, offset, count)
|
: base (stream, buffer, offset, count)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_decoder = new ChunkStream ((WebHeaderCollection) context.Request.Headers);
|
_decoder = new ChunkStream ((WebHeaderCollection) context.Request.Headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Properties
|
#region Internal Properties
|
||||||
|
|
||||||
internal ChunkStream Decoder {
|
internal ChunkStream Decoder {
|
||||||
get {
|
get {
|
||||||
return _decoder;
|
return _decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
set {
|
set {
|
||||||
_decoder = value;
|
_decoder = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Methods
|
#region Private Methods
|
||||||
|
|
||||||
private void onRead (IAsyncResult asyncResult)
|
private void onRead (IAsyncResult asyncResult)
|
||||||
{
|
{
|
||||||
var rstate = (ReadBufferState) asyncResult.AsyncState;
|
var rstate = (ReadBufferState) asyncResult.AsyncState;
|
||||||
var ares = rstate.AsyncResult;
|
var ares = rstate.AsyncResult;
|
||||||
try {
|
try {
|
||||||
var nread = base.EndRead (asyncResult);
|
var nread = base.EndRead (asyncResult);
|
||||||
_decoder.Write (ares.Buffer, ares.Offset, nread);
|
_decoder.Write (ares.Buffer, ares.Offset, nread);
|
||||||
nread = _decoder.Read (rstate.Buffer, rstate.Offset, rstate.Count);
|
nread = _decoder.Read (rstate.Buffer, rstate.Offset, rstate.Count);
|
||||||
rstate.Offset += nread;
|
rstate.Offset += nread;
|
||||||
rstate.Count -= nread;
|
rstate.Count -= nread;
|
||||||
if (rstate.Count == 0 || !_decoder.WantMore || nread == 0) {
|
if (rstate.Count == 0 || !_decoder.WantMore || nread == 0) {
|
||||||
_noMoreData = !_decoder.WantMore && nread == 0;
|
_noMoreData = !_decoder.WantMore && nread == 0;
|
||||||
ares.Count = rstate.InitialCount - rstate.Count;
|
ares.Count = rstate.InitialCount - rstate.Count;
|
||||||
ares.Complete ();
|
ares.Complete ();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ares.Offset = 0;
|
ares.Offset = 0;
|
||||||
ares.Count = Math.Min (_bufferLength, _decoder.ChunkLeft + 6);
|
ares.Count = Math.Min (_bufferLength, _decoder.ChunkLeft + 6);
|
||||||
base.BeginRead (ares.Buffer, ares.Offset, ares.Count, onRead, rstate);
|
base.BeginRead (ares.Buffer, ares.Offset, ares.Count, onRead, rstate);
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
_context.ErrorMessage = ex.Message;
|
_context.ErrorMessage = ex.Message;
|
||||||
_context.SendError ();
|
_context.SendError ();
|
||||||
|
|
||||||
ares.Complete (ex);
|
ares.Complete (ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
public override IAsyncResult BeginRead (
|
public override IAsyncResult BeginRead (
|
||||||
byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException (GetType ().ToString ());
|
throw new ObjectDisposedException (GetType ().ToString ());
|
||||||
|
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
throw new ArgumentNullException ("buffer");
|
throw new ArgumentNullException ("buffer");
|
||||||
|
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
throw new ArgumentOutOfRangeException ("offset", "A negative value.");
|
throw new ArgumentOutOfRangeException ("offset", "A negative value.");
|
||||||
|
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
throw new ArgumentOutOfRangeException ("count", "A negative value.");
|
throw new ArgumentOutOfRangeException ("count", "A negative value.");
|
||||||
|
|
||||||
var len = buffer.Length;
|
var len = buffer.Length;
|
||||||
if (offset + count > len)
|
if (offset + count > len)
|
||||||
throw new ArgumentException (
|
throw new ArgumentException (
|
||||||
"The sum of 'offset' and 'count' is greater than 'buffer' length.");
|
"The sum of 'offset' and 'count' is greater than 'buffer' length.");
|
||||||
|
|
||||||
var ares = new HttpStreamAsyncResult (callback, state);
|
var ares = new HttpStreamAsyncResult (callback, state);
|
||||||
if (_noMoreData) {
|
if (_noMoreData) {
|
||||||
ares.Complete ();
|
ares.Complete ();
|
||||||
return ares;
|
return ares;
|
||||||
}
|
}
|
||||||
|
|
||||||
var nread = _decoder.Read (buffer, offset, count);
|
var nread = _decoder.Read (buffer, offset, count);
|
||||||
offset += nread;
|
offset += nread;
|
||||||
count -= nread;
|
count -= nread;
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
// Got all we wanted, no need to bother the decoder yet.
|
// Got all we wanted, no need to bother the decoder yet.
|
||||||
ares.Count = nread;
|
ares.Count = nread;
|
||||||
ares.Complete ();
|
ares.Complete ();
|
||||||
|
|
||||||
return ares;
|
return ares;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_decoder.WantMore) {
|
if (!_decoder.WantMore) {
|
||||||
_noMoreData = nread == 0;
|
_noMoreData = nread == 0;
|
||||||
ares.Count = nread;
|
ares.Count = nread;
|
||||||
ares.Complete ();
|
ares.Complete ();
|
||||||
|
|
||||||
return ares;
|
return ares;
|
||||||
}
|
}
|
||||||
|
|
||||||
ares.Buffer = new byte[_bufferLength];
|
ares.Buffer = new byte[_bufferLength];
|
||||||
ares.Offset = 0;
|
ares.Offset = 0;
|
||||||
ares.Count = _bufferLength;
|
ares.Count = _bufferLength;
|
||||||
|
|
||||||
var rstate = new ReadBufferState (buffer, offset, count, ares);
|
var rstate = new ReadBufferState (buffer, offset, count, ares);
|
||||||
rstate.InitialCount += nread;
|
rstate.InitialCount += nread;
|
||||||
base.BeginRead (ares.Buffer, ares.Offset, ares.Count, onRead, rstate);
|
base.BeginRead (ares.Buffer, ares.Offset, ares.Count, onRead, rstate);
|
||||||
|
|
||||||
return ares;
|
return ares;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Close ()
|
public override void Close ()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
base.Close ();
|
base.Close ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int EndRead (IAsyncResult asyncResult)
|
public override int EndRead (IAsyncResult asyncResult)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException (GetType ().ToString ());
|
throw new ObjectDisposedException (GetType ().ToString ());
|
||||||
|
|
||||||
if (asyncResult == null)
|
if (asyncResult == null)
|
||||||
throw new ArgumentNullException ("asyncResult");
|
throw new ArgumentNullException ("asyncResult");
|
||||||
|
|
||||||
var ares = asyncResult as HttpStreamAsyncResult;
|
var ares = asyncResult as HttpStreamAsyncResult;
|
||||||
if (ares == null)
|
if (ares == null)
|
||||||
throw new ArgumentException ("A wrong IAsyncResult.", "asyncResult");
|
throw new ArgumentException ("A wrong IAsyncResult.", "asyncResult");
|
||||||
|
|
||||||
if (!ares.IsCompleted)
|
if (!ares.IsCompleted)
|
||||||
ares.AsyncWaitHandle.WaitOne ();
|
ares.AsyncWaitHandle.WaitOne ();
|
||||||
|
|
||||||
if (ares.HasException)
|
if (ares.HasException)
|
||||||
throw new HttpListenerException (400, "I/O operation aborted.");
|
throw new HttpListenerException (400, "I/O operation aborted.");
|
||||||
|
|
||||||
return ares.Count;
|
return ares.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int Read (byte[] buffer, int offset, int count)
|
public override int Read (byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
var ares = BeginRead (buffer, offset, count, null, null);
|
var ares = BeginRead (buffer, offset, count, null, null);
|
||||||
return EndRead (ares);
|
return EndRead (ares);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,165 +1,165 @@
|
|||||||
#region License
|
#region License
|
||||||
/*
|
/*
|
||||||
* CookieException.cs
|
* CookieException.cs
|
||||||
*
|
*
|
||||||
* This code is derived from CookieException.cs (System.Net) of Mono
|
* This code is derived from CookieException.cs (System.Net) of Mono
|
||||||
* (http://www.mono-project.com).
|
* (http://www.mono-project.com).
|
||||||
*
|
*
|
||||||
* The MIT License
|
* The MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2019 sta.blockhead
|
* Copyright (c) 2012-2019 sta.blockhead
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Authors
|
#region Authors
|
||||||
/*
|
/*
|
||||||
* Authors:
|
* Authors:
|
||||||
* - Lawrence Pit <loz@cable.a2000.nl>
|
* - Lawrence Pit <loz@cable.a2000.nl>
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Security.Permissions;
|
using System.Security.Permissions;
|
||||||
|
|
||||||
namespace WebSocketSharp.Net
|
namespace WebSocketSharp.Net
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The exception that is thrown when a <see cref="Cookie"/> gets an error.
|
/// The exception that is thrown when a <see cref="Cookie"/> gets an error.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class CookieException : FormatException, ISerializable
|
public class CookieException : FormatException, ISerializable
|
||||||
{
|
{
|
||||||
#region Internal Constructors
|
#region Internal Constructors
|
||||||
|
|
||||||
internal CookieException (string message)
|
internal CookieException (string message)
|
||||||
: base (message)
|
: base (message)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
internal CookieException (string message, Exception innerException)
|
internal CookieException (string message, Exception innerException)
|
||||||
: base (message, innerException)
|
: base (message, innerException)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Protected Constructors
|
#region Protected Constructors
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="CookieException"/> class
|
/// Initializes a new instance of the <see cref="CookieException"/> class
|
||||||
/// with the serialized data.
|
/// with the serialized data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="serializationInfo">
|
/// <param name="serializationInfo">
|
||||||
/// A <see cref="SerializationInfo"/> that holds the serialized object data.
|
/// A <see cref="SerializationInfo"/> that holds the serialized object data.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="streamingContext">
|
/// <param name="streamingContext">
|
||||||
/// A <see cref="StreamingContext"/> that specifies the source for
|
/// A <see cref="StreamingContext"/> that specifies the source for
|
||||||
/// the deserialization.
|
/// the deserialization.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <exception cref="ArgumentNullException">
|
/// <exception cref="ArgumentNullException">
|
||||||
/// <paramref name="serializationInfo"/> is <see langword="null"/>.
|
/// <paramref name="serializationInfo"/> is <see langword="null"/>.
|
||||||
/// </exception>
|
/// </exception>
|
||||||
protected CookieException (
|
protected CookieException (
|
||||||
SerializationInfo serializationInfo, StreamingContext streamingContext
|
SerializationInfo serializationInfo, StreamingContext streamingContext
|
||||||
)
|
)
|
||||||
: base (serializationInfo, streamingContext)
|
: base (serializationInfo, streamingContext)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Constructors
|
#region Public Constructors
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="CookieException"/> class.
|
/// Initializes a new instance of the <see cref="CookieException"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CookieException ()
|
public CookieException ()
|
||||||
: base ()
|
: base ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Populates the specified <see cref="SerializationInfo"/> instance with
|
/// Populates the specified <see cref="SerializationInfo"/> instance with
|
||||||
/// the data needed to serialize the current instance.
|
/// the data needed to serialize the current instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="serializationInfo">
|
/// <param name="serializationInfo">
|
||||||
/// A <see cref="SerializationInfo"/> that holds the serialized object data.
|
/// A <see cref="SerializationInfo"/> that holds the serialized object data.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="streamingContext">
|
/// <param name="streamingContext">
|
||||||
/// A <see cref="StreamingContext"/> that specifies the destination for
|
/// A <see cref="StreamingContext"/> that specifies the destination for
|
||||||
/// the serialization.
|
/// the serialization.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <exception cref="ArgumentNullException">
|
/// <exception cref="ArgumentNullException">
|
||||||
/// <paramref name="serializationInfo"/> is <see langword="null"/>.
|
/// <paramref name="serializationInfo"/> is <see langword="null"/>.
|
||||||
/// </exception>
|
/// </exception>
|
||||||
[
|
[
|
||||||
SecurityPermission (
|
SecurityPermission (
|
||||||
SecurityAction.LinkDemand,
|
SecurityAction.LinkDemand,
|
||||||
Flags = SecurityPermissionFlag.SerializationFormatter
|
Flags = SecurityPermissionFlag.SerializationFormatter
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
public override void GetObjectData (
|
public override void GetObjectData (
|
||||||
SerializationInfo serializationInfo, StreamingContext streamingContext
|
SerializationInfo serializationInfo, StreamingContext streamingContext
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
base.GetObjectData (serializationInfo, streamingContext);
|
base.GetObjectData (serializationInfo, streamingContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Explicit Interface Implementation
|
#region Explicit Interface Implementation
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Populates the specified <see cref="SerializationInfo"/> instance with
|
/// Populates the specified <see cref="SerializationInfo"/> instance with
|
||||||
/// the data needed to serialize the current instance.
|
/// the data needed to serialize the current instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="serializationInfo">
|
/// <param name="serializationInfo">
|
||||||
/// A <see cref="SerializationInfo"/> that holds the serialized object data.
|
/// A <see cref="SerializationInfo"/> that holds the serialized object data.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="streamingContext">
|
/// <param name="streamingContext">
|
||||||
/// A <see cref="StreamingContext"/> that specifies the destination for
|
/// A <see cref="StreamingContext"/> that specifies the destination for
|
||||||
/// the serialization.
|
/// the serialization.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <exception cref="ArgumentNullException">
|
/// <exception cref="ArgumentNullException">
|
||||||
/// <paramref name="serializationInfo"/> is <see langword="null"/>.
|
/// <paramref name="serializationInfo"/> is <see langword="null"/>.
|
||||||
/// </exception>
|
/// </exception>
|
||||||
[
|
[
|
||||||
SecurityPermission (
|
SecurityPermission (
|
||||||
SecurityAction.LinkDemand,
|
SecurityAction.LinkDemand,
|
||||||
Flags = SecurityPermissionFlag.SerializationFormatter,
|
Flags = SecurityPermissionFlag.SerializationFormatter,
|
||||||
SerializationFormatter = true
|
SerializationFormatter = true
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
void ISerializable.GetObjectData (
|
void ISerializable.GetObjectData (
|
||||||
SerializationInfo serializationInfo, StreamingContext streamingContext
|
SerializationInfo serializationInfo, StreamingContext streamingContext
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
base.GetObjectData (serializationInfo, streamingContext);
|
base.GetObjectData (serializationInfo, streamingContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue