added stuff
parent
06fc05ee04
commit
f1b7a6de0f
@ -1,14 +1,14 @@
|
||||
## Ignore build results and temporary files.
|
||||
|
||||
Backup*
|
||||
_UpgradeReport_Files
|
||||
bin
|
||||
obj
|
||||
|
||||
*.mdb
|
||||
*.pdb
|
||||
*.pidb
|
||||
*.suo
|
||||
*.user
|
||||
*.userprefs
|
||||
UpgradeLog*.*
|
||||
## Ignore build results and temporary files.
|
||||
|
||||
Backup*
|
||||
_UpgradeReport_Files
|
||||
bin
|
||||
obj
|
||||
|
||||
*.mdb
|
||||
*.pdb
|
||||
*.pidb
|
||||
*.suo
|
||||
*.user
|
||||
*.userprefs
|
||||
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.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("Example")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("sta.blockhead")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("Example")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("sta.blockhead")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
|
||||
@ -1,71 +1,78 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{52805AEC-EFB1-4F42-BB8E-3ED4E692C568}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Example</RootNamespace>
|
||||
<AssemblyName>example</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
||||
<DefineConstants>DEBUG,UBUNTU</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
||||
<DefineConstants>UBUNTU</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="notify-sharp, Version=0.4.0.0, Culture=neutral, PublicKeyToken=2df29c54e245917a">
|
||||
<Package>notify-sharp</Package>
|
||||
</Reference>
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
||||
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
||||
<Name>websocket-sharp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Notifier.cs" />
|
||||
<Compile Include="NotificationMessage.cs" />
|
||||
</ItemGroup>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{52805AEC-EFB1-4F42-BB8E-3ED4E692C568}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Example</RootNamespace>
|
||||
<AssemblyName>example</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
||||
<DefineConstants>DEBUG,UBUNTU</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
||||
<DefineConstants>UBUNTU</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
|
||||
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net35\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="notify-sharp, Version=0.4.0.0, Culture=neutral, PublicKeyToken=2df29c54e245917a">
|
||||
<Package>notify-sharp</Package>
|
||||
</Reference>
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
||||
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
||||
<Name>websocket-sharp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<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>
|
||||
@ -1,24 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace Example
|
||||
{
|
||||
internal class NotificationMessage
|
||||
{
|
||||
public string Body {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string Icon {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string Summary {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return String.Format ("{0}: {1}", Summary, Body);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
|
||||
namespace Example
|
||||
{
|
||||
internal class NotificationMessage
|
||||
{
|
||||
public string Body {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string Icon {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string Summary {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return String.Format ("{0}: {1}", Summary, Body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,81 +1,81 @@
|
||||
#if UBUNTU
|
||||
using Notifications;
|
||||
#endif
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace Example
|
||||
{
|
||||
internal class Notifier : IDisposable
|
||||
{
|
||||
private volatile bool _enabled;
|
||||
private ManualResetEvent _exited;
|
||||
private Queue<NotificationMessage> _queue;
|
||||
private object _sync;
|
||||
|
||||
public Notifier ()
|
||||
{
|
||||
_enabled = true;
|
||||
_exited = new ManualResetEvent (false);
|
||||
_queue = new Queue<NotificationMessage> ();
|
||||
_sync = ((ICollection) _queue).SyncRoot;
|
||||
|
||||
ThreadPool.QueueUserWorkItem (
|
||||
state => {
|
||||
while (_enabled || Count > 0) {
|
||||
var msg = dequeue ();
|
||||
if (msg != null) {
|
||||
#if UBUNTU
|
||||
var nf = new Notification (msg.Summary, msg.Body, msg.Icon);
|
||||
nf.AddHint ("append", "allowed");
|
||||
nf.Show ();
|
||||
#else
|
||||
Console.WriteLine (msg);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
Thread.Sleep (500);
|
||||
}
|
||||
}
|
||||
|
||||
_exited.Set ();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public int Count {
|
||||
get {
|
||||
lock (_sync)
|
||||
return _queue.Count;
|
||||
}
|
||||
}
|
||||
|
||||
private NotificationMessage dequeue ()
|
||||
{
|
||||
lock (_sync)
|
||||
return _queue.Count > 0 ? _queue.Dequeue () : null;
|
||||
}
|
||||
|
||||
public void Close ()
|
||||
{
|
||||
_enabled = false;
|
||||
_exited.WaitOne ();
|
||||
_exited.Close ();
|
||||
}
|
||||
|
||||
public void Notify (NotificationMessage message)
|
||||
{
|
||||
lock (_sync) {
|
||||
if (_enabled)
|
||||
_queue.Enqueue (message);
|
||||
}
|
||||
}
|
||||
|
||||
void IDisposable.Dispose ()
|
||||
{
|
||||
Close ();
|
||||
}
|
||||
}
|
||||
}
|
||||
#if UBUNTU
|
||||
using Notifications;
|
||||
#endif
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace Example
|
||||
{
|
||||
internal class Notifier : IDisposable
|
||||
{
|
||||
private volatile bool _enabled;
|
||||
private ManualResetEvent _exited;
|
||||
private Queue<NotificationMessage> _queue;
|
||||
private object _sync;
|
||||
|
||||
public Notifier ()
|
||||
{
|
||||
_enabled = true;
|
||||
_exited = new ManualResetEvent (false);
|
||||
_queue = new Queue<NotificationMessage> ();
|
||||
_sync = ((ICollection) _queue).SyncRoot;
|
||||
|
||||
ThreadPool.QueueUserWorkItem (
|
||||
state => {
|
||||
while (_enabled || Count > 0) {
|
||||
var msg = dequeue ();
|
||||
if (msg != null) {
|
||||
#if UBUNTU
|
||||
var nf = new Notification (msg.Summary, msg.Body, msg.Icon);
|
||||
nf.AddHint ("append", "allowed");
|
||||
nf.Show ();
|
||||
#else
|
||||
Console.WriteLine (msg);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
Thread.Sleep (500);
|
||||
}
|
||||
}
|
||||
|
||||
_exited.Set ();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public int Count {
|
||||
get {
|
||||
lock (_sync)
|
||||
return _queue.Count;
|
||||
}
|
||||
}
|
||||
|
||||
private NotificationMessage dequeue ()
|
||||
{
|
||||
lock (_sync)
|
||||
return _queue.Count > 0 ? _queue.Dequeue () : null;
|
||||
}
|
||||
|
||||
public void Close ()
|
||||
{
|
||||
_enabled = false;
|
||||
_exited.WaitOne ();
|
||||
_exited.Close ();
|
||||
}
|
||||
|
||||
public void Notify (NotificationMessage message)
|
||||
{
|
||||
lock (_sync) {
|
||||
if (_enabled)
|
||||
_queue.Enqueue (message);
|
||||
}
|
||||
}
|
||||
|
||||
void IDisposable.Dispose ()
|
||||
{
|
||||
Close ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,128 +1,128 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Net;
|
||||
|
||||
namespace Example
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main (string[] args)
|
||||
{
|
||||
// Create a new instance of the WebSocket class.
|
||||
//
|
||||
// The WebSocket class inherits the System.IDisposable interface, so you can
|
||||
// use the using statement. And the WebSocket connection will be closed with
|
||||
// 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,
|
||||
// you should create a new instance with a wss scheme WebSocket URL.
|
||||
|
||||
using (var nf = new Notifier ())
|
||||
using (var ws = new WebSocket ("ws://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 ("wss://localhost:5963/Echo"))
|
||||
//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 ("ws://localhost:4649/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 ("wss://localhost:5963/Chat?name=nobita"))
|
||||
{
|
||||
// Set the WebSocket events.
|
||||
|
||||
ws.OnOpen += (sender, e) => ws.Send ("Hi, there!");
|
||||
|
||||
ws.OnMessage += (sender, e) =>
|
||||
nf.Notify (
|
||||
new NotificationMessage {
|
||||
Summary = "WebSocket Message",
|
||||
Body = !e.IsPing ? e.Data : "Received a ping.",
|
||||
Icon = "notification-message-im"
|
||||
}
|
||||
);
|
||||
|
||||
ws.OnError += (sender, e) =>
|
||||
nf.Notify (
|
||||
new NotificationMessage {
|
||||
Summary = "WebSocket Error",
|
||||
Body = e.Message,
|
||||
Icon = "notification-message-im"
|
||||
}
|
||||
);
|
||||
|
||||
ws.OnClose += (sender, e) =>
|
||||
nf.Notify (
|
||||
new NotificationMessage {
|
||||
Summary = String.Format ("WebSocket Close ({0})", e.Code),
|
||||
Body = e.Reason,
|
||||
Icon = "notification-message-im"
|
||||
}
|
||||
);
|
||||
#if DEBUG
|
||||
// To change the logging level.
|
||||
ws.Log.Level = LogLevel.Trace;
|
||||
|
||||
// To change the wait time for the response to the Ping or Close.
|
||||
//ws.WaitTime = TimeSpan.FromSeconds (10);
|
||||
|
||||
// To emit a WebSocket.OnMessage event when receives a ping.
|
||||
//ws.EmitOnPing = true;
|
||||
#endif
|
||||
// To enable the Per-message Compression extension.
|
||||
//ws.Compression = CompressionMethod.Deflate;
|
||||
|
||||
// To validate the server certificate.
|
||||
/*
|
||||
ws.SslConfiguration.ServerCertificateValidationCallback =
|
||||
(sender, certificate, chain, sslPolicyErrors) => {
|
||||
ws.Log.Debug (
|
||||
String.Format (
|
||||
"Certificate:\n- Issuer: {0}\n- Subject: {1}",
|
||||
certificate.Issuer,
|
||||
certificate.Subject
|
||||
)
|
||||
);
|
||||
|
||||
return true; // If the server certificate is valid.
|
||||
};
|
||||
*/
|
||||
|
||||
// To send the credentials for the HTTP Authentication (Basic/Digest).
|
||||
//ws.SetCredentials ("nobita", "password", false);
|
||||
|
||||
// To send the Origin header.
|
||||
//ws.Origin = "http://localhost:4649";
|
||||
|
||||
// To send the cookies.
|
||||
//ws.SetCookie (new Cookie ("name", "nobita"));
|
||||
//ws.SetCookie (new Cookie ("roles", "\"idiot, gunfighter\""));
|
||||
|
||||
// To connect through the HTTP Proxy server.
|
||||
//ws.SetProxy ("http://localhost:3128", "nobita", "password");
|
||||
|
||||
// To enable the redirection.
|
||||
//ws.EnableRedirection = true;
|
||||
|
||||
// Connect to the server.
|
||||
ws.Connect ();
|
||||
|
||||
// Connect to the server asynchronously.
|
||||
//ws.ConnectAsync ();
|
||||
|
||||
Console.WriteLine ("\nType 'exit' to exit.\n");
|
||||
while (true) {
|
||||
Thread.Sleep (1000);
|
||||
Console.Write ("> ");
|
||||
var msg = Console.ReadLine ();
|
||||
if (msg == "exit")
|
||||
break;
|
||||
|
||||
// Send a text message.
|
||||
ws.Send (msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Threading;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Net;
|
||||
|
||||
namespace Example
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main (string[] args)
|
||||
{
|
||||
// Create a new instance of the WebSocket class.
|
||||
//
|
||||
// The WebSocket class inherits the System.IDisposable interface, so you can
|
||||
// use the using statement. And the WebSocket connection will be closed with
|
||||
// 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,
|
||||
// you should create a new instance with a wss scheme WebSocket URL.
|
||||
|
||||
using (var nf = new Notifier ())
|
||||
using (var ws = new WebSocket ("ws://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 ("wss://localhost:5963/Echo"))
|
||||
//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 ("ws://localhost:4649/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 ("wss://localhost:5963/Chat?name=nobita"))
|
||||
{
|
||||
// Set the WebSocket events.
|
||||
|
||||
ws.OnOpen += (sender, e) => ws.Send ("Hi, there!");
|
||||
|
||||
ws.OnMessage += (sender, e) =>
|
||||
nf.Notify (
|
||||
new NotificationMessage {
|
||||
Summary = "WebSocket Message",
|
||||
Body = !e.IsPing ? e.Data : "Received a ping.",
|
||||
Icon = "notification-message-im"
|
||||
}
|
||||
);
|
||||
|
||||
ws.OnError += (sender, e) =>
|
||||
nf.Notify (
|
||||
new NotificationMessage {
|
||||
Summary = "WebSocket Error",
|
||||
Body = e.Message,
|
||||
Icon = "notification-message-im"
|
||||
}
|
||||
);
|
||||
|
||||
ws.OnClose += (sender, e) =>
|
||||
nf.Notify (
|
||||
new NotificationMessage {
|
||||
Summary = String.Format ("WebSocket Close ({0})", e.Code),
|
||||
Body = e.Reason,
|
||||
Icon = "notification-message-im"
|
||||
}
|
||||
);
|
||||
#if DEBUG
|
||||
// To change the logging level.
|
||||
ws.Log.Level = LogLevel.Trace;
|
||||
|
||||
// To change the wait time for the response to the Ping or Close.
|
||||
//ws.WaitTime = TimeSpan.FromSeconds (10);
|
||||
|
||||
// To emit a WebSocket.OnMessage event when receives a ping.
|
||||
//ws.EmitOnPing = true;
|
||||
#endif
|
||||
// To enable the Per-message Compression extension.
|
||||
//ws.Compression = CompressionMethod.Deflate;
|
||||
|
||||
// To validate the server certificate.
|
||||
/*
|
||||
ws.SslConfiguration.ServerCertificateValidationCallback =
|
||||
(sender, certificate, chain, sslPolicyErrors) => {
|
||||
ws.Log.Debug (
|
||||
String.Format (
|
||||
"Certificate:\n- Issuer: {0}\n- Subject: {1}",
|
||||
certificate.Issuer,
|
||||
certificate.Subject
|
||||
)
|
||||
);
|
||||
|
||||
return true; // If the server certificate is valid.
|
||||
};
|
||||
*/
|
||||
|
||||
// To send the credentials for the HTTP Authentication (Basic/Digest).
|
||||
//ws.SetCredentials ("nobita", "password", false);
|
||||
|
||||
// To send the Origin header.
|
||||
//ws.Origin = "http://localhost:4649";
|
||||
|
||||
// To send the cookies.
|
||||
//ws.SetCookie (new Cookie ("name", "nobita"));
|
||||
//ws.SetCookie (new Cookie ("roles", "\"idiot, gunfighter\""));
|
||||
|
||||
// To connect through the HTTP Proxy server.
|
||||
//ws.SetProxy ("http://localhost:3128", "nobita", "password");
|
||||
|
||||
// To enable the redirection.
|
||||
//ws.EnableRedirection = true;
|
||||
|
||||
// Connect to the server.
|
||||
ws.Connect ();
|
||||
|
||||
// Connect to the server asynchronously.
|
||||
//ws.ConnectAsync ();
|
||||
|
||||
Console.WriteLine ("\nType 'exit' to exit.\n");
|
||||
while (true) {
|
||||
Thread.Sleep (1000);
|
||||
Console.Write ("> ");
|
||||
var msg = Console.ReadLine ();
|
||||
if (msg == "exit")
|
||||
break;
|
||||
|
||||
// Send a text message.
|
||||
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.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("Example1")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("sta.blockhead")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("Example1")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("sta.blockhead")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
|
||||
@ -1,192 +1,192 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using WebSocketSharp;
|
||||
|
||||
namespace Example1
|
||||
{
|
||||
internal class AudioStreamer : IDisposable
|
||||
{
|
||||
private Dictionary<uint, Queue> _audioBox;
|
||||
private uint? _id;
|
||||
private string _name;
|
||||
private Notifier _notifier;
|
||||
private Timer _timer;
|
||||
private WebSocket _websocket;
|
||||
|
||||
public AudioStreamer (string url)
|
||||
{
|
||||
_websocket = new WebSocket (url);
|
||||
|
||||
_audioBox = new Dictionary<uint, Queue> ();
|
||||
_id = null;
|
||||
_notifier = new Notifier ();
|
||||
_timer = new Timer (sendHeartbeat, null, -1, -1);
|
||||
|
||||
configure ();
|
||||
}
|
||||
|
||||
private void configure ()
|
||||
{
|
||||
#if DEBUG
|
||||
_websocket.Log.Level = LogLevel.Trace;
|
||||
#endif
|
||||
_websocket.OnOpen += (sender, e) =>
|
||||
_websocket.Send (createTextMessage ("connection", String.Empty));
|
||||
|
||||
_websocket.OnMessage += (sender, e) => {
|
||||
if (e.IsText) {
|
||||
_notifier.Notify (processTextMessage (e.Data));
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.IsBinary) {
|
||||
processBinaryMessage (e.RawData);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
_websocket.OnError += (sender, e) =>
|
||||
_notifier.Notify (
|
||||
new NotificationMessage {
|
||||
Summary = "AudioStreamer (error)",
|
||||
Body = e.Message,
|
||||
Icon = "notification-message-im"
|
||||
}
|
||||
);
|
||||
|
||||
_websocket.OnClose += (sender, e) =>
|
||||
_notifier.Notify (
|
||||
new NotificationMessage {
|
||||
Summary = "AudioStreamer (disconnect)",
|
||||
Body = String.Format ("code: {0} reason: {1}", e.Code, e.Reason),
|
||||
Icon = "notification-message-im"
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private byte[] createBinaryMessage (float[,] bufferArray)
|
||||
{
|
||||
return new BinaryMessage {
|
||||
UserID = (uint) _id,
|
||||
ChannelNumber = (byte) bufferArray.GetLength (0),
|
||||
BufferLength = (uint) bufferArray.GetLength (1),
|
||||
BufferArray = bufferArray
|
||||
}
|
||||
.ToArray ();
|
||||
}
|
||||
|
||||
private string createTextMessage (string type, string message)
|
||||
{
|
||||
return new TextMessage {
|
||||
UserID = _id,
|
||||
Name = _name,
|
||||
Type = type,
|
||||
Message = message
|
||||
}
|
||||
.ToString ();
|
||||
}
|
||||
|
||||
private void processBinaryMessage (byte[] data)
|
||||
{
|
||||
var msg = BinaryMessage.Parse (data);
|
||||
|
||||
var id = msg.UserID;
|
||||
if (id == _id)
|
||||
return;
|
||||
|
||||
Queue queue;
|
||||
if (_audioBox.TryGetValue (id, out queue)) {
|
||||
queue.Enqueue (msg.BufferArray);
|
||||
return;
|
||||
}
|
||||
|
||||
queue = Queue.Synchronized (new Queue ());
|
||||
queue.Enqueue (msg.BufferArray);
|
||||
_audioBox.Add (id, queue);
|
||||
}
|
||||
|
||||
private NotificationMessage processTextMessage (string data)
|
||||
{
|
||||
var json = JObject.Parse (data);
|
||||
var id = (uint) json["user_id"];
|
||||
var name = (string) json["name"];
|
||||
var type = (string) json["type"];
|
||||
|
||||
string body;
|
||||
if (type == "message") {
|
||||
body = String.Format ("{0}: {1}", name, (string) json["message"]);
|
||||
}
|
||||
else if (type == "start_music") {
|
||||
body = String.Format ("{0}: Started playing music!", name);
|
||||
}
|
||||
else if (type == "connection") {
|
||||
var users = (JArray) json["message"];
|
||||
var buff = new StringBuilder ("Now keeping connections:");
|
||||
foreach (JToken user in users) {
|
||||
buff.AppendFormat (
|
||||
"\n- user_id: {0} name: {1}", (uint) user["user_id"], (string) user["name"]
|
||||
);
|
||||
}
|
||||
|
||||
body = buff.ToString ();
|
||||
}
|
||||
else if (type == "connected") {
|
||||
_id = id;
|
||||
_timer.Change (30000, 30000);
|
||||
|
||||
body = String.Format ("user_id: {0} name: {1}", id, name);
|
||||
}
|
||||
else {
|
||||
body = "Received unknown type message.";
|
||||
}
|
||||
|
||||
return new NotificationMessage {
|
||||
Summary = String.Format ("AudioStreamer ({0})", type),
|
||||
Body = body,
|
||||
Icon = "notification-message-im"
|
||||
};
|
||||
}
|
||||
|
||||
private void sendHeartbeat (object state)
|
||||
{
|
||||
_websocket.Send (createTextMessage ("heartbeat", String.Empty));
|
||||
}
|
||||
|
||||
public void Close ()
|
||||
{
|
||||
Disconnect ();
|
||||
_timer.Dispose ();
|
||||
_notifier.Close ();
|
||||
}
|
||||
|
||||
public void Connect (string username)
|
||||
{
|
||||
_name = username;
|
||||
_websocket.Connect ();
|
||||
}
|
||||
|
||||
public void Disconnect ()
|
||||
{
|
||||
_timer.Change (-1, -1);
|
||||
_websocket.Close (CloseStatusCode.Away);
|
||||
_audioBox.Clear ();
|
||||
_id = null;
|
||||
_name = null;
|
||||
}
|
||||
|
||||
public void Write (string message)
|
||||
{
|
||||
_websocket.Send (createTextMessage ("message", message));
|
||||
}
|
||||
|
||||
void IDisposable.Dispose ()
|
||||
{
|
||||
Close ();
|
||||
}
|
||||
}
|
||||
}
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using WebSocketSharp;
|
||||
|
||||
namespace Example1
|
||||
{
|
||||
internal class AudioStreamer : IDisposable
|
||||
{
|
||||
private Dictionary<uint, Queue> _audioBox;
|
||||
private uint? _id;
|
||||
private string _name;
|
||||
private Notifier _notifier;
|
||||
private Timer _timer;
|
||||
private WebSocket _websocket;
|
||||
|
||||
public AudioStreamer (string url)
|
||||
{
|
||||
_websocket = new WebSocket (url);
|
||||
|
||||
_audioBox = new Dictionary<uint, Queue> ();
|
||||
_id = null;
|
||||
_notifier = new Notifier ();
|
||||
_timer = new Timer (sendHeartbeat, null, -1, -1);
|
||||
|
||||
configure ();
|
||||
}
|
||||
|
||||
private void configure ()
|
||||
{
|
||||
#if DEBUG
|
||||
_websocket.Log.Level = LogLevel.Trace;
|
||||
#endif
|
||||
_websocket.OnOpen += (sender, e) =>
|
||||
_websocket.Send (createTextMessage ("connection", String.Empty));
|
||||
|
||||
_websocket.OnMessage += (sender, e) => {
|
||||
if (e.IsText) {
|
||||
_notifier.Notify (processTextMessage (e.Data));
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.IsBinary) {
|
||||
processBinaryMessage (e.RawData);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
_websocket.OnError += (sender, e) =>
|
||||
_notifier.Notify (
|
||||
new NotificationMessage {
|
||||
Summary = "AudioStreamer (error)",
|
||||
Body = e.Message,
|
||||
Icon = "notification-message-im"
|
||||
}
|
||||
);
|
||||
|
||||
_websocket.OnClose += (sender, e) =>
|
||||
_notifier.Notify (
|
||||
new NotificationMessage {
|
||||
Summary = "AudioStreamer (disconnect)",
|
||||
Body = String.Format ("code: {0} reason: {1}", e.Code, e.Reason),
|
||||
Icon = "notification-message-im"
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private byte[] createBinaryMessage (float[,] bufferArray)
|
||||
{
|
||||
return new BinaryMessage {
|
||||
UserID = (uint) _id,
|
||||
ChannelNumber = (byte) bufferArray.GetLength (0),
|
||||
BufferLength = (uint) bufferArray.GetLength (1),
|
||||
BufferArray = bufferArray
|
||||
}
|
||||
.ToArray ();
|
||||
}
|
||||
|
||||
private string createTextMessage (string type, string message)
|
||||
{
|
||||
return new TextMessage {
|
||||
UserID = _id,
|
||||
Name = _name,
|
||||
Type = type,
|
||||
Message = message
|
||||
}
|
||||
.ToString ();
|
||||
}
|
||||
|
||||
private void processBinaryMessage (byte[] data)
|
||||
{
|
||||
var msg = BinaryMessage.Parse (data);
|
||||
|
||||
var id = msg.UserID;
|
||||
if (id == _id)
|
||||
return;
|
||||
|
||||
Queue queue;
|
||||
if (_audioBox.TryGetValue (id, out queue)) {
|
||||
queue.Enqueue (msg.BufferArray);
|
||||
return;
|
||||
}
|
||||
|
||||
queue = Queue.Synchronized (new Queue ());
|
||||
queue.Enqueue (msg.BufferArray);
|
||||
_audioBox.Add (id, queue);
|
||||
}
|
||||
|
||||
private NotificationMessage processTextMessage (string data)
|
||||
{
|
||||
var json = JObject.Parse (data);
|
||||
var id = (uint) json["user_id"];
|
||||
var name = (string) json["name"];
|
||||
var type = (string) json["type"];
|
||||
|
||||
string body;
|
||||
if (type == "message") {
|
||||
body = String.Format ("{0}: {1}", name, (string) json["message"]);
|
||||
}
|
||||
else if (type == "start_music") {
|
||||
body = String.Format ("{0}: Started playing music!", name);
|
||||
}
|
||||
else if (type == "connection") {
|
||||
var users = (JArray) json["message"];
|
||||
var buff = new StringBuilder ("Now keeping connections:");
|
||||
foreach (JToken user in users) {
|
||||
buff.AppendFormat (
|
||||
"\n- user_id: {0} name: {1}", (uint) user["user_id"], (string) user["name"]
|
||||
);
|
||||
}
|
||||
|
||||
body = buff.ToString ();
|
||||
}
|
||||
else if (type == "connected") {
|
||||
_id = id;
|
||||
_timer.Change (30000, 30000);
|
||||
|
||||
body = String.Format ("user_id: {0} name: {1}", id, name);
|
||||
}
|
||||
else {
|
||||
body = "Received unknown type message.";
|
||||
}
|
||||
|
||||
return new NotificationMessage {
|
||||
Summary = String.Format ("AudioStreamer ({0})", type),
|
||||
Body = body,
|
||||
Icon = "notification-message-im"
|
||||
};
|
||||
}
|
||||
|
||||
private void sendHeartbeat (object state)
|
||||
{
|
||||
_websocket.Send (createTextMessage ("heartbeat", String.Empty));
|
||||
}
|
||||
|
||||
public void Close ()
|
||||
{
|
||||
Disconnect ();
|
||||
_timer.Dispose ();
|
||||
_notifier.Close ();
|
||||
}
|
||||
|
||||
public void Connect (string username)
|
||||
{
|
||||
_name = username;
|
||||
_websocket.Connect ();
|
||||
}
|
||||
|
||||
public void Disconnect ()
|
||||
{
|
||||
_timer.Change (-1, -1);
|
||||
_websocket.Close (CloseStatusCode.Away);
|
||||
_audioBox.Clear ();
|
||||
_id = null;
|
||||
_name = null;
|
||||
}
|
||||
|
||||
public void Write (string message)
|
||||
{
|
||||
_websocket.Send (createTextMessage ("message", message));
|
||||
}
|
||||
|
||||
void IDisposable.Dispose ()
|
||||
{
|
||||
Close ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,74 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using WebSocketSharp;
|
||||
|
||||
namespace Example1
|
||||
{
|
||||
internal class BinaryMessage
|
||||
{
|
||||
public uint UserID {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public byte ChannelNumber {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public uint BufferLength {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public float[,] BufferArray {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public static BinaryMessage Parse (byte[] data)
|
||||
{
|
||||
var id = data.SubArray (0, 4).To<uint> (ByteOrder.Big);
|
||||
var num = data.SubArray (4, 1)[0];
|
||||
var len = data.SubArray (5, 4).To<uint> (ByteOrder.Big);
|
||||
var arr = new float[num, len];
|
||||
|
||||
var offset = 9;
|
||||
((uint) num).Times (
|
||||
i =>
|
||||
len.Times (
|
||||
j => {
|
||||
arr[i, j] = data.SubArray (offset, 4).To<float> (ByteOrder.Big);
|
||||
offset += 4;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
return new BinaryMessage {
|
||||
UserID = id,
|
||||
ChannelNumber = num,
|
||||
BufferLength = len,
|
||||
BufferArray = arr
|
||||
};
|
||||
}
|
||||
|
||||
public byte[] ToArray ()
|
||||
{
|
||||
var buff = new List<byte> ();
|
||||
|
||||
var id = UserID;
|
||||
var num = ChannelNumber;
|
||||
var len = BufferLength;
|
||||
var arr = BufferArray;
|
||||
|
||||
buff.AddRange (id.ToByteArray (ByteOrder.Big));
|
||||
buff.Add (num);
|
||||
buff.AddRange (len.ToByteArray (ByteOrder.Big));
|
||||
|
||||
((uint) num).Times (
|
||||
i =>
|
||||
len.Times (
|
||||
j => buff.AddRange (arr[i, j].ToByteArray (ByteOrder.Big))
|
||||
)
|
||||
);
|
||||
|
||||
return buff.ToArray ();
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using WebSocketSharp;
|
||||
|
||||
namespace Example1
|
||||
{
|
||||
internal class BinaryMessage
|
||||
{
|
||||
public uint UserID {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public byte ChannelNumber {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public uint BufferLength {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public float[,] BufferArray {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public static BinaryMessage Parse (byte[] data)
|
||||
{
|
||||
var id = data.SubArray (0, 4).To<uint> (ByteOrder.Big);
|
||||
var num = data.SubArray (4, 1)[0];
|
||||
var len = data.SubArray (5, 4).To<uint> (ByteOrder.Big);
|
||||
var arr = new float[num, len];
|
||||
|
||||
var offset = 9;
|
||||
((uint) num).Times (
|
||||
i =>
|
||||
len.Times (
|
||||
j => {
|
||||
arr[i, j] = data.SubArray (offset, 4).To<float> (ByteOrder.Big);
|
||||
offset += 4;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
return new BinaryMessage {
|
||||
UserID = id,
|
||||
ChannelNumber = num,
|
||||
BufferLength = len,
|
||||
BufferArray = arr
|
||||
};
|
||||
}
|
||||
|
||||
public byte[] ToArray ()
|
||||
{
|
||||
var buff = new List<byte> ();
|
||||
|
||||
var id = UserID;
|
||||
var num = ChannelNumber;
|
||||
var len = BufferLength;
|
||||
var arr = BufferArray;
|
||||
|
||||
buff.AddRange (id.ToByteArray (ByteOrder.Big));
|
||||
buff.Add (num);
|
||||
buff.AddRange (len.ToByteArray (ByteOrder.Big));
|
||||
|
||||
((uint) num).Times (
|
||||
i =>
|
||||
len.Times (
|
||||
j => buff.AddRange (arr[i, j].ToByteArray (ByteOrder.Big))
|
||||
)
|
||||
);
|
||||
|
||||
return buff.ToArray ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,77 +1,81 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{390E2568-57B7-4D17-91E5-C29336368CCF}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Example</RootNamespace>
|
||||
<AssemblyName>example1</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
||||
<DefineConstants>DEBUG;UBUNTU</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<DefineConstants>UBUNTU</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="notify-sharp, Version=0.4.0.0, Culture=neutral, PublicKeyToken=2df29c54e245917a">
|
||||
<Private>False</Private>
|
||||
<Package>notify-sharp</Package>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=3.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="AudioStreamer.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="TextMessage.cs" />
|
||||
<Compile Include="NotificationMessage.cs" />
|
||||
<Compile Include="Notifier.cs" />
|
||||
<Compile Include="BinaryMessage.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
||||
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
||||
<Name>websocket-sharp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{390E2568-57B7-4D17-91E5-C29336368CCF}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Example</RootNamespace>
|
||||
<AssemblyName>example1</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
||||
<DefineConstants>DEBUG;UBUNTU</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<DefineConstants>UBUNTU</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
|
||||
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net35\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="notify-sharp, Version=0.4.0.0, Culture=neutral, PublicKeyToken=2df29c54e245917a">
|
||||
<Private>False</Private>
|
||||
<Package>notify-sharp</Package>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="AudioStreamer.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="TextMessage.cs" />
|
||||
<Compile Include="NotificationMessage.cs" />
|
||||
<Compile Include="Notifier.cs" />
|
||||
<Compile Include="BinaryMessage.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
||||
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
||||
<Name>websocket-sharp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -1,24 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace Example1
|
||||
{
|
||||
internal class NotificationMessage
|
||||
{
|
||||
public string Body {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string Icon {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string Summary {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return String.Format ("{0}: {1}", Summary, Body);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
|
||||
namespace Example1
|
||||
{
|
||||
internal class NotificationMessage
|
||||
{
|
||||
public string Body {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string Icon {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string Summary {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return String.Format ("{0}: {1}", Summary, Body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,81 +1,81 @@
|
||||
#if UBUNTU
|
||||
using Notifications;
|
||||
#endif
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace Example1
|
||||
{
|
||||
internal class Notifier : IDisposable
|
||||
{
|
||||
private volatile bool _enabled;
|
||||
private ManualResetEvent _exited;
|
||||
private Queue<NotificationMessage> _queue;
|
||||
private object _sync;
|
||||
|
||||
public Notifier ()
|
||||
{
|
||||
_enabled = true;
|
||||
_exited = new ManualResetEvent (false);
|
||||
_queue = new Queue<NotificationMessage> ();
|
||||
_sync = ((ICollection) _queue).SyncRoot;
|
||||
|
||||
ThreadPool.QueueUserWorkItem (
|
||||
state => {
|
||||
while (_enabled || Count > 0) {
|
||||
var msg = dequeue ();
|
||||
if (msg != null) {
|
||||
#if UBUNTU
|
||||
var nf = new Notification (msg.Summary, msg.Body, msg.Icon);
|
||||
nf.AddHint ("append", "allowed");
|
||||
nf.Show ();
|
||||
#else
|
||||
Console.WriteLine (msg);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
Thread.Sleep (500);
|
||||
}
|
||||
}
|
||||
|
||||
_exited.Set ();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public int Count {
|
||||
get {
|
||||
lock (_sync)
|
||||
return _queue.Count;
|
||||
}
|
||||
}
|
||||
|
||||
private NotificationMessage dequeue ()
|
||||
{
|
||||
lock (_sync)
|
||||
return _queue.Count > 0 ? _queue.Dequeue () : null;
|
||||
}
|
||||
|
||||
public void Close ()
|
||||
{
|
||||
_enabled = false;
|
||||
_exited.WaitOne ();
|
||||
_exited.Close ();
|
||||
}
|
||||
|
||||
public void Notify (NotificationMessage message)
|
||||
{
|
||||
lock (_sync) {
|
||||
if (_enabled)
|
||||
_queue.Enqueue (message);
|
||||
}
|
||||
}
|
||||
|
||||
void IDisposable.Dispose ()
|
||||
{
|
||||
Close ();
|
||||
}
|
||||
}
|
||||
}
|
||||
#if UBUNTU
|
||||
using Notifications;
|
||||
#endif
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace Example1
|
||||
{
|
||||
internal class Notifier : IDisposable
|
||||
{
|
||||
private volatile bool _enabled;
|
||||
private ManualResetEvent _exited;
|
||||
private Queue<NotificationMessage> _queue;
|
||||
private object _sync;
|
||||
|
||||
public Notifier ()
|
||||
{
|
||||
_enabled = true;
|
||||
_exited = new ManualResetEvent (false);
|
||||
_queue = new Queue<NotificationMessage> ();
|
||||
_sync = ((ICollection) _queue).SyncRoot;
|
||||
|
||||
ThreadPool.QueueUserWorkItem (
|
||||
state => {
|
||||
while (_enabled || Count > 0) {
|
||||
var msg = dequeue ();
|
||||
if (msg != null) {
|
||||
#if UBUNTU
|
||||
var nf = new Notification (msg.Summary, msg.Body, msg.Icon);
|
||||
nf.AddHint ("append", "allowed");
|
||||
nf.Show ();
|
||||
#else
|
||||
Console.WriteLine (msg);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
Thread.Sleep (500);
|
||||
}
|
||||
}
|
||||
|
||||
_exited.Set ();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public int Count {
|
||||
get {
|
||||
lock (_sync)
|
||||
return _queue.Count;
|
||||
}
|
||||
}
|
||||
|
||||
private NotificationMessage dequeue ()
|
||||
{
|
||||
lock (_sync)
|
||||
return _queue.Count > 0 ? _queue.Dequeue () : null;
|
||||
}
|
||||
|
||||
public void Close ()
|
||||
{
|
||||
_enabled = false;
|
||||
_exited.WaitOne ();
|
||||
_exited.Close ();
|
||||
}
|
||||
|
||||
public void Notify (NotificationMessage message)
|
||||
{
|
||||
lock (_sync) {
|
||||
if (_enabled)
|
||||
_queue.Enqueue (message);
|
||||
}
|
||||
}
|
||||
|
||||
void IDisposable.Dispose ()
|
||||
{
|
||||
Close ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,37 +1,37 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Example1
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main (string[] args)
|
||||
{
|
||||
// The AudioStreamer class provides a client (chat) for AudioStreamer
|
||||
// (https://github.com/agektmr/AudioStreamer).
|
||||
|
||||
using (var streamer = new AudioStreamer ("ws://localhost:3000/socket"))
|
||||
{
|
||||
string name;
|
||||
do {
|
||||
Console.Write ("Input your name> ");
|
||||
name = Console.ReadLine ();
|
||||
}
|
||||
while (name.Length == 0);
|
||||
|
||||
streamer.Connect (name);
|
||||
|
||||
Console.WriteLine ("\nType 'exit' to exit.\n");
|
||||
while (true) {
|
||||
Thread.Sleep (1000);
|
||||
Console.Write ("> ");
|
||||
var msg = Console.ReadLine ();
|
||||
if (msg == "exit")
|
||||
break;
|
||||
|
||||
streamer.Write (msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Example1
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main (string[] args)
|
||||
{
|
||||
// The AudioStreamer class provides a client (chat) for AudioStreamer
|
||||
// (https://github.com/agektmr/AudioStreamer).
|
||||
|
||||
using (var streamer = new AudioStreamer ("ws://localhost:3000/socket"))
|
||||
{
|
||||
string name;
|
||||
do {
|
||||
Console.Write ("Input your name> ");
|
||||
name = Console.ReadLine ();
|
||||
}
|
||||
while (name.Length == 0);
|
||||
|
||||
streamer.Connect (name);
|
||||
|
||||
Console.WriteLine ("\nType 'exit' to exit.\n");
|
||||
while (true) {
|
||||
Thread.Sleep (1000);
|
||||
Console.Write ("> ");
|
||||
var msg = Console.ReadLine ();
|
||||
if (msg == "exit")
|
||||
break;
|
||||
|
||||
streamer.Write (msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,33 +1,33 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace Example1
|
||||
{
|
||||
internal class TextMessage
|
||||
{
|
||||
[JsonProperty ("user_id")]
|
||||
public uint? UserID {
|
||||
get; set;
|
||||
}
|
||||
|
||||
[JsonProperty ("name")]
|
||||
public string Name {
|
||||
get; set;
|
||||
}
|
||||
|
||||
[JsonProperty ("type")]
|
||||
public string Type {
|
||||
get; set;
|
||||
}
|
||||
|
||||
[JsonProperty ("message")]
|
||||
public string Message {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return JsonConvert.SerializeObject (this);
|
||||
}
|
||||
}
|
||||
}
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace Example1
|
||||
{
|
||||
internal class TextMessage
|
||||
{
|
||||
[JsonProperty ("user_id")]
|
||||
public uint? UserID {
|
||||
get; set;
|
||||
}
|
||||
|
||||
[JsonProperty ("name")]
|
||||
public string Name {
|
||||
get; set;
|
||||
}
|
||||
|
||||
[JsonProperty ("type")]
|
||||
public string Type {
|
||||
get; set;
|
||||
}
|
||||
|
||||
[JsonProperty ("message")]
|
||||
public string Message {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
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"?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="CertFilePassword" value="password"/>
|
||||
<add key="ServerCertFile" value="/path/to/cert.pfx"/>
|
||||
</appSettings>
|
||||
</configuration>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="CertFilePassword" value="password"/>
|
||||
<add key="ServerCertFile" value="/path/to/cert.pfx"/>
|
||||
</appSettings>
|
||||
</configuration>
|
||||
|
||||
@ -1,26 +1,26 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("Example2")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("sta.blockhead")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("Example2")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("sta.blockhead")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
|
||||
@ -1,50 +1,50 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Server;
|
||||
|
||||
namespace Example2
|
||||
{
|
||||
public class Chat : WebSocketBehavior
|
||||
{
|
||||
private string _name;
|
||||
private static int _number = 0;
|
||||
private string _prefix;
|
||||
|
||||
public Chat ()
|
||||
: this (null)
|
||||
{
|
||||
}
|
||||
|
||||
public Chat (string prefix)
|
||||
{
|
||||
_prefix = !prefix.IsNullOrEmpty () ? prefix : "anon#";
|
||||
}
|
||||
|
||||
private string getName ()
|
||||
{
|
||||
var name = Context.QueryString["name"];
|
||||
return !name.IsNullOrEmpty () ? name : _prefix + getNumber ();
|
||||
}
|
||||
|
||||
private static int getNumber ()
|
||||
{
|
||||
return Interlocked.Increment (ref _number);
|
||||
}
|
||||
|
||||
protected override void OnClose (CloseEventArgs e)
|
||||
{
|
||||
Sessions.Broadcast (String.Format ("{0} got logged off...", _name));
|
||||
}
|
||||
|
||||
protected override void OnMessage (MessageEventArgs e)
|
||||
{
|
||||
Sessions.Broadcast (String.Format ("{0}: {1}", _name, e.Data));
|
||||
}
|
||||
|
||||
protected override void OnOpen ()
|
||||
{
|
||||
_name = getName ();
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Threading;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Server;
|
||||
|
||||
namespace Example2
|
||||
{
|
||||
public class Chat : WebSocketBehavior
|
||||
{
|
||||
private string _name;
|
||||
private static int _number = 0;
|
||||
private string _prefix;
|
||||
|
||||
public Chat ()
|
||||
: this (null)
|
||||
{
|
||||
}
|
||||
|
||||
public Chat (string prefix)
|
||||
{
|
||||
_prefix = !prefix.IsNullOrEmpty () ? prefix : "anon#";
|
||||
}
|
||||
|
||||
private string getName ()
|
||||
{
|
||||
var name = Context.QueryString["name"];
|
||||
return !name.IsNullOrEmpty () ? name : _prefix + getNumber ();
|
||||
}
|
||||
|
||||
private static int getNumber ()
|
||||
{
|
||||
return Interlocked.Increment (ref _number);
|
||||
}
|
||||
|
||||
protected override void OnClose (CloseEventArgs e)
|
||||
{
|
||||
Sessions.Broadcast (String.Format ("{0} got logged off...", _name));
|
||||
}
|
||||
|
||||
protected override void OnMessage (MessageEventArgs e)
|
||||
{
|
||||
Sessions.Broadcast (String.Format ("{0}: {1}", _name, e.Data));
|
||||
}
|
||||
|
||||
protected override void OnOpen ()
|
||||
{
|
||||
_name = getName ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
using System;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Server;
|
||||
|
||||
namespace Example2
|
||||
{
|
||||
public class Echo : WebSocketBehavior
|
||||
{
|
||||
protected override void OnMessage (MessageEventArgs e)
|
||||
{
|
||||
var name = Context.QueryString["name"];
|
||||
Send (!name.IsNullOrEmpty () ? String.Format ("\"{0}\" to {1}", e.Data, name) : e.Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Server;
|
||||
|
||||
namespace Example2
|
||||
{
|
||||
public class Echo : WebSocketBehavior
|
||||
{
|
||||
protected override void OnMessage (MessageEventArgs e)
|
||||
{
|
||||
var name = Context.QueryString["name"];
|
||||
Send (!name.IsNullOrEmpty () ? String.Format ("\"{0}\" to {1}", e.Data, name) : e.Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,70 +1,75 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{B81A24C8-25BB-42B2-AF99-1E1EACCE74C7}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Example2</RootNamespace>
|
||||
<AssemblyName>example2</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Echo.cs" />
|
||||
<Compile Include="Chat.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
||||
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
||||
<Name>websocket-sharp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{B81A24C8-25BB-42B2-AF99-1E1EACCE74C7}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Example2</RootNamespace>
|
||||
<AssemblyName>example2</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
|
||||
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net35\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Echo.cs" />
|
||||
<Compile Include="Chat.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
||||
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
||||
<Name>websocket-sharp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -1,135 +1,135 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Net;
|
||||
using WebSocketSharp.Server;
|
||||
|
||||
namespace Example2
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main (string[] args)
|
||||
{
|
||||
// Create a new instance of the WebSocketServer class.
|
||||
//
|
||||
// If you would like to provide the secure connection, you should
|
||||
// create a new instance with the 'secure' parameter set to true,
|
||||
// or a wss scheme WebSocket URL.
|
||||
|
||||
var wssv = new WebSocketServer (4649);
|
||||
//var wssv = new WebSocketServer (5963, true);
|
||||
|
||||
//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.IPv6Any, 4649);
|
||||
//var wssv = new WebSocketServer (System.Net.IPAddress.IPv6Any, 5963, true);
|
||||
|
||||
//var wssv = new WebSocketServer ("ws://0.0.0.0:4649");
|
||||
//var wssv = new WebSocketServer ("wss://0.0.0.0:5963");
|
||||
|
||||
//var wssv = new WebSocketServer ("ws://[::0]:4649");
|
||||
//var wssv = new WebSocketServer ("wss://[::0]:5963");
|
||||
|
||||
//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.IPv6Loopback, 4649);
|
||||
//var wssv = new WebSocketServer (System.Net.IPAddress.IPv6Loopback, 5963, true);
|
||||
|
||||
//var wssv = new WebSocketServer ("ws://localhost:4649");
|
||||
//var wssv = new WebSocketServer ("wss://localhost:5963");
|
||||
|
||||
//var wssv = new WebSocketServer ("ws://127.0.0.1:4649");
|
||||
//var wssv = new WebSocketServer ("wss://127.0.0.1:5963");
|
||||
|
||||
//var wssv = new WebSocketServer ("ws://[::1]:4649");
|
||||
//var wssv = new WebSocketServer ("wss://[::1]:5963");
|
||||
#if DEBUG
|
||||
// To change the logging level.
|
||||
wssv.Log.Level = LogLevel.Trace;
|
||||
|
||||
// To change the wait time for the response to the WebSocket Ping or Close.
|
||||
//wssv.WaitTime = TimeSpan.FromSeconds (2);
|
||||
|
||||
// Not to remove the inactive sessions periodically.
|
||||
//wssv.KeepClean = false;
|
||||
#endif
|
||||
// To provide the secure connection.
|
||||
/*
|
||||
var cert = ConfigurationManager.AppSettings["ServerCertFile"];
|
||||
var passwd = ConfigurationManager.AppSettings["CertFilePassword"];
|
||||
wssv.SslConfiguration.ServerCertificate = new X509Certificate2 (cert, passwd);
|
||||
*/
|
||||
|
||||
// To provide the HTTP Authentication (Basic/Digest).
|
||||
/*
|
||||
wssv.AuthenticationSchemes = AuthenticationSchemes.Basic;
|
||||
wssv.Realm = "WebSocket Test";
|
||||
wssv.UserCredentialsFinder = id => {
|
||||
var name = id.Name;
|
||||
|
||||
// Return user name, password, and roles.
|
||||
return name == "nobita"
|
||||
? new NetworkCredential (name, "password", "gunfighter")
|
||||
: null; // If the user credentials aren't found.
|
||||
};
|
||||
*/
|
||||
|
||||
// To resolve to wait for socket in TIME_WAIT state.
|
||||
//wssv.ReuseAddress = true;
|
||||
|
||||
// Add the WebSocket services.
|
||||
wssv.AddWebSocketService<Echo> ("/Echo");
|
||||
wssv.AddWebSocketService<Chat> ("/Chat");
|
||||
|
||||
// Add the WebSocket service with initializing.
|
||||
/*
|
||||
wssv.AddWebSocketService<Chat> (
|
||||
"/Chat",
|
||||
() =>
|
||||
new Chat ("Anon#") {
|
||||
// To send the Sec-WebSocket-Protocol header that has a subprotocol name.
|
||||
Protocol = "chat",
|
||||
// To ignore the Sec-WebSocket-Extensions header.
|
||||
IgnoreExtensions = true,
|
||||
// To emit a WebSocket.OnMessage event when receives a ping.
|
||||
EmitOnPing = true,
|
||||
// To validate the Origin header.
|
||||
OriginValidator = val => {
|
||||
// Check the value of the Origin header, and return true if valid.
|
||||
Uri origin;
|
||||
return !val.IsNullOrEmpty ()
|
||||
&& Uri.TryCreate (val, UriKind.Absolute, out origin)
|
||||
&& origin.Host == "localhost";
|
||||
},
|
||||
// To validate the cookies.
|
||||
CookiesValidator = (req, res) => {
|
||||
// Check the cookies in 'req', and set the cookies to send to
|
||||
// the client with 'res' if necessary.
|
||||
foreach (Cookie cookie in req) {
|
||||
cookie.Expired = true;
|
||||
res.Add (cookie);
|
||||
}
|
||||
|
||||
return true; // If valid.
|
||||
}
|
||||
}
|
||||
);
|
||||
*/
|
||||
|
||||
wssv.Start ();
|
||||
if (wssv.IsListening) {
|
||||
Console.WriteLine ("Listening on port {0}, and providing WebSocket services:", wssv.Port);
|
||||
foreach (var path in wssv.WebSocketServices.Paths)
|
||||
Console.WriteLine ("- {0}", path);
|
||||
}
|
||||
|
||||
Console.WriteLine ("\nPress Enter key to stop the server...");
|
||||
Console.ReadLine ();
|
||||
|
||||
wssv.Stop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Net;
|
||||
using WebSocketSharp.Server;
|
||||
|
||||
namespace Example2
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main (string[] args)
|
||||
{
|
||||
// Create a new instance of the WebSocketServer class.
|
||||
//
|
||||
// If you would like to provide the secure connection, you should
|
||||
// create a new instance with the 'secure' parameter set to true,
|
||||
// or a wss scheme WebSocket URL.
|
||||
|
||||
var wssv = new WebSocketServer (4649);
|
||||
//var wssv = new WebSocketServer (5963, true);
|
||||
|
||||
//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.IPv6Any, 4649);
|
||||
//var wssv = new WebSocketServer (System.Net.IPAddress.IPv6Any, 5963, true);
|
||||
|
||||
//var wssv = new WebSocketServer ("ws://0.0.0.0:4649");
|
||||
//var wssv = new WebSocketServer ("wss://0.0.0.0:5963");
|
||||
|
||||
//var wssv = new WebSocketServer ("ws://[::0]:4649");
|
||||
//var wssv = new WebSocketServer ("wss://[::0]:5963");
|
||||
|
||||
//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.IPv6Loopback, 4649);
|
||||
//var wssv = new WebSocketServer (System.Net.IPAddress.IPv6Loopback, 5963, true);
|
||||
|
||||
//var wssv = new WebSocketServer ("ws://localhost:4649");
|
||||
//var wssv = new WebSocketServer ("wss://localhost:5963");
|
||||
|
||||
//var wssv = new WebSocketServer ("ws://127.0.0.1:4649");
|
||||
//var wssv = new WebSocketServer ("wss://127.0.0.1:5963");
|
||||
|
||||
//var wssv = new WebSocketServer ("ws://[::1]:4649");
|
||||
//var wssv = new WebSocketServer ("wss://[::1]:5963");
|
||||
#if DEBUG
|
||||
// To change the logging level.
|
||||
wssv.Log.Level = LogLevel.Trace;
|
||||
|
||||
// To change the wait time for the response to the WebSocket Ping or Close.
|
||||
//wssv.WaitTime = TimeSpan.FromSeconds (2);
|
||||
|
||||
// Not to remove the inactive sessions periodically.
|
||||
//wssv.KeepClean = false;
|
||||
#endif
|
||||
// To provide the secure connection.
|
||||
/*
|
||||
var cert = ConfigurationManager.AppSettings["ServerCertFile"];
|
||||
var passwd = ConfigurationManager.AppSettings["CertFilePassword"];
|
||||
wssv.SslConfiguration.ServerCertificate = new X509Certificate2 (cert, passwd);
|
||||
*/
|
||||
|
||||
// To provide the HTTP Authentication (Basic/Digest).
|
||||
/*
|
||||
wssv.AuthenticationSchemes = AuthenticationSchemes.Basic;
|
||||
wssv.Realm = "WebSocket Test";
|
||||
wssv.UserCredentialsFinder = id => {
|
||||
var name = id.Name;
|
||||
|
||||
// Return user name, password, and roles.
|
||||
return name == "nobita"
|
||||
? new NetworkCredential (name, "password", "gunfighter")
|
||||
: null; // If the user credentials aren't found.
|
||||
};
|
||||
*/
|
||||
|
||||
// To resolve to wait for socket in TIME_WAIT state.
|
||||
//wssv.ReuseAddress = true;
|
||||
|
||||
// Add the WebSocket services.
|
||||
wssv.AddWebSocketService<Echo> ("/Echo");
|
||||
wssv.AddWebSocketService<Chat> ("/Chat");
|
||||
|
||||
// Add the WebSocket service with initializing.
|
||||
/*
|
||||
wssv.AddWebSocketService<Chat> (
|
||||
"/Chat",
|
||||
() =>
|
||||
new Chat ("Anon#") {
|
||||
// To send the Sec-WebSocket-Protocol header that has a subprotocol name.
|
||||
Protocol = "chat",
|
||||
// To ignore the Sec-WebSocket-Extensions header.
|
||||
IgnoreExtensions = true,
|
||||
// To emit a WebSocket.OnMessage event when receives a ping.
|
||||
EmitOnPing = true,
|
||||
// To validate the Origin header.
|
||||
OriginValidator = val => {
|
||||
// Check the value of the Origin header, and return true if valid.
|
||||
Uri origin;
|
||||
return !val.IsNullOrEmpty ()
|
||||
&& Uri.TryCreate (val, UriKind.Absolute, out origin)
|
||||
&& origin.Host == "localhost";
|
||||
},
|
||||
// To validate the cookies.
|
||||
CookiesValidator = (req, res) => {
|
||||
// Check the cookies in 'req', and set the cookies to send to
|
||||
// the client with 'res' if necessary.
|
||||
foreach (Cookie cookie in req) {
|
||||
cookie.Expired = true;
|
||||
res.Add (cookie);
|
||||
}
|
||||
|
||||
return true; // If valid.
|
||||
}
|
||||
}
|
||||
);
|
||||
*/
|
||||
|
||||
wssv.Start ();
|
||||
if (wssv.IsListening) {
|
||||
Console.WriteLine ("Listening on port {0}, and providing WebSocket services:", wssv.Port);
|
||||
foreach (var path in wssv.WebSocketServices.Paths)
|
||||
Console.WriteLine ("- {0}", path);
|
||||
}
|
||||
|
||||
Console.WriteLine ("\nPress Enter key to stop the server...");
|
||||
Console.ReadLine ();
|
||||
|
||||
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"?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="CertFilePassword" value="password"/>
|
||||
<add key="DocumentRootPath" value="../../Public"/>
|
||||
<add key="ServerCertFile" value="/path/to/cert.pfx"/>
|
||||
</appSettings>
|
||||
</configuration>
|
||||
<?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>
|
||||
|
||||
@ -1,26 +1,26 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("Example3")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("sta.blockhead")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("Example3")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("sta.blockhead")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
|
||||
@ -1,50 +1,50 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Server;
|
||||
|
||||
namespace Example3
|
||||
{
|
||||
public class Chat : WebSocketBehavior
|
||||
{
|
||||
private string _name;
|
||||
private static int _number = 0;
|
||||
private string _prefix;
|
||||
|
||||
public Chat ()
|
||||
: this (null)
|
||||
{
|
||||
}
|
||||
|
||||
public Chat (string prefix)
|
||||
{
|
||||
_prefix = !prefix.IsNullOrEmpty () ? prefix : "anon#";
|
||||
}
|
||||
|
||||
private string getName ()
|
||||
{
|
||||
var name = Context.QueryString["name"];
|
||||
return !name.IsNullOrEmpty () ? name : _prefix + getNumber ();
|
||||
}
|
||||
|
||||
private static int getNumber ()
|
||||
{
|
||||
return Interlocked.Increment (ref _number);
|
||||
}
|
||||
|
||||
protected override void OnClose (CloseEventArgs e)
|
||||
{
|
||||
Sessions.Broadcast (String.Format ("{0} got logged off...", _name));
|
||||
}
|
||||
|
||||
protected override void OnMessage (MessageEventArgs e)
|
||||
{
|
||||
Sessions.Broadcast (String.Format ("{0}: {1}", _name, e.Data));
|
||||
}
|
||||
|
||||
protected override void OnOpen ()
|
||||
{
|
||||
_name = getName ();
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Threading;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Server;
|
||||
|
||||
namespace Example3
|
||||
{
|
||||
public class Chat : WebSocketBehavior
|
||||
{
|
||||
private string _name;
|
||||
private static int _number = 0;
|
||||
private string _prefix;
|
||||
|
||||
public Chat ()
|
||||
: this (null)
|
||||
{
|
||||
}
|
||||
|
||||
public Chat (string prefix)
|
||||
{
|
||||
_prefix = !prefix.IsNullOrEmpty () ? prefix : "anon#";
|
||||
}
|
||||
|
||||
private string getName ()
|
||||
{
|
||||
var name = Context.QueryString["name"];
|
||||
return !name.IsNullOrEmpty () ? name : _prefix + getNumber ();
|
||||
}
|
||||
|
||||
private static int getNumber ()
|
||||
{
|
||||
return Interlocked.Increment (ref _number);
|
||||
}
|
||||
|
||||
protected override void OnClose (CloseEventArgs e)
|
||||
{
|
||||
Sessions.Broadcast (String.Format ("{0} got logged off...", _name));
|
||||
}
|
||||
|
||||
protected override void OnMessage (MessageEventArgs e)
|
||||
{
|
||||
Sessions.Broadcast (String.Format ("{0}: {1}", _name, e.Data));
|
||||
}
|
||||
|
||||
protected override void OnOpen ()
|
||||
{
|
||||
_name = getName ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
using System;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Server;
|
||||
|
||||
namespace Example3
|
||||
{
|
||||
public class Echo : WebSocketBehavior
|
||||
{
|
||||
protected override void OnMessage (MessageEventArgs e)
|
||||
{
|
||||
var name = Context.QueryString["name"];
|
||||
Send (!name.IsNullOrEmpty () ? String.Format ("\"{0}\" to {1}", e.Data, name) : e.Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Server;
|
||||
|
||||
namespace Example3
|
||||
{
|
||||
public class Echo : WebSocketBehavior
|
||||
{
|
||||
protected override void OnMessage (MessageEventArgs e)
|
||||
{
|
||||
var name = Context.QueryString["name"];
|
||||
Send (!name.IsNullOrEmpty () ? String.Format ("\"{0}\" to {1}", e.Data, name) : e.Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,76 +1,81 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{C648BA25-77E5-4A40-A97F-D0AA37B9FB26}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Example3</RootNamespace>
|
||||
<AssemblyName>example3</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Chat.cs" />
|
||||
<Compile Include="Echo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
||||
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
||||
<Name>websocket-sharp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="Public\index.html" />
|
||||
<None Include="Public\Js\echotest.js" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Public\" />
|
||||
<Folder Include="Public\Js\" />
|
||||
</ItemGroup>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{C648BA25-77E5-4A40-A97F-D0AA37B9FB26}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Example3</RootNamespace>
|
||||
<AssemblyName>example3</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_Ubuntu|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_Ubuntu|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release_Ubuntu</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
|
||||
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net35\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Chat.cs" />
|
||||
<Compile Include="Echo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\websocket-sharp\websocket-sharp.csproj">
|
||||
<Project>{B357BAC7-529E-4D81-A0D2-71041B19C8DE}</Project>
|
||||
<Name>websocket-sharp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="Public\index.html" />
|
||||
<None Include="Public\Js\echotest.js" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Public\" />
|
||||
<Folder Include="Public\Js\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -1,167 +1,167 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Net;
|
||||
using WebSocketSharp.Server;
|
||||
|
||||
namespace Example3
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main (string[] args)
|
||||
{
|
||||
// Create a new instance of the HttpServer class.
|
||||
//
|
||||
// If you would like to provide the secure connection, you should
|
||||
// create a new instance with the 'secure' parameter set to true,
|
||||
// or an https scheme HTTP URL.
|
||||
|
||||
var httpsv = new HttpServer (4649);
|
||||
//var httpsv = new HttpServer (5963, true);
|
||||
|
||||
//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.IPv6Any, 4649);
|
||||
//var httpsv = new HttpServer (System.Net.IPAddress.IPv6Any, 5963, true);
|
||||
|
||||
//var httpsv = new HttpServer ("http://0.0.0.0:4649");
|
||||
//var httpsv = new HttpServer ("https://0.0.0.0:5963");
|
||||
|
||||
//var httpsv = new HttpServer ("http://[::0]:4649");
|
||||
//var httpsv = new HttpServer ("https://[::0]:5963");
|
||||
|
||||
//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.IPv6Loopback, 4649);
|
||||
//var httpsv = new HttpServer (System.Net.IPAddress.IPv6Loopback, 5963, true);
|
||||
|
||||
//var httpsv = new HttpServer ("http://localhost:4649");
|
||||
//var httpsv = new HttpServer ("https://localhost:5963");
|
||||
|
||||
//var httpsv = new HttpServer ("http://127.0.0.1:4649");
|
||||
//var httpsv = new HttpServer ("https://127.0.0.1:5963");
|
||||
|
||||
//var httpsv = new HttpServer ("http://[::1]:4649");
|
||||
//var httpsv = new HttpServer ("https://[::1]:5963");
|
||||
#if DEBUG
|
||||
// To change the logging level.
|
||||
httpsv.Log.Level = LogLevel.Trace;
|
||||
|
||||
// To change the wait time for the response to the WebSocket Ping or Close.
|
||||
//httpsv.WaitTime = TimeSpan.FromSeconds (2);
|
||||
|
||||
// Not to remove the inactive WebSocket sessions periodically.
|
||||
//httpsv.KeepClean = false;
|
||||
#endif
|
||||
// To provide the secure connection.
|
||||
/*
|
||||
var cert = ConfigurationManager.AppSettings["ServerCertFile"];
|
||||
var passwd = ConfigurationManager.AppSettings["CertFilePassword"];
|
||||
httpsv.SslConfiguration.ServerCertificate = new X509Certificate2 (cert, passwd);
|
||||
*/
|
||||
|
||||
// To provide the HTTP Authentication (Basic/Digest).
|
||||
/*
|
||||
httpsv.AuthenticationSchemes = AuthenticationSchemes.Basic;
|
||||
httpsv.Realm = "WebSocket Test";
|
||||
httpsv.UserCredentialsFinder = id => {
|
||||
var name = id.Name;
|
||||
|
||||
// Return user name, password, and roles.
|
||||
return name == "nobita"
|
||||
? new NetworkCredential (name, "password", "gunfighter")
|
||||
: null; // If the user credentials aren't found.
|
||||
};
|
||||
*/
|
||||
|
||||
// To resolve to wait for socket in TIME_WAIT state.
|
||||
//httpsv.ReuseAddress = true;
|
||||
|
||||
// Set the document root path.
|
||||
httpsv.DocumentRootPath = ConfigurationManager.AppSettings["DocumentRootPath"];
|
||||
|
||||
// Set the HTTP GET request event.
|
||||
httpsv.OnGet += (sender, e) => {
|
||||
var req = e.Request;
|
||||
var res = e.Response;
|
||||
|
||||
var path = req.RawUrl;
|
||||
if (path == "/")
|
||||
path += "index.html";
|
||||
|
||||
byte[] contents;
|
||||
if (!e.TryReadFile (path, out contents)) {
|
||||
res.StatusCode = (int) HttpStatusCode.NotFound;
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.EndsWith (".html")) {
|
||||
res.ContentType = "text/html";
|
||||
res.ContentEncoding = Encoding.UTF8;
|
||||
}
|
||||
else if (path.EndsWith (".js")) {
|
||||
res.ContentType = "application/javascript";
|
||||
res.ContentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
res.ContentLength64 = contents.LongLength;
|
||||
res.Close (contents, true);
|
||||
};
|
||||
|
||||
// Add the WebSocket services.
|
||||
httpsv.AddWebSocketService<Echo> ("/Echo");
|
||||
httpsv.AddWebSocketService<Chat> ("/Chat");
|
||||
|
||||
// Add the WebSocket service with initializing.
|
||||
/*
|
||||
httpsv.AddWebSocketService<Chat> (
|
||||
"/Chat",
|
||||
() =>
|
||||
new Chat ("Anon#") {
|
||||
// To send the Sec-WebSocket-Protocol header that has a subprotocol name.
|
||||
Protocol = "chat",
|
||||
// To ignore the Sec-WebSocket-Extensions header.
|
||||
IgnoreExtensions = true,
|
||||
// To emit a WebSocket.OnMessage event when receives a ping.
|
||||
EmitOnPing = true,
|
||||
// To validate the Origin header.
|
||||
OriginValidator = val => {
|
||||
// Check the value of the Origin header, and return true if valid.
|
||||
Uri origin;
|
||||
return !val.IsNullOrEmpty ()
|
||||
&& Uri.TryCreate (val, UriKind.Absolute, out origin)
|
||||
&& origin.Host == "localhost";
|
||||
},
|
||||
// To validate the cookies.
|
||||
CookiesValidator = (req, res) => {
|
||||
// Check the cookies in 'req', and set the cookies to send to
|
||||
// the client with 'res' if necessary.
|
||||
foreach (Cookie cookie in req) {
|
||||
cookie.Expired = true;
|
||||
res.Add (cookie);
|
||||
}
|
||||
|
||||
return true; // If valid.
|
||||
}
|
||||
}
|
||||
);
|
||||
*/
|
||||
|
||||
httpsv.Start ();
|
||||
if (httpsv.IsListening) {
|
||||
Console.WriteLine ("Listening on port {0}, and providing WebSocket services:", httpsv.Port);
|
||||
foreach (var path in httpsv.WebSocketServices.Paths)
|
||||
Console.WriteLine ("- {0}", path);
|
||||
}
|
||||
|
||||
Console.WriteLine ("\nPress Enter key to stop the server...");
|
||||
Console.ReadLine ();
|
||||
|
||||
httpsv.Stop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Net;
|
||||
using WebSocketSharp.Server;
|
||||
|
||||
namespace Example3
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main (string[] args)
|
||||
{
|
||||
// Create a new instance of the HttpServer class.
|
||||
//
|
||||
// If you would like to provide the secure connection, you should
|
||||
// create a new instance with the 'secure' parameter set to true,
|
||||
// or an https scheme HTTP URL.
|
||||
|
||||
var httpsv = new HttpServer (12346);
|
||||
//var httpsv = new HttpServer (5963, true);
|
||||
|
||||
//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.IPv6Any, 4649);
|
||||
//var httpsv = new HttpServer (System.Net.IPAddress.IPv6Any, 5963, true);
|
||||
|
||||
//var httpsv = new HttpServer ("http://0.0.0.0:4649");
|
||||
//var httpsv = new HttpServer ("https://0.0.0.0:5963");
|
||||
|
||||
//var httpsv = new HttpServer ("http://[::0]:4649");
|
||||
//var httpsv = new HttpServer ("https://[::0]:5963");
|
||||
|
||||
//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.IPv6Loopback, 4649);
|
||||
//var httpsv = new HttpServer (System.Net.IPAddress.IPv6Loopback, 5963, true);
|
||||
|
||||
//var httpsv = new HttpServer ("http://localhost:4649");
|
||||
//var httpsv = new HttpServer ("https://localhost:5963");
|
||||
|
||||
//var httpsv = new HttpServer ("http://127.0.0.1:4649");
|
||||
//var httpsv = new HttpServer ("https://127.0.0.1:5963");
|
||||
|
||||
//var httpsv = new HttpServer ("http://[::1]:4649");
|
||||
//var httpsv = new HttpServer ("https://[::1]:5963");
|
||||
#if DEBUG
|
||||
// To change the logging level.
|
||||
httpsv.Log.Level = LogLevel.Trace;
|
||||
|
||||
// To change the wait time for the response to the WebSocket Ping or Close.
|
||||
//httpsv.WaitTime = TimeSpan.FromSeconds (2);
|
||||
|
||||
// Not to remove the inactive WebSocket sessions periodically.
|
||||
//httpsv.KeepClean = false;
|
||||
#endif
|
||||
// To provide the secure connection.
|
||||
/*
|
||||
var cert = ConfigurationManager.AppSettings["ServerCertFile"];
|
||||
var passwd = ConfigurationManager.AppSettings["CertFilePassword"];
|
||||
httpsv.SslConfiguration.ServerCertificate = new X509Certificate2 (cert, passwd);
|
||||
*/
|
||||
|
||||
// To provide the HTTP Authentication (Basic/Digest).
|
||||
/*
|
||||
httpsv.AuthenticationSchemes = AuthenticationSchemes.Basic;
|
||||
httpsv.Realm = "WebSocket Test";
|
||||
httpsv.UserCredentialsFinder = id => {
|
||||
var name = id.Name;
|
||||
|
||||
// Return user name, password, and roles.
|
||||
return name == "nobita"
|
||||
? new NetworkCredential (name, "password", "gunfighter")
|
||||
: null; // If the user credentials aren't found.
|
||||
};
|
||||
*/
|
||||
|
||||
// To resolve to wait for socket in TIME_WAIT state.
|
||||
//httpsv.ReuseAddress = true;
|
||||
|
||||
// Set the document root path.
|
||||
httpsv.DocumentRootPath = ConfigurationManager.AppSettings["DocumentRootPath"];
|
||||
|
||||
// Set the HTTP GET request event.
|
||||
httpsv.OnGet += (sender, e) => {
|
||||
var req = e.Request;
|
||||
var res = e.Response;
|
||||
|
||||
var path = req.RawUrl;
|
||||
if (path == "/")
|
||||
path += "index.html";
|
||||
|
||||
byte[] contents;
|
||||
if (!e.TryReadFile (path, out contents)) {
|
||||
res.StatusCode = (int) HttpStatusCode.NotFound;
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.EndsWith (".html")) {
|
||||
res.ContentType = "text/html";
|
||||
res.ContentEncoding = Encoding.UTF8;
|
||||
}
|
||||
else if (path.EndsWith (".js")) {
|
||||
res.ContentType = "application/javascript";
|
||||
res.ContentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
res.ContentLength64 = contents.LongLength;
|
||||
res.Close (contents, true);
|
||||
};
|
||||
|
||||
// Add the WebSocket services.
|
||||
httpsv.AddWebSocketService<Echo> ("/Echo");
|
||||
httpsv.AddWebSocketService<Chat> ("/Chat");
|
||||
|
||||
// Add the WebSocket service with initializing.
|
||||
/*
|
||||
httpsv.AddWebSocketService<Chat> (
|
||||
"/Chat",
|
||||
() =>
|
||||
new Chat ("Anon#") {
|
||||
// To send the Sec-WebSocket-Protocol header that has a subprotocol name.
|
||||
Protocol = "chat",
|
||||
// To ignore the Sec-WebSocket-Extensions header.
|
||||
IgnoreExtensions = true,
|
||||
// To emit a WebSocket.OnMessage event when receives a ping.
|
||||
EmitOnPing = true,
|
||||
// To validate the Origin header.
|
||||
OriginValidator = val => {
|
||||
// Check the value of the Origin header, and return true if valid.
|
||||
Uri origin;
|
||||
return !val.IsNullOrEmpty ()
|
||||
&& Uri.TryCreate (val, UriKind.Absolute, out origin)
|
||||
&& origin.Host == "localhost";
|
||||
},
|
||||
// To validate the cookies.
|
||||
CookiesValidator = (req, res) => {
|
||||
// Check the cookies in 'req', and set the cookies to send to
|
||||
// the client with 'res' if necessary.
|
||||
foreach (Cookie cookie in req) {
|
||||
cookie.Expired = true;
|
||||
res.Add (cookie);
|
||||
}
|
||||
|
||||
return true; // If valid.
|
||||
}
|
||||
}
|
||||
);
|
||||
*/
|
||||
|
||||
httpsv.Start ();
|
||||
if (httpsv.IsListening) {
|
||||
Console.WriteLine ("Listening on port {0}, and providing WebSocket services:", httpsv.Port);
|
||||
foreach (var path in httpsv.WebSocketServices.Paths)
|
||||
Console.WriteLine ("- {0}", path);
|
||||
}
|
||||
|
||||
Console.WriteLine ("\nPress Enter key to stop the server...");
|
||||
Console.ReadLine ();
|
||||
|
||||
httpsv.Stop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,68 +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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
@ -1,12 +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>
|
||||
<!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>
|
||||
|
||||
@ -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)
|
||||
|
||||
Copyright (c) 2010-2021 sta.blockhead
|
||||
|
||||
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.
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2010-2021 sta.blockhead
|
||||
|
||||
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.
|
||||
|
||||
@ -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.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("websocket-sharp")]
|
||||
[assembly: AssemblyDescription("A C# implementation of the WebSocket protocol client and server")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("websocket-sharp.dll")]
|
||||
[assembly: AssemblyCopyright("sta.blockhead")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("1.0.2.*")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("websocket-sharp")]
|
||||
[assembly: AssemblyDescription("A C# implementation of the WebSocket protocol client and server")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("websocket-sharp.dll")]
|
||||
[assembly: AssemblyCopyright("sta.blockhead")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("1.0.2.*")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
|
||||
@ -1,47 +1,47 @@
|
||||
#region License
|
||||
/*
|
||||
* ByteOrder.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the byte order.
|
||||
/// </summary>
|
||||
public enum ByteOrder
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies Little-endian.
|
||||
/// </summary>
|
||||
Little,
|
||||
/// <summary>
|
||||
/// Specifies Big-endian.
|
||||
/// </summary>
|
||||
Big
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* ByteOrder.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the byte order.
|
||||
/// </summary>
|
||||
public enum ByteOrder
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies Little-endian.
|
||||
/// </summary>
|
||||
Little,
|
||||
/// <summary>
|
||||
/// Specifies Big-endian.
|
||||
/// </summary>
|
||||
Big
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,113 +1,113 @@
|
||||
#region License
|
||||
/*
|
||||
* CloseEventArgs.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2019 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the event data for the <see cref="WebSocket.OnClose"/> event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// That event occurs when the WebSocket connection has been closed.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If you would like to get the reason for the connection close, you should
|
||||
/// access the <see cref="Code"/> or <see cref="Reason"/> property.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class CloseEventArgs : EventArgs
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private bool _clean;
|
||||
private PayloadData _payloadData;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal CloseEventArgs (PayloadData payloadData, bool clean)
|
||||
{
|
||||
_payloadData = payloadData;
|
||||
_clean = clean;
|
||||
}
|
||||
|
||||
internal CloseEventArgs (ushort code, string reason, bool clean)
|
||||
{
|
||||
_payloadData = new PayloadData (code, reason);
|
||||
_clean = clean;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the status code for the connection close.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ushort"/> that represents the status code for
|
||||
/// the connection close if present.
|
||||
/// </value>
|
||||
public ushort Code {
|
||||
get {
|
||||
return _payloadData.Code;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reason for the connection close.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string"/> that represents the reason for
|
||||
/// the connection close if present.
|
||||
/// </value>
|
||||
public string Reason {
|
||||
get {
|
||||
return _payloadData.Reason;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the connection has been closed cleanly.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if the connection has been closed cleanly; otherwise,
|
||||
/// <c>false</c>.
|
||||
/// </value>
|
||||
public bool WasClean {
|
||||
get {
|
||||
return _clean;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* CloseEventArgs.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2019 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the event data for the <see cref="WebSocket.OnClose"/> event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// That event occurs when the WebSocket connection has been closed.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If you would like to get the reason for the connection close, you should
|
||||
/// access the <see cref="Code"/> or <see cref="Reason"/> property.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class CloseEventArgs : EventArgs
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private bool _clean;
|
||||
private PayloadData _payloadData;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal CloseEventArgs (PayloadData payloadData, bool clean)
|
||||
{
|
||||
_payloadData = payloadData;
|
||||
_clean = clean;
|
||||
}
|
||||
|
||||
internal CloseEventArgs (ushort code, string reason, bool clean)
|
||||
{
|
||||
_payloadData = new PayloadData (code, reason);
|
||||
_clean = clean;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the status code for the connection close.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ushort"/> that represents the status code for
|
||||
/// the connection close if present.
|
||||
/// </value>
|
||||
public ushort Code {
|
||||
get {
|
||||
return _payloadData.Code;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reason for the connection close.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string"/> that represents the reason for
|
||||
/// the connection close if present.
|
||||
/// </value>
|
||||
public string Reason {
|
||||
get {
|
||||
return _payloadData.Reason;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the connection has been closed cleanly.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if the connection has been closed cleanly; otherwise,
|
||||
/// <c>false</c>.
|
||||
/// </value>
|
||||
public bool WasClean {
|
||||
get {
|
||||
return _clean;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,120 +1,120 @@
|
||||
#region License
|
||||
/*
|
||||
* CloseStatusCode.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2016 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates the status code for the WebSocket connection close.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The values of this enumeration are defined in
|
||||
/// <see href="http://tools.ietf.org/html/rfc6455#section-7.4">
|
||||
/// Section 7.4</see> of RFC 6455.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// "Reserved value" cannot be sent as a status code in
|
||||
/// closing handshake by an endpoint.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public enum CloseStatusCode : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1000. Indicates normal close.
|
||||
/// </summary>
|
||||
Normal = 1000,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1001. Indicates that an endpoint is
|
||||
/// going away.
|
||||
/// </summary>
|
||||
Away = 1001,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1002. Indicates that an endpoint is
|
||||
/// terminating the connection due to a protocol error.
|
||||
/// </summary>
|
||||
ProtocolError = 1002,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1003. Indicates that an endpoint is
|
||||
/// terminating the connection because it has received a type of
|
||||
/// data that it cannot accept.
|
||||
/// </summary>
|
||||
UnsupportedData = 1003,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1004. Still undefined. A Reserved value.
|
||||
/// </summary>
|
||||
Undefined = 1004,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1005. Indicates that no status code was
|
||||
/// actually present. A Reserved value.
|
||||
/// </summary>
|
||||
NoStatus = 1005,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1006. Indicates that the connection was
|
||||
/// closed abnormally. A Reserved value.
|
||||
/// </summary>
|
||||
Abnormal = 1006,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1007. Indicates that an endpoint is
|
||||
/// terminating the connection because it has received a message that
|
||||
/// contains data that is not consistent with the type of the message.
|
||||
/// </summary>
|
||||
InvalidData = 1007,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1008. Indicates that an endpoint is
|
||||
/// terminating the connection because it has received a message that
|
||||
/// violates its policy.
|
||||
/// </summary>
|
||||
PolicyViolation = 1008,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1009. Indicates that an endpoint is
|
||||
/// terminating the connection because it has received a message that
|
||||
/// is too big to process.
|
||||
/// </summary>
|
||||
TooBig = 1009,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1010. Indicates that a client is
|
||||
/// terminating the connection because it has expected the server to
|
||||
/// negotiate one or more extension, but the server did not return
|
||||
/// them in the handshake response.
|
||||
/// </summary>
|
||||
MandatoryExtension = 1010,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1011. Indicates that a server is
|
||||
/// terminating the connection because it has encountered an unexpected
|
||||
/// condition that prevented it from fulfilling the request.
|
||||
/// </summary>
|
||||
ServerError = 1011,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1015. Indicates that the connection was
|
||||
/// closed due to a failure to perform a TLS handshake. A Reserved value.
|
||||
/// </summary>
|
||||
TlsHandshakeFailure = 1015
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* CloseStatusCode.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2016 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates the status code for the WebSocket connection close.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The values of this enumeration are defined in
|
||||
/// <see href="http://tools.ietf.org/html/rfc6455#section-7.4">
|
||||
/// Section 7.4</see> of RFC 6455.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// "Reserved value" cannot be sent as a status code in
|
||||
/// closing handshake by an endpoint.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public enum CloseStatusCode : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1000. Indicates normal close.
|
||||
/// </summary>
|
||||
Normal = 1000,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1001. Indicates that an endpoint is
|
||||
/// going away.
|
||||
/// </summary>
|
||||
Away = 1001,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1002. Indicates that an endpoint is
|
||||
/// terminating the connection due to a protocol error.
|
||||
/// </summary>
|
||||
ProtocolError = 1002,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1003. Indicates that an endpoint is
|
||||
/// terminating the connection because it has received a type of
|
||||
/// data that it cannot accept.
|
||||
/// </summary>
|
||||
UnsupportedData = 1003,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1004. Still undefined. A Reserved value.
|
||||
/// </summary>
|
||||
Undefined = 1004,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1005. Indicates that no status code was
|
||||
/// actually present. A Reserved value.
|
||||
/// </summary>
|
||||
NoStatus = 1005,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1006. Indicates that the connection was
|
||||
/// closed abnormally. A Reserved value.
|
||||
/// </summary>
|
||||
Abnormal = 1006,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1007. Indicates that an endpoint is
|
||||
/// terminating the connection because it has received a message that
|
||||
/// contains data that is not consistent with the type of the message.
|
||||
/// </summary>
|
||||
InvalidData = 1007,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1008. Indicates that an endpoint is
|
||||
/// terminating the connection because it has received a message that
|
||||
/// violates its policy.
|
||||
/// </summary>
|
||||
PolicyViolation = 1008,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1009. Indicates that an endpoint is
|
||||
/// terminating the connection because it has received a message that
|
||||
/// is too big to process.
|
||||
/// </summary>
|
||||
TooBig = 1009,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1010. Indicates that a client is
|
||||
/// terminating the connection because it has expected the server to
|
||||
/// negotiate one or more extension, but the server did not return
|
||||
/// them in the handshake response.
|
||||
/// </summary>
|
||||
MandatoryExtension = 1010,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1011. Indicates that a server is
|
||||
/// terminating the connection because it has encountered an unexpected
|
||||
/// condition that prevented it from fulfilling the request.
|
||||
/// </summary>
|
||||
ServerError = 1011,
|
||||
/// <summary>
|
||||
/// Equivalent to close status 1015. Indicates that the connection was
|
||||
/// closed due to a failure to perform a TLS handshake. A Reserved value.
|
||||
/// </summary>
|
||||
TlsHandshakeFailure = 1015
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,52 +1,52 @@
|
||||
#region License
|
||||
/*
|
||||
* CompressionMethod.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2013-2017 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the method for compression.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The methods are defined in
|
||||
/// <see href="https://tools.ietf.org/html/rfc7692">
|
||||
/// Compression Extensions for WebSocket</see>.
|
||||
/// </remarks>
|
||||
public enum CompressionMethod : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies no compression.
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// Specifies DEFLATE.
|
||||
/// </summary>
|
||||
Deflate
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* CompressionMethod.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2013-2017 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the method for compression.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The methods are defined in
|
||||
/// <see href="https://tools.ietf.org/html/rfc7692">
|
||||
/// Compression Extensions for WebSocket</see>.
|
||||
/// </remarks>
|
||||
public enum CompressionMethod : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies no compression.
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// Specifies DEFLATE.
|
||||
/// </summary>
|
||||
Deflate
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,109 +1,109 @@
|
||||
#region License
|
||||
/*
|
||||
* ErrorEventArgs.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2016 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region Contributors
|
||||
/*
|
||||
* Contributors:
|
||||
* - Frank Razenberg <frank@zzattack.org>
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the event data for the <see cref="WebSocket.OnError"/> event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// That event occurs when the <see cref="WebSocket"/> gets an error.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If you would like to get the error message, you should access
|
||||
/// the <see cref="ErrorEventArgs.Message"/> property.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// And if the error is due to an exception, you can get it by accessing
|
||||
/// the <see cref="ErrorEventArgs.Exception"/> property.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class ErrorEventArgs : EventArgs
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private Exception _exception;
|
||||
private string _message;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal ErrorEventArgs (string message)
|
||||
: this (message, null)
|
||||
{
|
||||
}
|
||||
|
||||
internal ErrorEventArgs (string message, Exception exception)
|
||||
{
|
||||
_message = message;
|
||||
_exception = exception;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the exception that caused the error.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// An <see cref="System.Exception"/> instance that represents the cause of
|
||||
/// the error if it is due to an exception; otherwise, <see langword="null"/>.
|
||||
/// </value>
|
||||
public Exception Exception {
|
||||
get {
|
||||
return _exception;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the error message.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string"/> that represents the error message.
|
||||
/// </value>
|
||||
public string Message {
|
||||
get {
|
||||
return _message;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* ErrorEventArgs.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2016 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region Contributors
|
||||
/*
|
||||
* Contributors:
|
||||
* - Frank Razenberg <frank@zzattack.org>
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the event data for the <see cref="WebSocket.OnError"/> event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// That event occurs when the <see cref="WebSocket"/> gets an error.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If you would like to get the error message, you should access
|
||||
/// the <see cref="ErrorEventArgs.Message"/> property.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// And if the error is due to an exception, you can get it by accessing
|
||||
/// the <see cref="ErrorEventArgs.Exception"/> property.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class ErrorEventArgs : EventArgs
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private Exception _exception;
|
||||
private string _message;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal ErrorEventArgs (string message)
|
||||
: this (message, null)
|
||||
{
|
||||
}
|
||||
|
||||
internal ErrorEventArgs (string message, Exception exception)
|
||||
{
|
||||
_message = message;
|
||||
_exception = exception;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the exception that caused the error.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// An <see cref="System.Exception"/> instance that represents the cause of
|
||||
/// the error if it is due to an exception; otherwise, <see langword="null"/>.
|
||||
/// </value>
|
||||
public Exception Exception {
|
||||
get {
|
||||
return _exception;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the error message.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string"/> that represents the error message.
|
||||
/// </value>
|
||||
public string Message {
|
||||
get {
|
||||
return _message;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,51 +1,51 @@
|
||||
#region License
|
||||
/*
|
||||
* Fin.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates whether a WebSocket frame is the final frame of a message.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
internal enum Fin : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Equivalent to numeric value 0. Indicates more frames of a message follow.
|
||||
/// </summary>
|
||||
More = 0x0,
|
||||
/// <summary>
|
||||
/// Equivalent to numeric value 1. Indicates the final frame of a message.
|
||||
/// </summary>
|
||||
Final = 0x1
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* Fin.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates whether a WebSocket frame is the final frame of a message.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
internal enum Fin : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Equivalent to numeric value 0. Indicates more frames of a message follow.
|
||||
/// </summary>
|
||||
More = 0x0,
|
||||
/// <summary>
|
||||
/// Equivalent to numeric value 1. Indicates the final frame of a message.
|
||||
/// </summary>
|
||||
Final = 0x1
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,208 +1,208 @@
|
||||
#region License
|
||||
/*
|
||||
* HttpBase.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2014 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using WebSocketSharp.Net;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
internal abstract class HttpBase
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private NameValueCollection _headers;
|
||||
private const int _headersMaxLength = 8192;
|
||||
private Version _version;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Fields
|
||||
|
||||
internal byte[] EntityBodyData;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected const string CrLf = "\r\n";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Constructors
|
||||
|
||||
protected HttpBase (Version version, NameValueCollection headers)
|
||||
{
|
||||
_version = version;
|
||||
_headers = headers;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public string EntityBody {
|
||||
get {
|
||||
if (EntityBodyData == null || EntityBodyData.LongLength == 0)
|
||||
return String.Empty;
|
||||
|
||||
Encoding enc = null;
|
||||
|
||||
var contentType = _headers["Content-Type"];
|
||||
if (contentType != null && contentType.Length > 0)
|
||||
enc = HttpUtility.GetEncoding (contentType);
|
||||
|
||||
return (enc ?? Encoding.UTF8).GetString (EntityBodyData);
|
||||
}
|
||||
}
|
||||
|
||||
public NameValueCollection Headers {
|
||||
get {
|
||||
return _headers;
|
||||
}
|
||||
}
|
||||
|
||||
public Version ProtocolVersion {
|
||||
get {
|
||||
return _version;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private static byte[] readEntityBody (Stream stream, string length)
|
||||
{
|
||||
long len;
|
||||
if (!Int64.TryParse (length, out len))
|
||||
throw new ArgumentException ("Cannot be parsed.", "length");
|
||||
|
||||
if (len < 0)
|
||||
throw new ArgumentOutOfRangeException ("length", "Less than zero.");
|
||||
|
||||
return len > 1024
|
||||
? stream.ReadBytes (len, 1024)
|
||||
: len > 0
|
||||
? stream.ReadBytes ((int) len)
|
||||
: null;
|
||||
}
|
||||
|
||||
private static string[] readHeaders (Stream stream, int maxLength)
|
||||
{
|
||||
var buff = new List<byte> ();
|
||||
var cnt = 0;
|
||||
Action<int> add = i => {
|
||||
if (i == -1)
|
||||
throw new EndOfStreamException ("The header cannot be read from the data source.");
|
||||
|
||||
buff.Add ((byte) i);
|
||||
cnt++;
|
||||
};
|
||||
|
||||
var read = false;
|
||||
while (cnt < maxLength) {
|
||||
if (stream.ReadByte ().EqualsWith ('\r', add) &&
|
||||
stream.ReadByte ().EqualsWith ('\n', add) &&
|
||||
stream.ReadByte ().EqualsWith ('\r', add) &&
|
||||
stream.ReadByte ().EqualsWith ('\n', add)) {
|
||||
read = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!read)
|
||||
throw new WebSocketException ("The length of header part is greater than the max length.");
|
||||
|
||||
return Encoding.UTF8.GetString (buff.ToArray ())
|
||||
.Replace (CrLf + " ", " ")
|
||||
.Replace (CrLf + "\t", " ")
|
||||
.Split (new[] { CrLf }, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected static T Read<T> (Stream stream, Func<string[], T> parser, int millisecondsTimeout)
|
||||
where T : HttpBase
|
||||
{
|
||||
var timeout = false;
|
||||
var timer = new Timer (
|
||||
state => {
|
||||
timeout = true;
|
||||
stream.Close ();
|
||||
},
|
||||
null,
|
||||
millisecondsTimeout,
|
||||
-1);
|
||||
|
||||
T http = null;
|
||||
Exception exception = null;
|
||||
try {
|
||||
http = parser (readHeaders (stream, _headersMaxLength));
|
||||
var contentLen = http.Headers["Content-Length"];
|
||||
if (contentLen != null && contentLen.Length > 0)
|
||||
http.EntityBodyData = readEntityBody (stream, contentLen);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
exception = ex;
|
||||
}
|
||||
finally {
|
||||
timer.Change (-1, -1);
|
||||
timer.Dispose ();
|
||||
}
|
||||
|
||||
var msg = timeout
|
||||
? "A timeout has occurred while reading an HTTP request/response."
|
||||
: exception != null
|
||||
? "An exception has occurred while reading an HTTP request/response."
|
||||
: null;
|
||||
|
||||
if (msg != null)
|
||||
throw new WebSocketException (msg, exception);
|
||||
|
||||
return http;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public byte[] ToByteArray ()
|
||||
{
|
||||
return Encoding.UTF8.GetBytes (ToString ());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* HttpBase.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2014 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using WebSocketSharp.Net;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
internal abstract class HttpBase
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private NameValueCollection _headers;
|
||||
private const int _headersMaxLength = 8192;
|
||||
private Version _version;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Fields
|
||||
|
||||
internal byte[] EntityBodyData;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected const string CrLf = "\r\n";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Constructors
|
||||
|
||||
protected HttpBase (Version version, NameValueCollection headers)
|
||||
{
|
||||
_version = version;
|
||||
_headers = headers;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public string EntityBody {
|
||||
get {
|
||||
if (EntityBodyData == null || EntityBodyData.LongLength == 0)
|
||||
return String.Empty;
|
||||
|
||||
Encoding enc = null;
|
||||
|
||||
var contentType = _headers["Content-Type"];
|
||||
if (contentType != null && contentType.Length > 0)
|
||||
enc = HttpUtility.GetEncoding (contentType);
|
||||
|
||||
return (enc ?? Encoding.UTF8).GetString (EntityBodyData);
|
||||
}
|
||||
}
|
||||
|
||||
public NameValueCollection Headers {
|
||||
get {
|
||||
return _headers;
|
||||
}
|
||||
}
|
||||
|
||||
public Version ProtocolVersion {
|
||||
get {
|
||||
return _version;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private static byte[] readEntityBody (Stream stream, string length)
|
||||
{
|
||||
long len;
|
||||
if (!Int64.TryParse (length, out len))
|
||||
throw new ArgumentException ("Cannot be parsed.", "length");
|
||||
|
||||
if (len < 0)
|
||||
throw new ArgumentOutOfRangeException ("length", "Less than zero.");
|
||||
|
||||
return len > 1024
|
||||
? stream.ReadBytes (len, 1024)
|
||||
: len > 0
|
||||
? stream.ReadBytes ((int) len)
|
||||
: null;
|
||||
}
|
||||
|
||||
private static string[] readHeaders (Stream stream, int maxLength)
|
||||
{
|
||||
var buff = new List<byte> ();
|
||||
var cnt = 0;
|
||||
Action<int> add = i => {
|
||||
if (i == -1)
|
||||
throw new EndOfStreamException ("The header cannot be read from the data source.");
|
||||
|
||||
buff.Add ((byte) i);
|
||||
cnt++;
|
||||
};
|
||||
|
||||
var read = false;
|
||||
while (cnt < maxLength) {
|
||||
if (stream.ReadByte ().EqualsWith ('\r', add) &&
|
||||
stream.ReadByte ().EqualsWith ('\n', add) &&
|
||||
stream.ReadByte ().EqualsWith ('\r', add) &&
|
||||
stream.ReadByte ().EqualsWith ('\n', add)) {
|
||||
read = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!read)
|
||||
throw new WebSocketException ("The length of header part is greater than the max length.");
|
||||
|
||||
return Encoding.UTF8.GetString (buff.ToArray ())
|
||||
.Replace (CrLf + " ", " ")
|
||||
.Replace (CrLf + "\t", " ")
|
||||
.Split (new[] { CrLf }, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected static T Read<T> (Stream stream, Func<string[], T> parser, int millisecondsTimeout)
|
||||
where T : HttpBase
|
||||
{
|
||||
var timeout = false;
|
||||
var timer = new Timer (
|
||||
state => {
|
||||
timeout = true;
|
||||
stream.Close ();
|
||||
},
|
||||
null,
|
||||
millisecondsTimeout,
|
||||
-1);
|
||||
|
||||
T http = null;
|
||||
Exception exception = null;
|
||||
try {
|
||||
http = parser (readHeaders (stream, _headersMaxLength));
|
||||
var contentLen = http.Headers["Content-Length"];
|
||||
if (contentLen != null && contentLen.Length > 0)
|
||||
http.EntityBodyData = readEntityBody (stream, contentLen);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
exception = ex;
|
||||
}
|
||||
finally {
|
||||
timer.Change (-1, -1);
|
||||
timer.Dispose ();
|
||||
}
|
||||
|
||||
var msg = timeout
|
||||
? "A timeout has occurred while reading an HTTP request/response."
|
||||
: exception != null
|
||||
? "An exception has occurred while reading an HTTP request/response."
|
||||
: null;
|
||||
|
||||
if (msg != null)
|
||||
throw new WebSocketException (msg, exception);
|
||||
|
||||
return http;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public byte[] ToByteArray ()
|
||||
{
|
||||
return Encoding.UTF8.GetBytes (ToString ());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,217 +1,217 @@
|
||||
#region License
|
||||
/*
|
||||
* HttpRequest.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region Contributors
|
||||
/*
|
||||
* Contributors:
|
||||
* - David Burhans
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using WebSocketSharp.Net;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
internal class HttpRequest : HttpBase
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private CookieCollection _cookies;
|
||||
private string _method;
|
||||
private string _uri;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Constructors
|
||||
|
||||
private HttpRequest (string method, string uri, Version version, NameValueCollection headers)
|
||||
: base (version, headers)
|
||||
{
|
||||
_method = method;
|
||||
_uri = uri;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal HttpRequest (string method, string uri)
|
||||
: this (method, uri, HttpVersion.Version11, new NameValueCollection ())
|
||||
{
|
||||
Headers["User-Agent"] = "websocket-sharp/1.0";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public AuthenticationResponse AuthenticationResponse {
|
||||
get {
|
||||
var res = Headers["Authorization"];
|
||||
return res != null && res.Length > 0
|
||||
? AuthenticationResponse.Parse (res)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
public CookieCollection Cookies {
|
||||
get {
|
||||
if (_cookies == null)
|
||||
_cookies = Headers.GetCookies (false);
|
||||
|
||||
return _cookies;
|
||||
}
|
||||
}
|
||||
|
||||
public string HttpMethod {
|
||||
get {
|
||||
return _method;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsWebSocketRequest {
|
||||
get {
|
||||
return _method == "GET"
|
||||
&& ProtocolVersion > HttpVersion.Version10
|
||||
&& Headers.Upgrades ("websocket");
|
||||
}
|
||||
}
|
||||
|
||||
public string RequestUri {
|
||||
get {
|
||||
return _uri;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
internal static HttpRequest CreateConnectRequest (Uri uri)
|
||||
{
|
||||
var host = uri.DnsSafeHost;
|
||||
var port = uri.Port;
|
||||
var authority = String.Format ("{0}:{1}", host, port);
|
||||
var req = new HttpRequest ("CONNECT", authority);
|
||||
req.Headers["Host"] = port == 80 ? host : authority;
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
internal static HttpRequest CreateWebSocketRequest (Uri uri)
|
||||
{
|
||||
var req = new HttpRequest ("GET", uri.PathAndQuery);
|
||||
var headers = req.Headers;
|
||||
|
||||
// Only includes a port number in the Host header value if it's non-default.
|
||||
// See: https://tools.ietf.org/html/rfc6455#page-17
|
||||
var port = uri.Port;
|
||||
var schm = uri.Scheme;
|
||||
headers["Host"] = (port == 80 && schm == "ws") || (port == 443 && schm == "wss")
|
||||
? uri.DnsSafeHost
|
||||
: uri.Authority;
|
||||
|
||||
headers["Upgrade"] = "websocket";
|
||||
headers["Connection"] = "Upgrade";
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
internal HttpResponse GetResponse (Stream stream, int millisecondsTimeout)
|
||||
{
|
||||
var buff = ToByteArray ();
|
||||
stream.Write (buff, 0, buff.Length);
|
||||
|
||||
return Read<HttpResponse> (stream, HttpResponse.Parse, millisecondsTimeout);
|
||||
}
|
||||
|
||||
internal static HttpRequest Parse (string[] headerParts)
|
||||
{
|
||||
var requestLine = headerParts[0].Split (new[] { ' ' }, 3);
|
||||
if (requestLine.Length != 3)
|
||||
throw new ArgumentException ("Invalid request line: " + headerParts[0]);
|
||||
|
||||
var headers = new WebHeaderCollection ();
|
||||
for (int i = 1; i < headerParts.Length; i++)
|
||||
headers.InternalSet (headerParts[i], false);
|
||||
|
||||
return new HttpRequest (
|
||||
requestLine[0], requestLine[1], new Version (requestLine[2].Substring (5)), headers);
|
||||
}
|
||||
|
||||
internal static HttpRequest Read (Stream stream, int millisecondsTimeout)
|
||||
{
|
||||
return Read<HttpRequest> (stream, Parse, millisecondsTimeout);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void SetCookies (CookieCollection cookies)
|
||||
{
|
||||
if (cookies == null || cookies.Count == 0)
|
||||
return;
|
||||
|
||||
var buff = new StringBuilder (64);
|
||||
foreach (var cookie in cookies.Sorted)
|
||||
if (!cookie.Expired)
|
||||
buff.AppendFormat ("{0}; ", cookie.ToString ());
|
||||
|
||||
var len = buff.Length;
|
||||
if (len > 2) {
|
||||
buff.Length = len - 2;
|
||||
Headers["Cookie"] = buff.ToString ();
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
var output = new StringBuilder (64);
|
||||
output.AppendFormat ("{0} {1} HTTP/{2}{3}", _method, _uri, ProtocolVersion, CrLf);
|
||||
|
||||
var headers = Headers;
|
||||
foreach (var key in headers.AllKeys)
|
||||
output.AppendFormat ("{0}: {1}{2}", key, headers[key], CrLf);
|
||||
|
||||
output.Append (CrLf);
|
||||
|
||||
var entity = EntityBody;
|
||||
if (entity.Length > 0)
|
||||
output.Append (entity);
|
||||
|
||||
return output.ToString ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* HttpRequest.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region Contributors
|
||||
/*
|
||||
* Contributors:
|
||||
* - David Burhans
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using WebSocketSharp.Net;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
internal class HttpRequest : HttpBase
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private CookieCollection _cookies;
|
||||
private string _method;
|
||||
private string _uri;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Constructors
|
||||
|
||||
private HttpRequest (string method, string uri, Version version, NameValueCollection headers)
|
||||
: base (version, headers)
|
||||
{
|
||||
_method = method;
|
||||
_uri = uri;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal HttpRequest (string method, string uri)
|
||||
: this (method, uri, HttpVersion.Version11, new NameValueCollection ())
|
||||
{
|
||||
Headers["User-Agent"] = "websocket-sharp/1.0";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public AuthenticationResponse AuthenticationResponse {
|
||||
get {
|
||||
var res = Headers["Authorization"];
|
||||
return res != null && res.Length > 0
|
||||
? AuthenticationResponse.Parse (res)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
public CookieCollection Cookies {
|
||||
get {
|
||||
if (_cookies == null)
|
||||
_cookies = Headers.GetCookies (false);
|
||||
|
||||
return _cookies;
|
||||
}
|
||||
}
|
||||
|
||||
public string HttpMethod {
|
||||
get {
|
||||
return _method;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsWebSocketRequest {
|
||||
get {
|
||||
return _method == "GET"
|
||||
&& ProtocolVersion > HttpVersion.Version10
|
||||
&& Headers.Upgrades ("websocket");
|
||||
}
|
||||
}
|
||||
|
||||
public string RequestUri {
|
||||
get {
|
||||
return _uri;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
internal static HttpRequest CreateConnectRequest (Uri uri)
|
||||
{
|
||||
var host = uri.DnsSafeHost;
|
||||
var port = uri.Port;
|
||||
var authority = String.Format ("{0}:{1}", host, port);
|
||||
var req = new HttpRequest ("CONNECT", authority);
|
||||
req.Headers["Host"] = port == 80 ? host : authority;
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
internal static HttpRequest CreateWebSocketRequest (Uri uri)
|
||||
{
|
||||
var req = new HttpRequest ("GET", uri.PathAndQuery);
|
||||
var headers = req.Headers;
|
||||
|
||||
// Only includes a port number in the Host header value if it's non-default.
|
||||
// See: https://tools.ietf.org/html/rfc6455#page-17
|
||||
var port = uri.Port;
|
||||
var schm = uri.Scheme;
|
||||
headers["Host"] = (port == 80 && schm == "ws") || (port == 443 && schm == "wss")
|
||||
? uri.DnsSafeHost
|
||||
: uri.Authority;
|
||||
|
||||
headers["Upgrade"] = "websocket";
|
||||
headers["Connection"] = "Upgrade";
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
internal HttpResponse GetResponse (Stream stream, int millisecondsTimeout)
|
||||
{
|
||||
var buff = ToByteArray ();
|
||||
stream.Write (buff, 0, buff.Length);
|
||||
|
||||
return Read<HttpResponse> (stream, HttpResponse.Parse, millisecondsTimeout);
|
||||
}
|
||||
|
||||
internal static HttpRequest Parse (string[] headerParts)
|
||||
{
|
||||
var requestLine = headerParts[0].Split (new[] { ' ' }, 3);
|
||||
if (requestLine.Length != 3)
|
||||
throw new ArgumentException ("Invalid request line: " + headerParts[0]);
|
||||
|
||||
var headers = new WebHeaderCollection ();
|
||||
for (int i = 1; i < headerParts.Length; i++)
|
||||
headers.InternalSet (headerParts[i], false);
|
||||
|
||||
return new HttpRequest (
|
||||
requestLine[0], requestLine[1], new Version (requestLine[2].Substring (5)), headers);
|
||||
}
|
||||
|
||||
internal static HttpRequest Read (Stream stream, int millisecondsTimeout)
|
||||
{
|
||||
return Read<HttpRequest> (stream, Parse, millisecondsTimeout);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void SetCookies (CookieCollection cookies)
|
||||
{
|
||||
if (cookies == null || cookies.Count == 0)
|
||||
return;
|
||||
|
||||
var buff = new StringBuilder (64);
|
||||
foreach (var cookie in cookies.Sorted)
|
||||
if (!cookie.Expired)
|
||||
buff.AppendFormat ("{0}; ", cookie.ToString ());
|
||||
|
||||
var len = buff.Length;
|
||||
if (len > 2) {
|
||||
buff.Length = len - 2;
|
||||
Headers["Cookie"] = buff.ToString ();
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
var output = new StringBuilder (64);
|
||||
output.AppendFormat ("{0} {1} HTTP/{2}{3}", _method, _uri, ProtocolVersion, CrLf);
|
||||
|
||||
var headers = Headers;
|
||||
foreach (var key in headers.AllKeys)
|
||||
output.AppendFormat ("{0}: {1}{2}", key, headers[key], CrLf);
|
||||
|
||||
output.Append (CrLf);
|
||||
|
||||
var entity = EntityBody;
|
||||
if (entity.Length > 0)
|
||||
output.Append (entity);
|
||||
|
||||
return output.ToString ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,209 +1,209 @@
|
||||
#region License
|
||||
/*
|
||||
* HttpResponse.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2014 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using WebSocketSharp.Net;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
internal class HttpResponse : HttpBase
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private string _code;
|
||||
private string _reason;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Constructors
|
||||
|
||||
private HttpResponse (string code, string reason, Version version, NameValueCollection headers)
|
||||
: base (version, headers)
|
||||
{
|
||||
_code = code;
|
||||
_reason = reason;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal HttpResponse (HttpStatusCode code)
|
||||
: this (code, code.GetDescription ())
|
||||
{
|
||||
}
|
||||
|
||||
internal HttpResponse (HttpStatusCode code, string reason)
|
||||
: this (((int) code).ToString (), reason, HttpVersion.Version11, new NameValueCollection ())
|
||||
{
|
||||
Headers["Server"] = "websocket-sharp/1.0";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public CookieCollection Cookies {
|
||||
get {
|
||||
return Headers.GetCookies (true);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasConnectionClose {
|
||||
get {
|
||||
var comparison = StringComparison.OrdinalIgnoreCase;
|
||||
return Headers.Contains ("Connection", "close", comparison);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsProxyAuthenticationRequired {
|
||||
get {
|
||||
return _code == "407";
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsRedirect {
|
||||
get {
|
||||
return _code == "301" || _code == "302";
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsUnauthorized {
|
||||
get {
|
||||
return _code == "401";
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsWebSocketResponse {
|
||||
get {
|
||||
return ProtocolVersion > HttpVersion.Version10
|
||||
&& _code == "101"
|
||||
&& Headers.Upgrades ("websocket");
|
||||
}
|
||||
}
|
||||
|
||||
public string Reason {
|
||||
get {
|
||||
return _reason;
|
||||
}
|
||||
}
|
||||
|
||||
public string StatusCode {
|
||||
get {
|
||||
return _code;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
internal static HttpResponse CreateCloseResponse (HttpStatusCode code)
|
||||
{
|
||||
var res = new HttpResponse (code);
|
||||
res.Headers["Connection"] = "close";
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
internal static HttpResponse CreateUnauthorizedResponse (string challenge)
|
||||
{
|
||||
var res = new HttpResponse (HttpStatusCode.Unauthorized);
|
||||
res.Headers["WWW-Authenticate"] = challenge;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
internal static HttpResponse CreateWebSocketResponse ()
|
||||
{
|
||||
var res = new HttpResponse (HttpStatusCode.SwitchingProtocols);
|
||||
|
||||
var headers = res.Headers;
|
||||
headers["Upgrade"] = "websocket";
|
||||
headers["Connection"] = "Upgrade";
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
internal static HttpResponse Parse (string[] headerParts)
|
||||
{
|
||||
var statusLine = headerParts[0].Split (new[] { ' ' }, 3);
|
||||
if (statusLine.Length != 3)
|
||||
throw new ArgumentException ("Invalid status line: " + headerParts[0]);
|
||||
|
||||
var headers = new WebHeaderCollection ();
|
||||
for (int i = 1; i < headerParts.Length; i++)
|
||||
headers.InternalSet (headerParts[i], true);
|
||||
|
||||
return new HttpResponse (
|
||||
statusLine[1], statusLine[2], new Version (statusLine[0].Substring (5)), headers);
|
||||
}
|
||||
|
||||
internal static HttpResponse Read (Stream stream, int millisecondsTimeout)
|
||||
{
|
||||
return Read<HttpResponse> (stream, Parse, millisecondsTimeout);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void SetCookies (CookieCollection cookies)
|
||||
{
|
||||
if (cookies == null || cookies.Count == 0)
|
||||
return;
|
||||
|
||||
var headers = Headers;
|
||||
foreach (var cookie in cookies.Sorted)
|
||||
headers.Add ("Set-Cookie", cookie.ToResponseString ());
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
var output = new StringBuilder (64);
|
||||
output.AppendFormat ("HTTP/{0} {1} {2}{3}", ProtocolVersion, _code, _reason, CrLf);
|
||||
|
||||
var headers = Headers;
|
||||
foreach (var key in headers.AllKeys)
|
||||
output.AppendFormat ("{0}: {1}{2}", key, headers[key], CrLf);
|
||||
|
||||
output.Append (CrLf);
|
||||
|
||||
var entity = EntityBody;
|
||||
if (entity.Length > 0)
|
||||
output.Append (entity);
|
||||
|
||||
return output.ToString ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* HttpResponse.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2014 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using WebSocketSharp.Net;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
internal class HttpResponse : HttpBase
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private string _code;
|
||||
private string _reason;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Constructors
|
||||
|
||||
private HttpResponse (string code, string reason, Version version, NameValueCollection headers)
|
||||
: base (version, headers)
|
||||
{
|
||||
_code = code;
|
||||
_reason = reason;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal HttpResponse (HttpStatusCode code)
|
||||
: this (code, code.GetDescription ())
|
||||
{
|
||||
}
|
||||
|
||||
internal HttpResponse (HttpStatusCode code, string reason)
|
||||
: this (((int) code).ToString (), reason, HttpVersion.Version11, new NameValueCollection ())
|
||||
{
|
||||
Headers["Server"] = "websocket-sharp/1.0";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public CookieCollection Cookies {
|
||||
get {
|
||||
return Headers.GetCookies (true);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasConnectionClose {
|
||||
get {
|
||||
var comparison = StringComparison.OrdinalIgnoreCase;
|
||||
return Headers.Contains ("Connection", "close", comparison);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsProxyAuthenticationRequired {
|
||||
get {
|
||||
return _code == "407";
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsRedirect {
|
||||
get {
|
||||
return _code == "301" || _code == "302";
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsUnauthorized {
|
||||
get {
|
||||
return _code == "401";
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsWebSocketResponse {
|
||||
get {
|
||||
return ProtocolVersion > HttpVersion.Version10
|
||||
&& _code == "101"
|
||||
&& Headers.Upgrades ("websocket");
|
||||
}
|
||||
}
|
||||
|
||||
public string Reason {
|
||||
get {
|
||||
return _reason;
|
||||
}
|
||||
}
|
||||
|
||||
public string StatusCode {
|
||||
get {
|
||||
return _code;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
internal static HttpResponse CreateCloseResponse (HttpStatusCode code)
|
||||
{
|
||||
var res = new HttpResponse (code);
|
||||
res.Headers["Connection"] = "close";
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
internal static HttpResponse CreateUnauthorizedResponse (string challenge)
|
||||
{
|
||||
var res = new HttpResponse (HttpStatusCode.Unauthorized);
|
||||
res.Headers["WWW-Authenticate"] = challenge;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
internal static HttpResponse CreateWebSocketResponse ()
|
||||
{
|
||||
var res = new HttpResponse (HttpStatusCode.SwitchingProtocols);
|
||||
|
||||
var headers = res.Headers;
|
||||
headers["Upgrade"] = "websocket";
|
||||
headers["Connection"] = "Upgrade";
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
internal static HttpResponse Parse (string[] headerParts)
|
||||
{
|
||||
var statusLine = headerParts[0].Split (new[] { ' ' }, 3);
|
||||
if (statusLine.Length != 3)
|
||||
throw new ArgumentException ("Invalid status line: " + headerParts[0]);
|
||||
|
||||
var headers = new WebHeaderCollection ();
|
||||
for (int i = 1; i < headerParts.Length; i++)
|
||||
headers.InternalSet (headerParts[i], true);
|
||||
|
||||
return new HttpResponse (
|
||||
statusLine[1], statusLine[2], new Version (statusLine[0].Substring (5)), headers);
|
||||
}
|
||||
|
||||
internal static HttpResponse Read (Stream stream, int millisecondsTimeout)
|
||||
{
|
||||
return Read<HttpResponse> (stream, Parse, millisecondsTimeout);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void SetCookies (CookieCollection cookies)
|
||||
{
|
||||
if (cookies == null || cookies.Count == 0)
|
||||
return;
|
||||
|
||||
var headers = Headers;
|
||||
foreach (var cookie in cookies.Sorted)
|
||||
headers.Add ("Set-Cookie", cookie.ToResponseString ());
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
var output = new StringBuilder (64);
|
||||
output.AppendFormat ("HTTP/{0} {1} {2}{3}", ProtocolVersion, _code, _reason, CrLf);
|
||||
|
||||
var headers = Headers;
|
||||
foreach (var key in headers.AllKeys)
|
||||
output.AppendFormat ("{0}: {1}{2}", key, headers[key], CrLf);
|
||||
|
||||
output.Append (CrLf);
|
||||
|
||||
var entity = EntityBody;
|
||||
if (entity.Length > 0)
|
||||
output.Append (entity);
|
||||
|
||||
return output.ToString ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,149 +1,149 @@
|
||||
#region License
|
||||
/*
|
||||
* LogData.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2013-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a log data used by the <see cref="Logger"/> class.
|
||||
/// </summary>
|
||||
public class LogData
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private StackFrame _caller;
|
||||
private DateTime _date;
|
||||
private LogLevel _level;
|
||||
private string _message;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal LogData (LogLevel level, StackFrame caller, string message)
|
||||
{
|
||||
_level = level;
|
||||
_caller = caller;
|
||||
_message = message ?? String.Empty;
|
||||
_date = DateTime.Now;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the information of the logging method caller.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="StackFrame"/> that provides the information of the logging method caller.
|
||||
/// </value>
|
||||
public StackFrame Caller {
|
||||
get {
|
||||
return _caller;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the date and time when the log data was created.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="DateTime"/> that represents the date and time when the log data was created.
|
||||
/// </value>
|
||||
public DateTime Date {
|
||||
get {
|
||||
return _date;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the logging level of the log data.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// One of the <see cref="LogLevel"/> enum values, indicates the logging level of the log data.
|
||||
/// </value>
|
||||
public LogLevel Level {
|
||||
get {
|
||||
return _level;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the message of the log data.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string"/> that represents the message of the log data.
|
||||
/// </value>
|
||||
public string Message {
|
||||
get {
|
||||
return _message;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="string"/> that represents the current <see cref="LogData"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="string"/> that represents the current <see cref="LogData"/>.
|
||||
/// </returns>
|
||||
public override string ToString ()
|
||||
{
|
||||
var header = String.Format ("{0}|{1,-5}|", _date, _level);
|
||||
var method = _caller.GetMethod ();
|
||||
var type = method.DeclaringType;
|
||||
#if DEBUG
|
||||
var lineNum = _caller.GetFileLineNumber ();
|
||||
var headerAndCaller =
|
||||
String.Format ("{0}{1}.{2}:{3}|", header, type.Name, method.Name, lineNum);
|
||||
#else
|
||||
var headerAndCaller = String.Format ("{0}{1}.{2}|", header, type.Name, method.Name);
|
||||
#endif
|
||||
var msgs = _message.Replace ("\r\n", "\n").TrimEnd ('\n').Split ('\n');
|
||||
if (msgs.Length <= 1)
|
||||
return String.Format ("{0}{1}", headerAndCaller, _message);
|
||||
|
||||
var buff = new StringBuilder (String.Format ("{0}{1}\n", headerAndCaller, msgs[0]), 64);
|
||||
|
||||
var fmt = String.Format ("{{0,{0}}}{{1}}\n", header.Length);
|
||||
for (var i = 1; i < msgs.Length; i++)
|
||||
buff.AppendFormat (fmt, "", msgs[i]);
|
||||
|
||||
buff.Length--;
|
||||
return buff.ToString ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* LogData.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2013-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a log data used by the <see cref="Logger"/> class.
|
||||
/// </summary>
|
||||
public class LogData
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private StackFrame _caller;
|
||||
private DateTime _date;
|
||||
private LogLevel _level;
|
||||
private string _message;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal LogData (LogLevel level, StackFrame caller, string message)
|
||||
{
|
||||
_level = level;
|
||||
_caller = caller;
|
||||
_message = message ?? String.Empty;
|
||||
_date = DateTime.Now;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the information of the logging method caller.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="StackFrame"/> that provides the information of the logging method caller.
|
||||
/// </value>
|
||||
public StackFrame Caller {
|
||||
get {
|
||||
return _caller;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the date and time when the log data was created.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="DateTime"/> that represents the date and time when the log data was created.
|
||||
/// </value>
|
||||
public DateTime Date {
|
||||
get {
|
||||
return _date;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the logging level of the log data.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// One of the <see cref="LogLevel"/> enum values, indicates the logging level of the log data.
|
||||
/// </value>
|
||||
public LogLevel Level {
|
||||
get {
|
||||
return _level;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the message of the log data.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string"/> that represents the message of the log data.
|
||||
/// </value>
|
||||
public string Message {
|
||||
get {
|
||||
return _message;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="string"/> that represents the current <see cref="LogData"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="string"/> that represents the current <see cref="LogData"/>.
|
||||
/// </returns>
|
||||
public override string ToString ()
|
||||
{
|
||||
var header = String.Format ("{0}|{1,-5}|", _date, _level);
|
||||
var method = _caller.GetMethod ();
|
||||
var type = method.DeclaringType;
|
||||
#if DEBUG
|
||||
var lineNum = _caller.GetFileLineNumber ();
|
||||
var headerAndCaller =
|
||||
String.Format ("{0}{1}.{2}:{3}|", header, type.Name, method.Name, lineNum);
|
||||
#else
|
||||
var headerAndCaller = String.Format ("{0}{1}.{2}|", header, type.Name, method.Name);
|
||||
#endif
|
||||
var msgs = _message.Replace ("\r\n", "\n").TrimEnd ('\n').Split ('\n');
|
||||
if (msgs.Length <= 1)
|
||||
return String.Format ("{0}{1}", headerAndCaller, _message);
|
||||
|
||||
var buff = new StringBuilder (String.Format ("{0}{1}\n", headerAndCaller, msgs[0]), 64);
|
||||
|
||||
var fmt = String.Format ("{{0,{0}}}{{1}}\n", header.Length);
|
||||
for (var i = 1; i < msgs.Length; i++)
|
||||
buff.AppendFormat (fmt, "", msgs[i]);
|
||||
|
||||
buff.Length--;
|
||||
return buff.ToString ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,63 +1,63 @@
|
||||
#region License
|
||||
/*
|
||||
* LogLevel.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2013-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the logging level.
|
||||
/// </summary>
|
||||
public enum LogLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the bottom logging level.
|
||||
/// </summary>
|
||||
Trace,
|
||||
/// <summary>
|
||||
/// Specifies the 2nd logging level from the bottom.
|
||||
/// </summary>
|
||||
Debug,
|
||||
/// <summary>
|
||||
/// Specifies the 3rd logging level from the bottom.
|
||||
/// </summary>
|
||||
Info,
|
||||
/// <summary>
|
||||
/// Specifies the 3rd logging level from the top.
|
||||
/// </summary>
|
||||
Warn,
|
||||
/// <summary>
|
||||
/// Specifies the 2nd logging level from the top.
|
||||
/// </summary>
|
||||
Error,
|
||||
/// <summary>
|
||||
/// Specifies the top logging level.
|
||||
/// </summary>
|
||||
Fatal
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* LogLevel.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2013-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the logging level.
|
||||
/// </summary>
|
||||
public enum LogLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the bottom logging level.
|
||||
/// </summary>
|
||||
Trace,
|
||||
/// <summary>
|
||||
/// Specifies the 2nd logging level from the bottom.
|
||||
/// </summary>
|
||||
Debug,
|
||||
/// <summary>
|
||||
/// Specifies the 3rd logging level from the bottom.
|
||||
/// </summary>
|
||||
Info,
|
||||
/// <summary>
|
||||
/// Specifies the 3rd logging level from the top.
|
||||
/// </summary>
|
||||
Warn,
|
||||
/// <summary>
|
||||
/// Specifies the 2nd logging level from the top.
|
||||
/// </summary>
|
||||
Error,
|
||||
/// <summary>
|
||||
/// Specifies the top logging level.
|
||||
/// </summary>
|
||||
Fatal
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,330 +1,330 @@
|
||||
#region License
|
||||
/*
|
||||
* Logger.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2013-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a set of methods and properties for logging.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// If you output a log with lower than the value of the <see cref="Logger.Level"/> property,
|
||||
/// it cannot be outputted.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// 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.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// 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>
|
||||
/// delegate.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class Logger
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private volatile string _file;
|
||||
private volatile LogLevel _level;
|
||||
private Action<LogData, string> _output;
|
||||
private object _sync;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Logger"/> class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This constructor initializes the current logging level with <see cref="LogLevel.Error"/>.
|
||||
/// </remarks>
|
||||
public Logger ()
|
||||
: this (LogLevel.Error, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Logger"/> class with
|
||||
/// the specified logging <paramref name="level"/>.
|
||||
/// </summary>
|
||||
/// <param name="level">
|
||||
/// One of the <see cref="LogLevel"/> enum values.
|
||||
/// </param>
|
||||
public Logger (LogLevel level)
|
||||
: this (level, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Logger"/> class with
|
||||
/// the specified logging <paramref name="level"/>, path to the log <paramref name="file"/>,
|
||||
/// and <paramref name="output"/> action.
|
||||
/// </summary>
|
||||
/// <param name="level">
|
||||
/// One of the <see cref="LogLevel"/> enum values.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="string"/> that represents the path to the log file.
|
||||
/// </param>
|
||||
/// <param name="output">
|
||||
/// 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
|
||||
/// <paramref name="file"/>.
|
||||
/// </param>
|
||||
public Logger (LogLevel level, string file, Action<LogData, string> output)
|
||||
{
|
||||
_level = level;
|
||||
_file = file;
|
||||
_output = output ?? defaultOutput;
|
||||
_sync = new object ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current path to the log file.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string"/> that represents the current path to the log file if any.
|
||||
/// </value>
|
||||
public string File {
|
||||
get {
|
||||
return _file;
|
||||
}
|
||||
|
||||
set {
|
||||
lock (_sync) {
|
||||
_file = value;
|
||||
Warn (
|
||||
String.Format ("The current path to the log file has been changed to {0}.", _file));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current logging level.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A log with lower than the value of this property cannot be outputted.
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// One of the <see cref="LogLevel"/> enum values, specifies the current logging level.
|
||||
/// </value>
|
||||
public LogLevel Level {
|
||||
get {
|
||||
return _level;
|
||||
}
|
||||
|
||||
set {
|
||||
lock (_sync) {
|
||||
_level = value;
|
||||
Warn (String.Format ("The current logging level has been changed to {0}.", _level));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current output action used to output a log.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <para>
|
||||
/// 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
|
||||
/// the <see cref="Logger.File"/> property.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If the value to set is <see langword="null"/>, the current output action is changed to
|
||||
/// the default output action.
|
||||
/// </para>
|
||||
/// </value>
|
||||
public Action<LogData, string> Output {
|
||||
get {
|
||||
return _output;
|
||||
}
|
||||
|
||||
set {
|
||||
lock (_sync) {
|
||||
_output = value ?? defaultOutput;
|
||||
Warn ("The current output action has been changed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private static void defaultOutput (LogData data, string path)
|
||||
{
|
||||
var log = data.ToString ();
|
||||
Console.WriteLine (log);
|
||||
if (path != null && path.Length > 0)
|
||||
writeToFile (log, path);
|
||||
}
|
||||
|
||||
private void output (string message, LogLevel level)
|
||||
{
|
||||
lock (_sync) {
|
||||
if (_level > level)
|
||||
return;
|
||||
|
||||
LogData data = null;
|
||||
try {
|
||||
data = new LogData (level, new StackFrame (2, true), message);
|
||||
_output (data, _file);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
data = new LogData (LogLevel.Fatal, new StackFrame (0, true), ex.Message);
|
||||
Console.WriteLine (data.ToString ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeToFile (string value, string path)
|
||||
{
|
||||
using (var writer = new StreamWriter (path, true))
|
||||
using (var syncWriter = TextWriter.Synchronized (writer))
|
||||
syncWriter.WriteLine (value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Debug"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the current logging level is higher than <see cref="LogLevel.Debug"/>,
|
||||
/// this method doesn't output <paramref name="message"/> as a log.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that represents the message to output as a log.
|
||||
/// </param>
|
||||
public void Debug (string message)
|
||||
{
|
||||
if (_level > LogLevel.Debug)
|
||||
return;
|
||||
|
||||
output (message, LogLevel.Debug);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Error"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the current logging level is higher than <see cref="LogLevel.Error"/>,
|
||||
/// this method doesn't output <paramref name="message"/> as a log.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that represents the message to output as a log.
|
||||
/// </param>
|
||||
public void Error (string message)
|
||||
{
|
||||
if (_level > LogLevel.Error)
|
||||
return;
|
||||
|
||||
output (message, LogLevel.Error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Fatal"/>.
|
||||
/// </summary>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that represents the message to output as a log.
|
||||
/// </param>
|
||||
public void Fatal (string message)
|
||||
{
|
||||
output (message, LogLevel.Fatal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Info"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the current logging level is higher than <see cref="LogLevel.Info"/>,
|
||||
/// this method doesn't output <paramref name="message"/> as a log.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that represents the message to output as a log.
|
||||
/// </param>
|
||||
public void Info (string message)
|
||||
{
|
||||
if (_level > LogLevel.Info)
|
||||
return;
|
||||
|
||||
output (message, LogLevel.Info);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Trace"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the current logging level is higher than <see cref="LogLevel.Trace"/>,
|
||||
/// this method doesn't output <paramref name="message"/> as a log.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that represents the message to output as a log.
|
||||
/// </param>
|
||||
public void Trace (string message)
|
||||
{
|
||||
if (_level > LogLevel.Trace)
|
||||
return;
|
||||
|
||||
output (message, LogLevel.Trace);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Warn"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the current logging level is higher than <see cref="LogLevel.Warn"/>,
|
||||
/// this method doesn't output <paramref name="message"/> as a log.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that represents the message to output as a log.
|
||||
/// </param>
|
||||
public void Warn (string message)
|
||||
{
|
||||
if (_level > LogLevel.Warn)
|
||||
return;
|
||||
|
||||
output (message, LogLevel.Warn);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* Logger.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2013-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a set of methods and properties for logging.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// If you output a log with lower than the value of the <see cref="Logger.Level"/> property,
|
||||
/// it cannot be outputted.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// 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.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// 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>
|
||||
/// delegate.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class Logger
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private volatile string _file;
|
||||
private volatile LogLevel _level;
|
||||
private Action<LogData, string> _output;
|
||||
private object _sync;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Logger"/> class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This constructor initializes the current logging level with <see cref="LogLevel.Error"/>.
|
||||
/// </remarks>
|
||||
public Logger ()
|
||||
: this (LogLevel.Error, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Logger"/> class with
|
||||
/// the specified logging <paramref name="level"/>.
|
||||
/// </summary>
|
||||
/// <param name="level">
|
||||
/// One of the <see cref="LogLevel"/> enum values.
|
||||
/// </param>
|
||||
public Logger (LogLevel level)
|
||||
: this (level, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Logger"/> class with
|
||||
/// the specified logging <paramref name="level"/>, path to the log <paramref name="file"/>,
|
||||
/// and <paramref name="output"/> action.
|
||||
/// </summary>
|
||||
/// <param name="level">
|
||||
/// One of the <see cref="LogLevel"/> enum values.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="string"/> that represents the path to the log file.
|
||||
/// </param>
|
||||
/// <param name="output">
|
||||
/// 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
|
||||
/// <paramref name="file"/>.
|
||||
/// </param>
|
||||
public Logger (LogLevel level, string file, Action<LogData, string> output)
|
||||
{
|
||||
_level = level;
|
||||
_file = file;
|
||||
_output = output ?? defaultOutput;
|
||||
_sync = new object ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current path to the log file.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string"/> that represents the current path to the log file if any.
|
||||
/// </value>
|
||||
public string File {
|
||||
get {
|
||||
return _file;
|
||||
}
|
||||
|
||||
set {
|
||||
lock (_sync) {
|
||||
_file = value;
|
||||
Warn (
|
||||
String.Format ("The current path to the log file has been changed to {0}.", _file));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current logging level.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A log with lower than the value of this property cannot be outputted.
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// One of the <see cref="LogLevel"/> enum values, specifies the current logging level.
|
||||
/// </value>
|
||||
public LogLevel Level {
|
||||
get {
|
||||
return _level;
|
||||
}
|
||||
|
||||
set {
|
||||
lock (_sync) {
|
||||
_level = value;
|
||||
Warn (String.Format ("The current logging level has been changed to {0}.", _level));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current output action used to output a log.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <para>
|
||||
/// 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
|
||||
/// the <see cref="Logger.File"/> property.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If the value to set is <see langword="null"/>, the current output action is changed to
|
||||
/// the default output action.
|
||||
/// </para>
|
||||
/// </value>
|
||||
public Action<LogData, string> Output {
|
||||
get {
|
||||
return _output;
|
||||
}
|
||||
|
||||
set {
|
||||
lock (_sync) {
|
||||
_output = value ?? defaultOutput;
|
||||
Warn ("The current output action has been changed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private static void defaultOutput (LogData data, string path)
|
||||
{
|
||||
var log = data.ToString ();
|
||||
Console.WriteLine (log);
|
||||
if (path != null && path.Length > 0)
|
||||
writeToFile (log, path);
|
||||
}
|
||||
|
||||
private void output (string message, LogLevel level)
|
||||
{
|
||||
lock (_sync) {
|
||||
if (_level > level)
|
||||
return;
|
||||
|
||||
LogData data = null;
|
||||
try {
|
||||
data = new LogData (level, new StackFrame (2, true), message);
|
||||
_output (data, _file);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
data = new LogData (LogLevel.Fatal, new StackFrame (0, true), ex.Message);
|
||||
Console.WriteLine (data.ToString ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeToFile (string value, string path)
|
||||
{
|
||||
using (var writer = new StreamWriter (path, true))
|
||||
using (var syncWriter = TextWriter.Synchronized (writer))
|
||||
syncWriter.WriteLine (value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Debug"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the current logging level is higher than <see cref="LogLevel.Debug"/>,
|
||||
/// this method doesn't output <paramref name="message"/> as a log.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that represents the message to output as a log.
|
||||
/// </param>
|
||||
public void Debug (string message)
|
||||
{
|
||||
if (_level > LogLevel.Debug)
|
||||
return;
|
||||
|
||||
output (message, LogLevel.Debug);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Error"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the current logging level is higher than <see cref="LogLevel.Error"/>,
|
||||
/// this method doesn't output <paramref name="message"/> as a log.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that represents the message to output as a log.
|
||||
/// </param>
|
||||
public void Error (string message)
|
||||
{
|
||||
if (_level > LogLevel.Error)
|
||||
return;
|
||||
|
||||
output (message, LogLevel.Error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Fatal"/>.
|
||||
/// </summary>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that represents the message to output as a log.
|
||||
/// </param>
|
||||
public void Fatal (string message)
|
||||
{
|
||||
output (message, LogLevel.Fatal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Info"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the current logging level is higher than <see cref="LogLevel.Info"/>,
|
||||
/// this method doesn't output <paramref name="message"/> as a log.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that represents the message to output as a log.
|
||||
/// </param>
|
||||
public void Info (string message)
|
||||
{
|
||||
if (_level > LogLevel.Info)
|
||||
return;
|
||||
|
||||
output (message, LogLevel.Info);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Trace"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the current logging level is higher than <see cref="LogLevel.Trace"/>,
|
||||
/// this method doesn't output <paramref name="message"/> as a log.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that represents the message to output as a log.
|
||||
/// </param>
|
||||
public void Trace (string message)
|
||||
{
|
||||
if (_level > LogLevel.Trace)
|
||||
return;
|
||||
|
||||
output (message, LogLevel.Trace);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs <paramref name="message"/> as a log with <see cref="LogLevel.Warn"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the current logging level is higher than <see cref="LogLevel.Warn"/>,
|
||||
/// this method doesn't output <paramref name="message"/> as a log.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that represents the message to output as a log.
|
||||
/// </param>
|
||||
public void Warn (string message)
|
||||
{
|
||||
if (_level > LogLevel.Warn)
|
||||
return;
|
||||
|
||||
output (message, LogLevel.Warn);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,51 +1,51 @@
|
||||
#region License
|
||||
/*
|
||||
* Mask.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates whether the payload data of a WebSocket frame is masked.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
internal enum Mask : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Equivalent to numeric value 0. Indicates not masked.
|
||||
/// </summary>
|
||||
Off = 0x0,
|
||||
/// <summary>
|
||||
/// Equivalent to numeric value 1. Indicates masked.
|
||||
/// </summary>
|
||||
On = 0x1
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* Mask.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates whether the payload data of a WebSocket frame is masked.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
internal enum Mask : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Equivalent to numeric value 0. Indicates not masked.
|
||||
/// </summary>
|
||||
Off = 0x0,
|
||||
/// <summary>
|
||||
/// Equivalent to numeric value 1. Indicates masked.
|
||||
/// </summary>
|
||||
On = 0x1
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,183 +1,183 @@
|
||||
#region License
|
||||
/*
|
||||
* MessageEventArgs.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2016 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the event data for the <see cref="WebSocket.OnMessage"/> event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// That event occurs when the <see cref="WebSocket"/> receives
|
||||
/// a message or a ping if the <see cref="WebSocket.EmitOnPing"/>
|
||||
/// property is set to <c>true</c>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If you would like to get the message data, you should access
|
||||
/// the <see cref="Data"/> or <see cref="RawData"/> property.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class MessageEventArgs : EventArgs
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private string _data;
|
||||
private bool _dataSet;
|
||||
private Opcode _opcode;
|
||||
private byte[] _rawData;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal MessageEventArgs (WebSocketFrame frame)
|
||||
{
|
||||
_opcode = frame.Opcode;
|
||||
_rawData = frame.PayloadData.ApplicationData;
|
||||
}
|
||||
|
||||
internal MessageEventArgs (Opcode opcode, byte[] rawData)
|
||||
{
|
||||
if ((ulong) rawData.LongLength > PayloadData.MaxLength)
|
||||
throw new WebSocketException (CloseStatusCode.TooBig);
|
||||
|
||||
_opcode = opcode;
|
||||
_rawData = rawData;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the opcode for the message.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see cref="Opcode.Text"/>, <see cref="Opcode.Binary"/>,
|
||||
/// or <see cref="Opcode.Ping"/>.
|
||||
/// </value>
|
||||
internal Opcode Opcode {
|
||||
get {
|
||||
return _opcode;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the message data as a <see cref="string"/>.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// 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;
|
||||
/// otherwise, <see langword="null"/>.
|
||||
/// </value>
|
||||
public string Data {
|
||||
get {
|
||||
setData ();
|
||||
return _data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the message type is binary.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if the message type is binary; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool IsBinary {
|
||||
get {
|
||||
return _opcode == Opcode.Binary;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the message type is ping.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if the message type is ping; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool IsPing {
|
||||
get {
|
||||
return _opcode == Opcode.Ping;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the message type is text.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if the message type is text; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool IsText {
|
||||
get {
|
||||
return _opcode == Opcode.Text;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the message data as an array of <see cref="byte"/>.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// An array of <see cref="byte"/> that represents the message data.
|
||||
/// </value>
|
||||
public byte[] RawData {
|
||||
get {
|
||||
setData ();
|
||||
return _rawData;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void setData ()
|
||||
{
|
||||
if (_dataSet)
|
||||
return;
|
||||
|
||||
if (_opcode == Opcode.Binary) {
|
||||
_dataSet = true;
|
||||
return;
|
||||
}
|
||||
|
||||
string data;
|
||||
if (_rawData.TryGetUTF8DecodedString (out data))
|
||||
_data = data;
|
||||
|
||||
_dataSet = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* MessageEventArgs.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2016 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the event data for the <see cref="WebSocket.OnMessage"/> event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// That event occurs when the <see cref="WebSocket"/> receives
|
||||
/// a message or a ping if the <see cref="WebSocket.EmitOnPing"/>
|
||||
/// property is set to <c>true</c>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If you would like to get the message data, you should access
|
||||
/// the <see cref="Data"/> or <see cref="RawData"/> property.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class MessageEventArgs : EventArgs
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private string _data;
|
||||
private bool _dataSet;
|
||||
private Opcode _opcode;
|
||||
private byte[] _rawData;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal MessageEventArgs (WebSocketFrame frame)
|
||||
{
|
||||
_opcode = frame.Opcode;
|
||||
_rawData = frame.PayloadData.ApplicationData;
|
||||
}
|
||||
|
||||
internal MessageEventArgs (Opcode opcode, byte[] rawData)
|
||||
{
|
||||
if ((ulong) rawData.LongLength > PayloadData.MaxLength)
|
||||
throw new WebSocketException (CloseStatusCode.TooBig);
|
||||
|
||||
_opcode = opcode;
|
||||
_rawData = rawData;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the opcode for the message.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see cref="Opcode.Text"/>, <see cref="Opcode.Binary"/>,
|
||||
/// or <see cref="Opcode.Ping"/>.
|
||||
/// </value>
|
||||
internal Opcode Opcode {
|
||||
get {
|
||||
return _opcode;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the message data as a <see cref="string"/>.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// 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;
|
||||
/// otherwise, <see langword="null"/>.
|
||||
/// </value>
|
||||
public string Data {
|
||||
get {
|
||||
setData ();
|
||||
return _data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the message type is binary.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if the message type is binary; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool IsBinary {
|
||||
get {
|
||||
return _opcode == Opcode.Binary;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the message type is ping.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if the message type is ping; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool IsPing {
|
||||
get {
|
||||
return _opcode == Opcode.Ping;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the message type is text.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if the message type is text; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool IsText {
|
||||
get {
|
||||
return _opcode == Opcode.Text;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the message data as an array of <see cref="byte"/>.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// An array of <see cref="byte"/> that represents the message data.
|
||||
/// </value>
|
||||
public byte[] RawData {
|
||||
get {
|
||||
setData ();
|
||||
return _rawData;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void setData ()
|
||||
{
|
||||
if (_dataSet)
|
||||
return;
|
||||
|
||||
if (_opcode == Opcode.Binary) {
|
||||
_dataSet = true;
|
||||
return;
|
||||
}
|
||||
|
||||
string data;
|
||||
if (_rawData.TryGetUTF8DecodedString (out data))
|
||||
_data = data;
|
||||
|
||||
_dataSet = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,151 +1,151 @@
|
||||
#region License
|
||||
/*
|
||||
* AuthenticationBase.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2014 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Text;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
internal abstract class AuthenticationBase
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private AuthenticationSchemes _scheme;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Fields
|
||||
|
||||
internal NameValueCollection Parameters;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Constructors
|
||||
|
||||
protected AuthenticationBase (AuthenticationSchemes scheme, NameValueCollection parameters)
|
||||
{
|
||||
_scheme = scheme;
|
||||
Parameters = parameters;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public string Algorithm {
|
||||
get {
|
||||
return Parameters["algorithm"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Nonce {
|
||||
get {
|
||||
return Parameters["nonce"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Opaque {
|
||||
get {
|
||||
return Parameters["opaque"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Qop {
|
||||
get {
|
||||
return Parameters["qop"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Realm {
|
||||
get {
|
||||
return Parameters["realm"];
|
||||
}
|
||||
}
|
||||
|
||||
public AuthenticationSchemes Scheme {
|
||||
get {
|
||||
return _scheme;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
internal static string CreateNonceValue ()
|
||||
{
|
||||
var src = new byte[16];
|
||||
var rand = new Random ();
|
||||
rand.NextBytes (src);
|
||||
|
||||
var res = new StringBuilder (32);
|
||||
foreach (var b in src)
|
||||
res.Append (b.ToString ("x2"));
|
||||
|
||||
return res.ToString ();
|
||||
}
|
||||
|
||||
internal static NameValueCollection ParseParameters (string value)
|
||||
{
|
||||
var res = new NameValueCollection ();
|
||||
foreach (var param in value.SplitHeaderValue (',')) {
|
||||
var i = param.IndexOf ('=');
|
||||
var name = i > 0 ? param.Substring (0, i).Trim () : null;
|
||||
var val = i < 0
|
||||
? param.Trim ().Trim ('"')
|
||||
: i < param.Length - 1
|
||||
? param.Substring (i + 1).Trim ().Trim ('"')
|
||||
: String.Empty;
|
||||
|
||||
res.Add (name, val);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
internal abstract string ToBasicString ();
|
||||
|
||||
internal abstract string ToDigestString ();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return _scheme == AuthenticationSchemes.Basic
|
||||
? ToBasicString ()
|
||||
: _scheme == AuthenticationSchemes.Digest
|
||||
? ToDigestString ()
|
||||
: String.Empty;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* AuthenticationBase.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2014 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Text;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
internal abstract class AuthenticationBase
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private AuthenticationSchemes _scheme;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Fields
|
||||
|
||||
internal NameValueCollection Parameters;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Constructors
|
||||
|
||||
protected AuthenticationBase (AuthenticationSchemes scheme, NameValueCollection parameters)
|
||||
{
|
||||
_scheme = scheme;
|
||||
Parameters = parameters;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public string Algorithm {
|
||||
get {
|
||||
return Parameters["algorithm"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Nonce {
|
||||
get {
|
||||
return Parameters["nonce"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Opaque {
|
||||
get {
|
||||
return Parameters["opaque"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Qop {
|
||||
get {
|
||||
return Parameters["qop"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Realm {
|
||||
get {
|
||||
return Parameters["realm"];
|
||||
}
|
||||
}
|
||||
|
||||
public AuthenticationSchemes Scheme {
|
||||
get {
|
||||
return _scheme;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
internal static string CreateNonceValue ()
|
||||
{
|
||||
var src = new byte[16];
|
||||
var rand = new Random ();
|
||||
rand.NextBytes (src);
|
||||
|
||||
var res = new StringBuilder (32);
|
||||
foreach (var b in src)
|
||||
res.Append (b.ToString ("x2"));
|
||||
|
||||
return res.ToString ();
|
||||
}
|
||||
|
||||
internal static NameValueCollection ParseParameters (string value)
|
||||
{
|
||||
var res = new NameValueCollection ();
|
||||
foreach (var param in value.SplitHeaderValue (',')) {
|
||||
var i = param.IndexOf ('=');
|
||||
var name = i > 0 ? param.Substring (0, i).Trim () : null;
|
||||
var val = i < 0
|
||||
? param.Trim ().Trim ('"')
|
||||
: i < param.Length - 1
|
||||
? param.Substring (i + 1).Trim ().Trim ('"')
|
||||
: String.Empty;
|
||||
|
||||
res.Add (name, val);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
internal abstract string ToBasicString ();
|
||||
|
||||
internal abstract string ToDigestString ();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return _scheme == AuthenticationSchemes.Basic
|
||||
? ToBasicString ()
|
||||
: _scheme == AuthenticationSchemes.Digest
|
||||
? ToDigestString ()
|
||||
: String.Empty;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,146 +1,146 @@
|
||||
#region License
|
||||
/*
|
||||
* AuthenticationChallenge.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2013-2014 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Text;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
internal class AuthenticationChallenge : AuthenticationBase
|
||||
{
|
||||
#region Private Constructors
|
||||
|
||||
private AuthenticationChallenge (AuthenticationSchemes scheme, NameValueCollection parameters)
|
||||
: base (scheme, parameters)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal AuthenticationChallenge (AuthenticationSchemes scheme, string realm)
|
||||
: base (scheme, new NameValueCollection ())
|
||||
{
|
||||
Parameters["realm"] = realm;
|
||||
if (scheme == AuthenticationSchemes.Digest) {
|
||||
Parameters["nonce"] = CreateNonceValue ();
|
||||
Parameters["algorithm"] = "MD5";
|
||||
Parameters["qop"] = "auth";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public string Domain {
|
||||
get {
|
||||
return Parameters["domain"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Stale {
|
||||
get {
|
||||
return Parameters["stale"];
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
internal static AuthenticationChallenge CreateBasicChallenge (string realm)
|
||||
{
|
||||
return new AuthenticationChallenge (AuthenticationSchemes.Basic, realm);
|
||||
}
|
||||
|
||||
internal static AuthenticationChallenge CreateDigestChallenge (string realm)
|
||||
{
|
||||
return new AuthenticationChallenge (AuthenticationSchemes.Digest, realm);
|
||||
}
|
||||
|
||||
internal static AuthenticationChallenge Parse (string value)
|
||||
{
|
||||
var chal = value.Split (new[] { ' ' }, 2);
|
||||
if (chal.Length != 2)
|
||||
return null;
|
||||
|
||||
var schm = chal[0].ToLower ();
|
||||
return schm == "basic"
|
||||
? new AuthenticationChallenge (
|
||||
AuthenticationSchemes.Basic, ParseParameters (chal[1]))
|
||||
: schm == "digest"
|
||||
? new AuthenticationChallenge (
|
||||
AuthenticationSchemes.Digest, ParseParameters (chal[1]))
|
||||
: null;
|
||||
}
|
||||
|
||||
internal override string ToBasicString ()
|
||||
{
|
||||
return String.Format ("Basic realm=\"{0}\"", Parameters["realm"]);
|
||||
}
|
||||
|
||||
internal override string ToDigestString ()
|
||||
{
|
||||
var output = new StringBuilder (128);
|
||||
|
||||
var domain = Parameters["domain"];
|
||||
if (domain != null)
|
||||
output.AppendFormat (
|
||||
"Digest realm=\"{0}\", domain=\"{1}\", nonce=\"{2}\"",
|
||||
Parameters["realm"],
|
||||
domain,
|
||||
Parameters["nonce"]);
|
||||
else
|
||||
output.AppendFormat (
|
||||
"Digest realm=\"{0}\", nonce=\"{1}\"", Parameters["realm"], Parameters["nonce"]);
|
||||
|
||||
var opaque = Parameters["opaque"];
|
||||
if (opaque != null)
|
||||
output.AppendFormat (", opaque=\"{0}\"", opaque);
|
||||
|
||||
var stale = Parameters["stale"];
|
||||
if (stale != null)
|
||||
output.AppendFormat (", stale={0}", stale);
|
||||
|
||||
var algo = Parameters["algorithm"];
|
||||
if (algo != null)
|
||||
output.AppendFormat (", algorithm={0}", algo);
|
||||
|
||||
var qop = Parameters["qop"];
|
||||
if (qop != null)
|
||||
output.AppendFormat (", qop=\"{0}\"", qop);
|
||||
|
||||
return output.ToString ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* AuthenticationChallenge.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2013-2014 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Text;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
internal class AuthenticationChallenge : AuthenticationBase
|
||||
{
|
||||
#region Private Constructors
|
||||
|
||||
private AuthenticationChallenge (AuthenticationSchemes scheme, NameValueCollection parameters)
|
||||
: base (scheme, parameters)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal AuthenticationChallenge (AuthenticationSchemes scheme, string realm)
|
||||
: base (scheme, new NameValueCollection ())
|
||||
{
|
||||
Parameters["realm"] = realm;
|
||||
if (scheme == AuthenticationSchemes.Digest) {
|
||||
Parameters["nonce"] = CreateNonceValue ();
|
||||
Parameters["algorithm"] = "MD5";
|
||||
Parameters["qop"] = "auth";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public string Domain {
|
||||
get {
|
||||
return Parameters["domain"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Stale {
|
||||
get {
|
||||
return Parameters["stale"];
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
internal static AuthenticationChallenge CreateBasicChallenge (string realm)
|
||||
{
|
||||
return new AuthenticationChallenge (AuthenticationSchemes.Basic, realm);
|
||||
}
|
||||
|
||||
internal static AuthenticationChallenge CreateDigestChallenge (string realm)
|
||||
{
|
||||
return new AuthenticationChallenge (AuthenticationSchemes.Digest, realm);
|
||||
}
|
||||
|
||||
internal static AuthenticationChallenge Parse (string value)
|
||||
{
|
||||
var chal = value.Split (new[] { ' ' }, 2);
|
||||
if (chal.Length != 2)
|
||||
return null;
|
||||
|
||||
var schm = chal[0].ToLower ();
|
||||
return schm == "basic"
|
||||
? new AuthenticationChallenge (
|
||||
AuthenticationSchemes.Basic, ParseParameters (chal[1]))
|
||||
: schm == "digest"
|
||||
? new AuthenticationChallenge (
|
||||
AuthenticationSchemes.Digest, ParseParameters (chal[1]))
|
||||
: null;
|
||||
}
|
||||
|
||||
internal override string ToBasicString ()
|
||||
{
|
||||
return String.Format ("Basic realm=\"{0}\"", Parameters["realm"]);
|
||||
}
|
||||
|
||||
internal override string ToDigestString ()
|
||||
{
|
||||
var output = new StringBuilder (128);
|
||||
|
||||
var domain = Parameters["domain"];
|
||||
if (domain != null)
|
||||
output.AppendFormat (
|
||||
"Digest realm=\"{0}\", domain=\"{1}\", nonce=\"{2}\"",
|
||||
Parameters["realm"],
|
||||
domain,
|
||||
Parameters["nonce"]);
|
||||
else
|
||||
output.AppendFormat (
|
||||
"Digest realm=\"{0}\", nonce=\"{1}\"", Parameters["realm"], Parameters["nonce"]);
|
||||
|
||||
var opaque = Parameters["opaque"];
|
||||
if (opaque != null)
|
||||
output.AppendFormat (", opaque=\"{0}\"", opaque);
|
||||
|
||||
var stale = Parameters["stale"];
|
||||
if (stale != null)
|
||||
output.AppendFormat (", stale={0}", stale);
|
||||
|
||||
var algo = Parameters["algorithm"];
|
||||
if (algo != null)
|
||||
output.AppendFormat (", algorithm={0}", algo);
|
||||
|
||||
var qop = Parameters["qop"];
|
||||
if (qop != null)
|
||||
output.AppendFormat (", qop=\"{0}\"", qop);
|
||||
|
||||
return output.ToString ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,323 +1,323 @@
|
||||
#region License
|
||||
/*
|
||||
* AuthenticationResponse.cs
|
||||
*
|
||||
* ParseBasicCredentials is derived from System.Net.HttpListenerContext.cs of Mono
|
||||
* (http://www.mono-project.com).
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
|
||||
* Copyright (c) 2013-2014 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
internal class AuthenticationResponse : AuthenticationBase
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private uint _nonceCount;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Constructors
|
||||
|
||||
private AuthenticationResponse (AuthenticationSchemes scheme, NameValueCollection parameters)
|
||||
: base (scheme, parameters)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal AuthenticationResponse (NetworkCredential credentials)
|
||||
: this (AuthenticationSchemes.Basic, new NameValueCollection (), credentials, 0)
|
||||
{
|
||||
}
|
||||
|
||||
internal AuthenticationResponse (
|
||||
AuthenticationChallenge challenge, NetworkCredential credentials, uint nonceCount)
|
||||
: this (challenge.Scheme, challenge.Parameters, credentials, nonceCount)
|
||||
{
|
||||
}
|
||||
|
||||
internal AuthenticationResponse (
|
||||
AuthenticationSchemes scheme,
|
||||
NameValueCollection parameters,
|
||||
NetworkCredential credentials,
|
||||
uint nonceCount)
|
||||
: base (scheme, parameters)
|
||||
{
|
||||
Parameters["username"] = credentials.Username;
|
||||
Parameters["password"] = credentials.Password;
|
||||
Parameters["uri"] = credentials.Domain;
|
||||
_nonceCount = nonceCount;
|
||||
if (scheme == AuthenticationSchemes.Digest)
|
||||
initAsDigest ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Properties
|
||||
|
||||
internal uint NonceCount {
|
||||
get {
|
||||
return _nonceCount < UInt32.MaxValue
|
||||
? _nonceCount
|
||||
: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public string Cnonce {
|
||||
get {
|
||||
return Parameters["cnonce"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Nc {
|
||||
get {
|
||||
return Parameters["nc"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Password {
|
||||
get {
|
||||
return Parameters["password"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Response {
|
||||
get {
|
||||
return Parameters["response"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Uri {
|
||||
get {
|
||||
return Parameters["uri"];
|
||||
}
|
||||
}
|
||||
|
||||
public string UserName {
|
||||
get {
|
||||
return Parameters["username"];
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private static string createA1 (string username, string password, string realm)
|
||||
{
|
||||
return String.Format ("{0}:{1}:{2}", username, realm, password);
|
||||
}
|
||||
|
||||
private static string createA1 (
|
||||
string username, string password, string realm, string nonce, string cnonce)
|
||||
{
|
||||
return String.Format (
|
||||
"{0}:{1}:{2}", hash (createA1 (username, password, realm)), nonce, cnonce);
|
||||
}
|
||||
|
||||
private static string createA2 (string method, string uri)
|
||||
{
|
||||
return String.Format ("{0}:{1}", method, uri);
|
||||
}
|
||||
|
||||
private static string createA2 (string method, string uri, string entity)
|
||||
{
|
||||
return String.Format ("{0}:{1}:{2}", method, uri, hash (entity));
|
||||
}
|
||||
|
||||
private static string hash (string value)
|
||||
{
|
||||
var src = Encoding.UTF8.GetBytes (value);
|
||||
var md5 = MD5.Create ();
|
||||
var hashed = md5.ComputeHash (src);
|
||||
|
||||
var res = new StringBuilder (64);
|
||||
foreach (var b in hashed)
|
||||
res.Append (b.ToString ("x2"));
|
||||
|
||||
return res.ToString ();
|
||||
}
|
||||
|
||||
private void initAsDigest ()
|
||||
{
|
||||
var qops = Parameters["qop"];
|
||||
if (qops != null) {
|
||||
if (qops.Split (',').Contains (qop => qop.Trim ().ToLower () == "auth")) {
|
||||
Parameters["qop"] = "auth";
|
||||
Parameters["cnonce"] = CreateNonceValue ();
|
||||
Parameters["nc"] = String.Format ("{0:x8}", ++_nonceCount);
|
||||
}
|
||||
else {
|
||||
Parameters["qop"] = null;
|
||||
}
|
||||
}
|
||||
|
||||
Parameters["method"] = "GET";
|
||||
Parameters["response"] = CreateRequestDigest (Parameters);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
internal static string CreateRequestDigest (NameValueCollection parameters)
|
||||
{
|
||||
var user = parameters["username"];
|
||||
var pass = parameters["password"];
|
||||
var realm = parameters["realm"];
|
||||
var nonce = parameters["nonce"];
|
||||
var uri = parameters["uri"];
|
||||
var algo = parameters["algorithm"];
|
||||
var qop = parameters["qop"];
|
||||
var cnonce = parameters["cnonce"];
|
||||
var nc = parameters["nc"];
|
||||
var method = parameters["method"];
|
||||
|
||||
var a1 = algo != null && algo.ToLower () == "md5-sess"
|
||||
? createA1 (user, pass, realm, nonce, cnonce)
|
||||
: createA1 (user, pass, realm);
|
||||
|
||||
var a2 = qop != null && qop.ToLower () == "auth-int"
|
||||
? createA2 (method, uri, parameters["entity"])
|
||||
: createA2 (method, uri);
|
||||
|
||||
var secret = hash (a1);
|
||||
var data = qop != null
|
||||
? String.Format ("{0}:{1}:{2}:{3}:{4}", nonce, nc, cnonce, qop, hash (a2))
|
||||
: String.Format ("{0}:{1}", nonce, hash (a2));
|
||||
|
||||
return hash (String.Format ("{0}:{1}", secret, data));
|
||||
}
|
||||
|
||||
internal static AuthenticationResponse Parse (string value)
|
||||
{
|
||||
try {
|
||||
var cred = value.Split (new[] { ' ' }, 2);
|
||||
if (cred.Length != 2)
|
||||
return null;
|
||||
|
||||
var schm = cred[0].ToLower ();
|
||||
return schm == "basic"
|
||||
? new AuthenticationResponse (
|
||||
AuthenticationSchemes.Basic, ParseBasicCredentials (cred[1]))
|
||||
: schm == "digest"
|
||||
? new AuthenticationResponse (
|
||||
AuthenticationSchemes.Digest, ParseParameters (cred[1]))
|
||||
: null;
|
||||
}
|
||||
catch {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static NameValueCollection ParseBasicCredentials (string value)
|
||||
{
|
||||
// Decode the basic-credentials (a Base64 encoded string).
|
||||
var userPass = Encoding.Default.GetString (Convert.FromBase64String (value));
|
||||
|
||||
// The format is [<domain>\]<username>:<password>.
|
||||
var i = userPass.IndexOf (':');
|
||||
var user = userPass.Substring (0, i);
|
||||
var pass = i < userPass.Length - 1 ? userPass.Substring (i + 1) : String.Empty;
|
||||
|
||||
// Check if 'domain' exists.
|
||||
i = user.IndexOf ('\\');
|
||||
if (i > -1)
|
||||
user = user.Substring (i + 1);
|
||||
|
||||
var res = new NameValueCollection ();
|
||||
res["username"] = user;
|
||||
res["password"] = pass;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
internal override string ToBasicString ()
|
||||
{
|
||||
var userPass = String.Format ("{0}:{1}", Parameters["username"], Parameters["password"]);
|
||||
var cred = Convert.ToBase64String (Encoding.UTF8.GetBytes (userPass));
|
||||
|
||||
return "Basic " + cred;
|
||||
}
|
||||
|
||||
internal override string ToDigestString ()
|
||||
{
|
||||
var output = new StringBuilder (256);
|
||||
output.AppendFormat (
|
||||
"Digest username=\"{0}\", realm=\"{1}\", nonce=\"{2}\", uri=\"{3}\", response=\"{4}\"",
|
||||
Parameters["username"],
|
||||
Parameters["realm"],
|
||||
Parameters["nonce"],
|
||||
Parameters["uri"],
|
||||
Parameters["response"]);
|
||||
|
||||
var opaque = Parameters["opaque"];
|
||||
if (opaque != null)
|
||||
output.AppendFormat (", opaque=\"{0}\"", opaque);
|
||||
|
||||
var algo = Parameters["algorithm"];
|
||||
if (algo != null)
|
||||
output.AppendFormat (", algorithm={0}", algo);
|
||||
|
||||
var qop = Parameters["qop"];
|
||||
if (qop != null)
|
||||
output.AppendFormat (
|
||||
", qop={0}, cnonce=\"{1}\", nc={2}", qop, Parameters["cnonce"], Parameters["nc"]);
|
||||
|
||||
return output.ToString ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public IIdentity ToIdentity ()
|
||||
{
|
||||
var schm = Scheme;
|
||||
return schm == AuthenticationSchemes.Basic
|
||||
? new HttpBasicIdentity (Parameters["username"], Parameters["password"]) as IIdentity
|
||||
: schm == AuthenticationSchemes.Digest
|
||||
? new HttpDigestIdentity (Parameters)
|
||||
: null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* AuthenticationResponse.cs
|
||||
*
|
||||
* ParseBasicCredentials is derived from System.Net.HttpListenerContext.cs of Mono
|
||||
* (http://www.mono-project.com).
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
|
||||
* Copyright (c) 2013-2014 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
internal class AuthenticationResponse : AuthenticationBase
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private uint _nonceCount;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Constructors
|
||||
|
||||
private AuthenticationResponse (AuthenticationSchemes scheme, NameValueCollection parameters)
|
||||
: base (scheme, parameters)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal AuthenticationResponse (NetworkCredential credentials)
|
||||
: this (AuthenticationSchemes.Basic, new NameValueCollection (), credentials, 0)
|
||||
{
|
||||
}
|
||||
|
||||
internal AuthenticationResponse (
|
||||
AuthenticationChallenge challenge, NetworkCredential credentials, uint nonceCount)
|
||||
: this (challenge.Scheme, challenge.Parameters, credentials, nonceCount)
|
||||
{
|
||||
}
|
||||
|
||||
internal AuthenticationResponse (
|
||||
AuthenticationSchemes scheme,
|
||||
NameValueCollection parameters,
|
||||
NetworkCredential credentials,
|
||||
uint nonceCount)
|
||||
: base (scheme, parameters)
|
||||
{
|
||||
Parameters["username"] = credentials.Username;
|
||||
Parameters["password"] = credentials.Password;
|
||||
Parameters["uri"] = credentials.Domain;
|
||||
_nonceCount = nonceCount;
|
||||
if (scheme == AuthenticationSchemes.Digest)
|
||||
initAsDigest ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Properties
|
||||
|
||||
internal uint NonceCount {
|
||||
get {
|
||||
return _nonceCount < UInt32.MaxValue
|
||||
? _nonceCount
|
||||
: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public string Cnonce {
|
||||
get {
|
||||
return Parameters["cnonce"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Nc {
|
||||
get {
|
||||
return Parameters["nc"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Password {
|
||||
get {
|
||||
return Parameters["password"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Response {
|
||||
get {
|
||||
return Parameters["response"];
|
||||
}
|
||||
}
|
||||
|
||||
public string Uri {
|
||||
get {
|
||||
return Parameters["uri"];
|
||||
}
|
||||
}
|
||||
|
||||
public string UserName {
|
||||
get {
|
||||
return Parameters["username"];
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private static string createA1 (string username, string password, string realm)
|
||||
{
|
||||
return String.Format ("{0}:{1}:{2}", username, realm, password);
|
||||
}
|
||||
|
||||
private static string createA1 (
|
||||
string username, string password, string realm, string nonce, string cnonce)
|
||||
{
|
||||
return String.Format (
|
||||
"{0}:{1}:{2}", hash (createA1 (username, password, realm)), nonce, cnonce);
|
||||
}
|
||||
|
||||
private static string createA2 (string method, string uri)
|
||||
{
|
||||
return String.Format ("{0}:{1}", method, uri);
|
||||
}
|
||||
|
||||
private static string createA2 (string method, string uri, string entity)
|
||||
{
|
||||
return String.Format ("{0}:{1}:{2}", method, uri, hash (entity));
|
||||
}
|
||||
|
||||
private static string hash (string value)
|
||||
{
|
||||
var src = Encoding.UTF8.GetBytes (value);
|
||||
var md5 = MD5.Create ();
|
||||
var hashed = md5.ComputeHash (src);
|
||||
|
||||
var res = new StringBuilder (64);
|
||||
foreach (var b in hashed)
|
||||
res.Append (b.ToString ("x2"));
|
||||
|
||||
return res.ToString ();
|
||||
}
|
||||
|
||||
private void initAsDigest ()
|
||||
{
|
||||
var qops = Parameters["qop"];
|
||||
if (qops != null) {
|
||||
if (qops.Split (',').Contains (qop => qop.Trim ().ToLower () == "auth")) {
|
||||
Parameters["qop"] = "auth";
|
||||
Parameters["cnonce"] = CreateNonceValue ();
|
||||
Parameters["nc"] = String.Format ("{0:x8}", ++_nonceCount);
|
||||
}
|
||||
else {
|
||||
Parameters["qop"] = null;
|
||||
}
|
||||
}
|
||||
|
||||
Parameters["method"] = "GET";
|
||||
Parameters["response"] = CreateRequestDigest (Parameters);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
internal static string CreateRequestDigest (NameValueCollection parameters)
|
||||
{
|
||||
var user = parameters["username"];
|
||||
var pass = parameters["password"];
|
||||
var realm = parameters["realm"];
|
||||
var nonce = parameters["nonce"];
|
||||
var uri = parameters["uri"];
|
||||
var algo = parameters["algorithm"];
|
||||
var qop = parameters["qop"];
|
||||
var cnonce = parameters["cnonce"];
|
||||
var nc = parameters["nc"];
|
||||
var method = parameters["method"];
|
||||
|
||||
var a1 = algo != null && algo.ToLower () == "md5-sess"
|
||||
? createA1 (user, pass, realm, nonce, cnonce)
|
||||
: createA1 (user, pass, realm);
|
||||
|
||||
var a2 = qop != null && qop.ToLower () == "auth-int"
|
||||
? createA2 (method, uri, parameters["entity"])
|
||||
: createA2 (method, uri);
|
||||
|
||||
var secret = hash (a1);
|
||||
var data = qop != null
|
||||
? String.Format ("{0}:{1}:{2}:{3}:{4}", nonce, nc, cnonce, qop, hash (a2))
|
||||
: String.Format ("{0}:{1}", nonce, hash (a2));
|
||||
|
||||
return hash (String.Format ("{0}:{1}", secret, data));
|
||||
}
|
||||
|
||||
internal static AuthenticationResponse Parse (string value)
|
||||
{
|
||||
try {
|
||||
var cred = value.Split (new[] { ' ' }, 2);
|
||||
if (cred.Length != 2)
|
||||
return null;
|
||||
|
||||
var schm = cred[0].ToLower ();
|
||||
return schm == "basic"
|
||||
? new AuthenticationResponse (
|
||||
AuthenticationSchemes.Basic, ParseBasicCredentials (cred[1]))
|
||||
: schm == "digest"
|
||||
? new AuthenticationResponse (
|
||||
AuthenticationSchemes.Digest, ParseParameters (cred[1]))
|
||||
: null;
|
||||
}
|
||||
catch {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static NameValueCollection ParseBasicCredentials (string value)
|
||||
{
|
||||
// Decode the basic-credentials (a Base64 encoded string).
|
||||
var userPass = Encoding.Default.GetString (Convert.FromBase64String (value));
|
||||
|
||||
// The format is [<domain>\]<username>:<password>.
|
||||
var i = userPass.IndexOf (':');
|
||||
var user = userPass.Substring (0, i);
|
||||
var pass = i < userPass.Length - 1 ? userPass.Substring (i + 1) : String.Empty;
|
||||
|
||||
// Check if 'domain' exists.
|
||||
i = user.IndexOf ('\\');
|
||||
if (i > -1)
|
||||
user = user.Substring (i + 1);
|
||||
|
||||
var res = new NameValueCollection ();
|
||||
res["username"] = user;
|
||||
res["password"] = pass;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
internal override string ToBasicString ()
|
||||
{
|
||||
var userPass = String.Format ("{0}:{1}", Parameters["username"], Parameters["password"]);
|
||||
var cred = Convert.ToBase64String (Encoding.UTF8.GetBytes (userPass));
|
||||
|
||||
return "Basic " + cred;
|
||||
}
|
||||
|
||||
internal override string ToDigestString ()
|
||||
{
|
||||
var output = new StringBuilder (256);
|
||||
output.AppendFormat (
|
||||
"Digest username=\"{0}\", realm=\"{1}\", nonce=\"{2}\", uri=\"{3}\", response=\"{4}\"",
|
||||
Parameters["username"],
|
||||
Parameters["realm"],
|
||||
Parameters["nonce"],
|
||||
Parameters["uri"],
|
||||
Parameters["response"]);
|
||||
|
||||
var opaque = Parameters["opaque"];
|
||||
if (opaque != null)
|
||||
output.AppendFormat (", opaque=\"{0}\"", opaque);
|
||||
|
||||
var algo = Parameters["algorithm"];
|
||||
if (algo != null)
|
||||
output.AppendFormat (", algorithm={0}", algo);
|
||||
|
||||
var qop = Parameters["qop"];
|
||||
if (qop != null)
|
||||
output.AppendFormat (
|
||||
", qop={0}, cnonce=\"{1}\", nc={2}", qop, Parameters["cnonce"], Parameters["nc"]);
|
||||
|
||||
return output.ToString ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public IIdentity ToIdentity ()
|
||||
{
|
||||
var schm = Scheme;
|
||||
return schm == AuthenticationSchemes.Basic
|
||||
? new HttpBasicIdentity (Parameters["username"], Parameters["password"]) as IIdentity
|
||||
: schm == AuthenticationSchemes.Digest
|
||||
? new HttpDigestIdentity (Parameters)
|
||||
: null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,66 +1,66 @@
|
||||
#region License
|
||||
/*
|
||||
* AuthenticationSchemes.cs
|
||||
*
|
||||
* This code is derived from AuthenticationSchemes.cs (System.Net) of Mono
|
||||
* (http://www.mono-project.com).
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
|
||||
* Copyright (c) 2012-2016 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region Authors
|
||||
/*
|
||||
* Authors:
|
||||
* - Atsushi Enomoto <atsushi@ximian.com>
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the scheme for authentication.
|
||||
/// </summary>
|
||||
public enum AuthenticationSchemes
|
||||
{
|
||||
/// <summary>
|
||||
/// No authentication is allowed.
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// Specifies digest authentication.
|
||||
/// </summary>
|
||||
Digest = 1,
|
||||
/// <summary>
|
||||
/// Specifies basic authentication.
|
||||
/// </summary>
|
||||
Basic = 8,
|
||||
/// <summary>
|
||||
/// Specifies anonymous authentication.
|
||||
/// </summary>
|
||||
Anonymous = 0x8000
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* AuthenticationSchemes.cs
|
||||
*
|
||||
* This code is derived from AuthenticationSchemes.cs (System.Net) of Mono
|
||||
* (http://www.mono-project.com).
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
|
||||
* Copyright (c) 2012-2016 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region Authors
|
||||
/*
|
||||
* Authors:
|
||||
* - Atsushi Enomoto <atsushi@ximian.com>
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the scheme for authentication.
|
||||
/// </summary>
|
||||
public enum AuthenticationSchemes
|
||||
{
|
||||
/// <summary>
|
||||
/// No authentication is allowed.
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// Specifies digest authentication.
|
||||
/// </summary>
|
||||
Digest = 1,
|
||||
/// <summary>
|
||||
/// Specifies basic authentication.
|
||||
/// </summary>
|
||||
Basic = 8,
|
||||
/// <summary>
|
||||
/// Specifies anonymous authentication.
|
||||
/// </summary>
|
||||
Anonymous = 0x8000
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,91 +1,91 @@
|
||||
#region License
|
||||
/*
|
||||
* Chunk.cs
|
||||
*
|
||||
* This code is derived from ChunkStream.cs (System.Net) of Mono
|
||||
* (http://www.mono-project.com).
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2003 Ximian, Inc (http://www.ximian.com)
|
||||
* Copyright (c) 2014-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region Authors
|
||||
/*
|
||||
* Authors:
|
||||
* - Gonzalo Paniagua Javier <gonzalo@ximian.com>
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
internal class Chunk
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private byte[] _data;
|
||||
private int _offset;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
public Chunk (byte[] data)
|
||||
{
|
||||
_data = data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public int ReadLeft {
|
||||
get {
|
||||
return _data.Length - _offset;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public int Read (byte[] buffer, int offset, int count)
|
||||
{
|
||||
var left = _data.Length - _offset;
|
||||
if (left == 0)
|
||||
return left;
|
||||
|
||||
if (count > left)
|
||||
count = left;
|
||||
|
||||
Buffer.BlockCopy (_data, _offset, buffer, offset, count);
|
||||
_offset += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* Chunk.cs
|
||||
*
|
||||
* This code is derived from ChunkStream.cs (System.Net) of Mono
|
||||
* (http://www.mono-project.com).
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2003 Ximian, Inc (http://www.ximian.com)
|
||||
* Copyright (c) 2014-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region Authors
|
||||
/*
|
||||
* Authors:
|
||||
* - Gonzalo Paniagua Javier <gonzalo@ximian.com>
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
internal class Chunk
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private byte[] _data;
|
||||
private int _offset;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
public Chunk (byte[] data)
|
||||
{
|
||||
_data = data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public int ReadLeft {
|
||||
get {
|
||||
return _data.Length - _offset;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public int Read (byte[] buffer, int offset, int count)
|
||||
{
|
||||
var left = _data.Length - _offset;
|
||||
if (left == 0)
|
||||
return left;
|
||||
|
||||
if (count > left)
|
||||
count = left;
|
||||
|
||||
Buffer.BlockCopy (_data, _offset, buffer, offset, count);
|
||||
_offset += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,360 +1,360 @@
|
||||
#region License
|
||||
/*
|
||||
* ChunkStream.cs
|
||||
*
|
||||
* This code is derived from ChunkStream.cs (System.Net) of Mono
|
||||
* (http://www.mono-project.com).
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2003 Ximian, Inc (http://www.ximian.com)
|
||||
* Copyright (c) 2012-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region Authors
|
||||
/*
|
||||
* Authors:
|
||||
* - Gonzalo Paniagua Javier <gonzalo@ximian.com>
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
internal class ChunkStream
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private int _chunkRead;
|
||||
private int _chunkSize;
|
||||
private List<Chunk> _chunks;
|
||||
private bool _gotIt;
|
||||
private WebHeaderCollection _headers;
|
||||
private StringBuilder _saved;
|
||||
private bool _sawCr;
|
||||
private InputChunkState _state;
|
||||
private int _trailerState;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
public ChunkStream (WebHeaderCollection headers)
|
||||
{
|
||||
_headers = headers;
|
||||
_chunkSize = -1;
|
||||
_chunks = new List<Chunk> ();
|
||||
_saved = new StringBuilder ();
|
||||
}
|
||||
|
||||
public ChunkStream (byte[] buffer, int offset, int count, WebHeaderCollection headers)
|
||||
: this (headers)
|
||||
{
|
||||
Write (buffer, offset, count);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Properties
|
||||
|
||||
internal WebHeaderCollection Headers {
|
||||
get {
|
||||
return _headers;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public int ChunkLeft {
|
||||
get {
|
||||
return _chunkSize - _chunkRead;
|
||||
}
|
||||
}
|
||||
|
||||
public bool WantMore {
|
||||
get {
|
||||
return _state != InputChunkState.End;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private int read (byte[] buffer, int offset, int count)
|
||||
{
|
||||
var nread = 0;
|
||||
|
||||
var cnt = _chunks.Count;
|
||||
for (var i = 0; i < cnt; i++) {
|
||||
var chunk = _chunks[i];
|
||||
if (chunk == null)
|
||||
continue;
|
||||
|
||||
if (chunk.ReadLeft == 0) {
|
||||
_chunks[i] = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
nread += chunk.Read (buffer, offset + nread, count - nread);
|
||||
if (nread == count)
|
||||
break;
|
||||
}
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
private static string removeChunkExtension (string value)
|
||||
{
|
||||
var idx = value.IndexOf (';');
|
||||
return idx > -1 ? value.Substring (0, idx) : value;
|
||||
}
|
||||
|
||||
private InputChunkState seekCrLf (byte[] buffer, ref int offset, int length)
|
||||
{
|
||||
if (!_sawCr) {
|
||||
if (buffer[offset++] != 13)
|
||||
throwProtocolViolation ("CR is expected.");
|
||||
|
||||
_sawCr = true;
|
||||
if (offset == length)
|
||||
return InputChunkState.DataEnded;
|
||||
}
|
||||
|
||||
if (buffer[offset++] != 10)
|
||||
throwProtocolViolation ("LF is expected.");
|
||||
|
||||
return InputChunkState.None;
|
||||
}
|
||||
|
||||
private InputChunkState setChunkSize (byte[] buffer, ref int offset, int length)
|
||||
{
|
||||
byte b = 0;
|
||||
while (offset < length) {
|
||||
b = buffer[offset++];
|
||||
if (_sawCr) {
|
||||
if (b != 10)
|
||||
throwProtocolViolation ("LF is expected.");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (b == 13) {
|
||||
_sawCr = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b == 10)
|
||||
throwProtocolViolation ("LF is unexpected.");
|
||||
|
||||
if (b == 32) // SP
|
||||
_gotIt = true;
|
||||
|
||||
if (!_gotIt)
|
||||
_saved.Append ((char) b);
|
||||
|
||||
if (_saved.Length > 20)
|
||||
throwProtocolViolation ("The chunk size is too long.");
|
||||
}
|
||||
|
||||
if (!_sawCr || b != 10)
|
||||
return InputChunkState.None;
|
||||
|
||||
_chunkRead = 0;
|
||||
try {
|
||||
_chunkSize = Int32.Parse (
|
||||
removeChunkExtension (_saved.ToString ()), NumberStyles.HexNumber);
|
||||
}
|
||||
catch {
|
||||
throwProtocolViolation ("The chunk size cannot be parsed.");
|
||||
}
|
||||
|
||||
if (_chunkSize == 0) {
|
||||
_trailerState = 2;
|
||||
return InputChunkState.Trailer;
|
||||
}
|
||||
|
||||
return InputChunkState.Data;
|
||||
}
|
||||
|
||||
private InputChunkState setTrailer (byte[] buffer, ref int offset, int length)
|
||||
{
|
||||
// Check if no trailer.
|
||||
if (_trailerState == 2 && buffer[offset] == 13 && _saved.Length == 0) {
|
||||
offset++;
|
||||
if (offset < length && buffer[offset] == 10) {
|
||||
offset++;
|
||||
return InputChunkState.End;
|
||||
}
|
||||
|
||||
offset--;
|
||||
}
|
||||
|
||||
while (offset < length && _trailerState < 4) {
|
||||
var b = buffer[offset++];
|
||||
_saved.Append ((char) b);
|
||||
if (_saved.Length > 4196)
|
||||
throwProtocolViolation ("The trailer is too long.");
|
||||
|
||||
if (_trailerState == 1 || _trailerState == 3) {
|
||||
if (b != 10)
|
||||
throwProtocolViolation ("LF is expected.");
|
||||
|
||||
_trailerState++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b == 13) {
|
||||
_trailerState++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b == 10)
|
||||
throwProtocolViolation ("LF is unexpected.");
|
||||
|
||||
_trailerState = 0;
|
||||
}
|
||||
|
||||
if (_trailerState < 4)
|
||||
return InputChunkState.Trailer;
|
||||
|
||||
_saved.Length -= 2;
|
||||
var reader = new StringReader (_saved.ToString ());
|
||||
|
||||
string line;
|
||||
while ((line = reader.ReadLine ()) != null && line.Length > 0)
|
||||
_headers.Add (line);
|
||||
|
||||
return InputChunkState.End;
|
||||
}
|
||||
|
||||
private static void throwProtocolViolation (string message)
|
||||
{
|
||||
throw new WebException (message, null, WebExceptionStatus.ServerProtocolViolation, null);
|
||||
}
|
||||
|
||||
private void write (byte[] buffer, ref int offset, int length)
|
||||
{
|
||||
if (_state == InputChunkState.End)
|
||||
throwProtocolViolation ("The chunks were ended.");
|
||||
|
||||
if (_state == InputChunkState.None) {
|
||||
_state = setChunkSize (buffer, ref offset, length);
|
||||
if (_state == InputChunkState.None)
|
||||
return;
|
||||
|
||||
_saved.Length = 0;
|
||||
_sawCr = false;
|
||||
_gotIt = false;
|
||||
}
|
||||
|
||||
if (_state == InputChunkState.Data && offset < length) {
|
||||
_state = writeData (buffer, ref offset, length);
|
||||
if (_state == InputChunkState.Data)
|
||||
return;
|
||||
}
|
||||
|
||||
if (_state == InputChunkState.DataEnded && offset < length) {
|
||||
_state = seekCrLf (buffer, ref offset, length);
|
||||
if (_state == InputChunkState.DataEnded)
|
||||
return;
|
||||
|
||||
_sawCr = false;
|
||||
}
|
||||
|
||||
if (_state == InputChunkState.Trailer && offset < length) {
|
||||
_state = setTrailer (buffer, ref offset, length);
|
||||
if (_state == InputChunkState.Trailer)
|
||||
return;
|
||||
|
||||
_saved.Length = 0;
|
||||
}
|
||||
|
||||
if (offset < length)
|
||||
write (buffer, ref offset, length);
|
||||
}
|
||||
|
||||
private InputChunkState writeData (byte[] buffer, ref int offset, int length)
|
||||
{
|
||||
var cnt = length - offset;
|
||||
var left = _chunkSize - _chunkRead;
|
||||
if (cnt > left)
|
||||
cnt = left;
|
||||
|
||||
var data = new byte[cnt];
|
||||
Buffer.BlockCopy (buffer, offset, data, 0, cnt);
|
||||
_chunks.Add (new Chunk (data));
|
||||
|
||||
offset += cnt;
|
||||
_chunkRead += cnt;
|
||||
|
||||
return _chunkRead == _chunkSize ? InputChunkState.DataEnded : InputChunkState.Data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
internal void ResetBuffer ()
|
||||
{
|
||||
_chunkRead = 0;
|
||||
_chunkSize = -1;
|
||||
_chunks.Clear ();
|
||||
}
|
||||
|
||||
internal int WriteAndReadBack (byte[] buffer, int offset, int writeCount, int readCount)
|
||||
{
|
||||
Write (buffer, offset, writeCount);
|
||||
return Read (buffer, offset, readCount);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public int Read (byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (count <= 0)
|
||||
return 0;
|
||||
|
||||
return read (buffer, offset, count);
|
||||
}
|
||||
|
||||
public void Write (byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
write (buffer, ref offset, offset + count);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* ChunkStream.cs
|
||||
*
|
||||
* This code is derived from ChunkStream.cs (System.Net) of Mono
|
||||
* (http://www.mono-project.com).
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2003 Ximian, Inc (http://www.ximian.com)
|
||||
* Copyright (c) 2012-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region Authors
|
||||
/*
|
||||
* Authors:
|
||||
* - Gonzalo Paniagua Javier <gonzalo@ximian.com>
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
internal class ChunkStream
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private int _chunkRead;
|
||||
private int _chunkSize;
|
||||
private List<Chunk> _chunks;
|
||||
private bool _gotIt;
|
||||
private WebHeaderCollection _headers;
|
||||
private StringBuilder _saved;
|
||||
private bool _sawCr;
|
||||
private InputChunkState _state;
|
||||
private int _trailerState;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
public ChunkStream (WebHeaderCollection headers)
|
||||
{
|
||||
_headers = headers;
|
||||
_chunkSize = -1;
|
||||
_chunks = new List<Chunk> ();
|
||||
_saved = new StringBuilder ();
|
||||
}
|
||||
|
||||
public ChunkStream (byte[] buffer, int offset, int count, WebHeaderCollection headers)
|
||||
: this (headers)
|
||||
{
|
||||
Write (buffer, offset, count);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Properties
|
||||
|
||||
internal WebHeaderCollection Headers {
|
||||
get {
|
||||
return _headers;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public int ChunkLeft {
|
||||
get {
|
||||
return _chunkSize - _chunkRead;
|
||||
}
|
||||
}
|
||||
|
||||
public bool WantMore {
|
||||
get {
|
||||
return _state != InputChunkState.End;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private int read (byte[] buffer, int offset, int count)
|
||||
{
|
||||
var nread = 0;
|
||||
|
||||
var cnt = _chunks.Count;
|
||||
for (var i = 0; i < cnt; i++) {
|
||||
var chunk = _chunks[i];
|
||||
if (chunk == null)
|
||||
continue;
|
||||
|
||||
if (chunk.ReadLeft == 0) {
|
||||
_chunks[i] = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
nread += chunk.Read (buffer, offset + nread, count - nread);
|
||||
if (nread == count)
|
||||
break;
|
||||
}
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
private static string removeChunkExtension (string value)
|
||||
{
|
||||
var idx = value.IndexOf (';');
|
||||
return idx > -1 ? value.Substring (0, idx) : value;
|
||||
}
|
||||
|
||||
private InputChunkState seekCrLf (byte[] buffer, ref int offset, int length)
|
||||
{
|
||||
if (!_sawCr) {
|
||||
if (buffer[offset++] != 13)
|
||||
throwProtocolViolation ("CR is expected.");
|
||||
|
||||
_sawCr = true;
|
||||
if (offset == length)
|
||||
return InputChunkState.DataEnded;
|
||||
}
|
||||
|
||||
if (buffer[offset++] != 10)
|
||||
throwProtocolViolation ("LF is expected.");
|
||||
|
||||
return InputChunkState.None;
|
||||
}
|
||||
|
||||
private InputChunkState setChunkSize (byte[] buffer, ref int offset, int length)
|
||||
{
|
||||
byte b = 0;
|
||||
while (offset < length) {
|
||||
b = buffer[offset++];
|
||||
if (_sawCr) {
|
||||
if (b != 10)
|
||||
throwProtocolViolation ("LF is expected.");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (b == 13) {
|
||||
_sawCr = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b == 10)
|
||||
throwProtocolViolation ("LF is unexpected.");
|
||||
|
||||
if (b == 32) // SP
|
||||
_gotIt = true;
|
||||
|
||||
if (!_gotIt)
|
||||
_saved.Append ((char) b);
|
||||
|
||||
if (_saved.Length > 20)
|
||||
throwProtocolViolation ("The chunk size is too long.");
|
||||
}
|
||||
|
||||
if (!_sawCr || b != 10)
|
||||
return InputChunkState.None;
|
||||
|
||||
_chunkRead = 0;
|
||||
try {
|
||||
_chunkSize = Int32.Parse (
|
||||
removeChunkExtension (_saved.ToString ()), NumberStyles.HexNumber);
|
||||
}
|
||||
catch {
|
||||
throwProtocolViolation ("The chunk size cannot be parsed.");
|
||||
}
|
||||
|
||||
if (_chunkSize == 0) {
|
||||
_trailerState = 2;
|
||||
return InputChunkState.Trailer;
|
||||
}
|
||||
|
||||
return InputChunkState.Data;
|
||||
}
|
||||
|
||||
private InputChunkState setTrailer (byte[] buffer, ref int offset, int length)
|
||||
{
|
||||
// Check if no trailer.
|
||||
if (_trailerState == 2 && buffer[offset] == 13 && _saved.Length == 0) {
|
||||
offset++;
|
||||
if (offset < length && buffer[offset] == 10) {
|
||||
offset++;
|
||||
return InputChunkState.End;
|
||||
}
|
||||
|
||||
offset--;
|
||||
}
|
||||
|
||||
while (offset < length && _trailerState < 4) {
|
||||
var b = buffer[offset++];
|
||||
_saved.Append ((char) b);
|
||||
if (_saved.Length > 4196)
|
||||
throwProtocolViolation ("The trailer is too long.");
|
||||
|
||||
if (_trailerState == 1 || _trailerState == 3) {
|
||||
if (b != 10)
|
||||
throwProtocolViolation ("LF is expected.");
|
||||
|
||||
_trailerState++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b == 13) {
|
||||
_trailerState++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b == 10)
|
||||
throwProtocolViolation ("LF is unexpected.");
|
||||
|
||||
_trailerState = 0;
|
||||
}
|
||||
|
||||
if (_trailerState < 4)
|
||||
return InputChunkState.Trailer;
|
||||
|
||||
_saved.Length -= 2;
|
||||
var reader = new StringReader (_saved.ToString ());
|
||||
|
||||
string line;
|
||||
while ((line = reader.ReadLine ()) != null && line.Length > 0)
|
||||
_headers.Add (line);
|
||||
|
||||
return InputChunkState.End;
|
||||
}
|
||||
|
||||
private static void throwProtocolViolation (string message)
|
||||
{
|
||||
throw new WebException (message, null, WebExceptionStatus.ServerProtocolViolation, null);
|
||||
}
|
||||
|
||||
private void write (byte[] buffer, ref int offset, int length)
|
||||
{
|
||||
if (_state == InputChunkState.End)
|
||||
throwProtocolViolation ("The chunks were ended.");
|
||||
|
||||
if (_state == InputChunkState.None) {
|
||||
_state = setChunkSize (buffer, ref offset, length);
|
||||
if (_state == InputChunkState.None)
|
||||
return;
|
||||
|
||||
_saved.Length = 0;
|
||||
_sawCr = false;
|
||||
_gotIt = false;
|
||||
}
|
||||
|
||||
if (_state == InputChunkState.Data && offset < length) {
|
||||
_state = writeData (buffer, ref offset, length);
|
||||
if (_state == InputChunkState.Data)
|
||||
return;
|
||||
}
|
||||
|
||||
if (_state == InputChunkState.DataEnded && offset < length) {
|
||||
_state = seekCrLf (buffer, ref offset, length);
|
||||
if (_state == InputChunkState.DataEnded)
|
||||
return;
|
||||
|
||||
_sawCr = false;
|
||||
}
|
||||
|
||||
if (_state == InputChunkState.Trailer && offset < length) {
|
||||
_state = setTrailer (buffer, ref offset, length);
|
||||
if (_state == InputChunkState.Trailer)
|
||||
return;
|
||||
|
||||
_saved.Length = 0;
|
||||
}
|
||||
|
||||
if (offset < length)
|
||||
write (buffer, ref offset, length);
|
||||
}
|
||||
|
||||
private InputChunkState writeData (byte[] buffer, ref int offset, int length)
|
||||
{
|
||||
var cnt = length - offset;
|
||||
var left = _chunkSize - _chunkRead;
|
||||
if (cnt > left)
|
||||
cnt = left;
|
||||
|
||||
var data = new byte[cnt];
|
||||
Buffer.BlockCopy (buffer, offset, data, 0, cnt);
|
||||
_chunks.Add (new Chunk (data));
|
||||
|
||||
offset += cnt;
|
||||
_chunkRead += cnt;
|
||||
|
||||
return _chunkRead == _chunkSize ? InputChunkState.DataEnded : InputChunkState.Data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
internal void ResetBuffer ()
|
||||
{
|
||||
_chunkRead = 0;
|
||||
_chunkSize = -1;
|
||||
_chunks.Clear ();
|
||||
}
|
||||
|
||||
internal int WriteAndReadBack (byte[] buffer, int offset, int writeCount, int readCount)
|
||||
{
|
||||
Write (buffer, offset, writeCount);
|
||||
return Read (buffer, offset, readCount);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public int Read (byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (count <= 0)
|
||||
return 0;
|
||||
|
||||
return read (buffer, offset, count);
|
||||
}
|
||||
|
||||
public void Write (byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
write (buffer, ref offset, offset + count);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,213 +1,213 @@
|
||||
#region License
|
||||
/*
|
||||
* ChunkedRequestStream.cs
|
||||
*
|
||||
* This code is derived from ChunkedInputStream.cs (System.Net) of Mono
|
||||
* (http://www.mono-project.com).
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
|
||||
* Copyright (c) 2012-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region Authors
|
||||
/*
|
||||
* Authors:
|
||||
* - Gonzalo Paniagua Javier <gonzalo@novell.com>
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
internal class ChunkedRequestStream : RequestStream
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private const int _bufferLength = 8192;
|
||||
private HttpListenerContext _context;
|
||||
private ChunkStream _decoder;
|
||||
private bool _disposed;
|
||||
private bool _noMoreData;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal ChunkedRequestStream (
|
||||
Stream stream, byte[] buffer, int offset, int count, HttpListenerContext context)
|
||||
: base (stream, buffer, offset, count)
|
||||
{
|
||||
_context = context;
|
||||
_decoder = new ChunkStream ((WebHeaderCollection) context.Request.Headers);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Properties
|
||||
|
||||
internal ChunkStream Decoder {
|
||||
get {
|
||||
return _decoder;
|
||||
}
|
||||
|
||||
set {
|
||||
_decoder = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void onRead (IAsyncResult asyncResult)
|
||||
{
|
||||
var rstate = (ReadBufferState) asyncResult.AsyncState;
|
||||
var ares = rstate.AsyncResult;
|
||||
try {
|
||||
var nread = base.EndRead (asyncResult);
|
||||
_decoder.Write (ares.Buffer, ares.Offset, nread);
|
||||
nread = _decoder.Read (rstate.Buffer, rstate.Offset, rstate.Count);
|
||||
rstate.Offset += nread;
|
||||
rstate.Count -= nread;
|
||||
if (rstate.Count == 0 || !_decoder.WantMore || nread == 0) {
|
||||
_noMoreData = !_decoder.WantMore && nread == 0;
|
||||
ares.Count = rstate.InitialCount - rstate.Count;
|
||||
ares.Complete ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ares.Offset = 0;
|
||||
ares.Count = Math.Min (_bufferLength, _decoder.ChunkLeft + 6);
|
||||
base.BeginRead (ares.Buffer, ares.Offset, ares.Count, onRead, rstate);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_context.ErrorMessage = ex.Message;
|
||||
_context.SendError ();
|
||||
|
||||
ares.Complete (ex);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public override IAsyncResult BeginRead (
|
||||
byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException (GetType ().ToString ());
|
||||
|
||||
if (buffer == null)
|
||||
throw new ArgumentNullException ("buffer");
|
||||
|
||||
if (offset < 0)
|
||||
throw new ArgumentOutOfRangeException ("offset", "A negative value.");
|
||||
|
||||
if (count < 0)
|
||||
throw new ArgumentOutOfRangeException ("count", "A negative value.");
|
||||
|
||||
var len = buffer.Length;
|
||||
if (offset + count > len)
|
||||
throw new ArgumentException (
|
||||
"The sum of 'offset' and 'count' is greater than 'buffer' length.");
|
||||
|
||||
var ares = new HttpStreamAsyncResult (callback, state);
|
||||
if (_noMoreData) {
|
||||
ares.Complete ();
|
||||
return ares;
|
||||
}
|
||||
|
||||
var nread = _decoder.Read (buffer, offset, count);
|
||||
offset += nread;
|
||||
count -= nread;
|
||||
if (count == 0) {
|
||||
// Got all we wanted, no need to bother the decoder yet.
|
||||
ares.Count = nread;
|
||||
ares.Complete ();
|
||||
|
||||
return ares;
|
||||
}
|
||||
|
||||
if (!_decoder.WantMore) {
|
||||
_noMoreData = nread == 0;
|
||||
ares.Count = nread;
|
||||
ares.Complete ();
|
||||
|
||||
return ares;
|
||||
}
|
||||
|
||||
ares.Buffer = new byte[_bufferLength];
|
||||
ares.Offset = 0;
|
||||
ares.Count = _bufferLength;
|
||||
|
||||
var rstate = new ReadBufferState (buffer, offset, count, ares);
|
||||
rstate.InitialCount += nread;
|
||||
base.BeginRead (ares.Buffer, ares.Offset, ares.Count, onRead, rstate);
|
||||
|
||||
return ares;
|
||||
}
|
||||
|
||||
public override void Close ()
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
_disposed = true;
|
||||
base.Close ();
|
||||
}
|
||||
|
||||
public override int EndRead (IAsyncResult asyncResult)
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException (GetType ().ToString ());
|
||||
|
||||
if (asyncResult == null)
|
||||
throw new ArgumentNullException ("asyncResult");
|
||||
|
||||
var ares = asyncResult as HttpStreamAsyncResult;
|
||||
if (ares == null)
|
||||
throw new ArgumentException ("A wrong IAsyncResult.", "asyncResult");
|
||||
|
||||
if (!ares.IsCompleted)
|
||||
ares.AsyncWaitHandle.WaitOne ();
|
||||
|
||||
if (ares.HasException)
|
||||
throw new HttpListenerException (400, "I/O operation aborted.");
|
||||
|
||||
return ares.Count;
|
||||
}
|
||||
|
||||
public override int Read (byte[] buffer, int offset, int count)
|
||||
{
|
||||
var ares = BeginRead (buffer, offset, count, null, null);
|
||||
return EndRead (ares);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* ChunkedRequestStream.cs
|
||||
*
|
||||
* This code is derived from ChunkedInputStream.cs (System.Net) of Mono
|
||||
* (http://www.mono-project.com).
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
|
||||
* Copyright (c) 2012-2015 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region Authors
|
||||
/*
|
||||
* Authors:
|
||||
* - Gonzalo Paniagua Javier <gonzalo@novell.com>
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
internal class ChunkedRequestStream : RequestStream
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private const int _bufferLength = 8192;
|
||||
private HttpListenerContext _context;
|
||||
private ChunkStream _decoder;
|
||||
private bool _disposed;
|
||||
private bool _noMoreData;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal ChunkedRequestStream (
|
||||
Stream stream, byte[] buffer, int offset, int count, HttpListenerContext context)
|
||||
: base (stream, buffer, offset, count)
|
||||
{
|
||||
_context = context;
|
||||
_decoder = new ChunkStream ((WebHeaderCollection) context.Request.Headers);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Properties
|
||||
|
||||
internal ChunkStream Decoder {
|
||||
get {
|
||||
return _decoder;
|
||||
}
|
||||
|
||||
set {
|
||||
_decoder = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void onRead (IAsyncResult asyncResult)
|
||||
{
|
||||
var rstate = (ReadBufferState) asyncResult.AsyncState;
|
||||
var ares = rstate.AsyncResult;
|
||||
try {
|
||||
var nread = base.EndRead (asyncResult);
|
||||
_decoder.Write (ares.Buffer, ares.Offset, nread);
|
||||
nread = _decoder.Read (rstate.Buffer, rstate.Offset, rstate.Count);
|
||||
rstate.Offset += nread;
|
||||
rstate.Count -= nread;
|
||||
if (rstate.Count == 0 || !_decoder.WantMore || nread == 0) {
|
||||
_noMoreData = !_decoder.WantMore && nread == 0;
|
||||
ares.Count = rstate.InitialCount - rstate.Count;
|
||||
ares.Complete ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ares.Offset = 0;
|
||||
ares.Count = Math.Min (_bufferLength, _decoder.ChunkLeft + 6);
|
||||
base.BeginRead (ares.Buffer, ares.Offset, ares.Count, onRead, rstate);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_context.ErrorMessage = ex.Message;
|
||||
_context.SendError ();
|
||||
|
||||
ares.Complete (ex);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public override IAsyncResult BeginRead (
|
||||
byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException (GetType ().ToString ());
|
||||
|
||||
if (buffer == null)
|
||||
throw new ArgumentNullException ("buffer");
|
||||
|
||||
if (offset < 0)
|
||||
throw new ArgumentOutOfRangeException ("offset", "A negative value.");
|
||||
|
||||
if (count < 0)
|
||||
throw new ArgumentOutOfRangeException ("count", "A negative value.");
|
||||
|
||||
var len = buffer.Length;
|
||||
if (offset + count > len)
|
||||
throw new ArgumentException (
|
||||
"The sum of 'offset' and 'count' is greater than 'buffer' length.");
|
||||
|
||||
var ares = new HttpStreamAsyncResult (callback, state);
|
||||
if (_noMoreData) {
|
||||
ares.Complete ();
|
||||
return ares;
|
||||
}
|
||||
|
||||
var nread = _decoder.Read (buffer, offset, count);
|
||||
offset += nread;
|
||||
count -= nread;
|
||||
if (count == 0) {
|
||||
// Got all we wanted, no need to bother the decoder yet.
|
||||
ares.Count = nread;
|
||||
ares.Complete ();
|
||||
|
||||
return ares;
|
||||
}
|
||||
|
||||
if (!_decoder.WantMore) {
|
||||
_noMoreData = nread == 0;
|
||||
ares.Count = nread;
|
||||
ares.Complete ();
|
||||
|
||||
return ares;
|
||||
}
|
||||
|
||||
ares.Buffer = new byte[_bufferLength];
|
||||
ares.Offset = 0;
|
||||
ares.Count = _bufferLength;
|
||||
|
||||
var rstate = new ReadBufferState (buffer, offset, count, ares);
|
||||
rstate.InitialCount += nread;
|
||||
base.BeginRead (ares.Buffer, ares.Offset, ares.Count, onRead, rstate);
|
||||
|
||||
return ares;
|
||||
}
|
||||
|
||||
public override void Close ()
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
_disposed = true;
|
||||
base.Close ();
|
||||
}
|
||||
|
||||
public override int EndRead (IAsyncResult asyncResult)
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException (GetType ().ToString ());
|
||||
|
||||
if (asyncResult == null)
|
||||
throw new ArgumentNullException ("asyncResult");
|
||||
|
||||
var ares = asyncResult as HttpStreamAsyncResult;
|
||||
if (ares == null)
|
||||
throw new ArgumentException ("A wrong IAsyncResult.", "asyncResult");
|
||||
|
||||
if (!ares.IsCompleted)
|
||||
ares.AsyncWaitHandle.WaitOne ();
|
||||
|
||||
if (ares.HasException)
|
||||
throw new HttpListenerException (400, "I/O operation aborted.");
|
||||
|
||||
return ares.Count;
|
||||
}
|
||||
|
||||
public override int Read (byte[] buffer, int offset, int count)
|
||||
{
|
||||
var ares = BeginRead (buffer, offset, count, null, null);
|
||||
return EndRead (ares);
|
||||
}
|
||||
|
||||
#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
|
||||
/*
|
||||
* CookieException.cs
|
||||
*
|
||||
* This code is derived from CookieException.cs (System.Net) of Mono
|
||||
* (http://www.mono-project.com).
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2019 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region Authors
|
||||
/*
|
||||
* Authors:
|
||||
* - Lawrence Pit <loz@cable.a2000.nl>
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Permissions;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// The exception that is thrown when a <see cref="Cookie"/> gets an error.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class CookieException : FormatException, ISerializable
|
||||
{
|
||||
#region Internal Constructors
|
||||
|
||||
internal CookieException (string message)
|
||||
: base (message)
|
||||
{
|
||||
}
|
||||
|
||||
internal CookieException (string message, Exception innerException)
|
||||
: base (message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CookieException"/> class
|
||||
/// with the serialized data.
|
||||
/// </summary>
|
||||
/// <param name="serializationInfo">
|
||||
/// A <see cref="SerializationInfo"/> that holds the serialized object data.
|
||||
/// </param>
|
||||
/// <param name="streamingContext">
|
||||
/// A <see cref="StreamingContext"/> that specifies the source for
|
||||
/// the deserialization.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="serializationInfo"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
protected CookieException (
|
||||
SerializationInfo serializationInfo, StreamingContext streamingContext
|
||||
)
|
||||
: base (serializationInfo, streamingContext)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CookieException"/> class.
|
||||
/// </summary>
|
||||
public CookieException ()
|
||||
: base ()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Populates the specified <see cref="SerializationInfo"/> instance with
|
||||
/// the data needed to serialize the current instance.
|
||||
/// </summary>
|
||||
/// <param name="serializationInfo">
|
||||
/// A <see cref="SerializationInfo"/> that holds the serialized object data.
|
||||
/// </param>
|
||||
/// <param name="streamingContext">
|
||||
/// A <see cref="StreamingContext"/> that specifies the destination for
|
||||
/// the serialization.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="serializationInfo"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
[
|
||||
SecurityPermission (
|
||||
SecurityAction.LinkDemand,
|
||||
Flags = SecurityPermissionFlag.SerializationFormatter
|
||||
)
|
||||
]
|
||||
public override void GetObjectData (
|
||||
SerializationInfo serializationInfo, StreamingContext streamingContext
|
||||
)
|
||||
{
|
||||
base.GetObjectData (serializationInfo, streamingContext);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Explicit Interface Implementation
|
||||
|
||||
/// <summary>
|
||||
/// Populates the specified <see cref="SerializationInfo"/> instance with
|
||||
/// the data needed to serialize the current instance.
|
||||
/// </summary>
|
||||
/// <param name="serializationInfo">
|
||||
/// A <see cref="SerializationInfo"/> that holds the serialized object data.
|
||||
/// </param>
|
||||
/// <param name="streamingContext">
|
||||
/// A <see cref="StreamingContext"/> that specifies the destination for
|
||||
/// the serialization.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="serializationInfo"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
[
|
||||
SecurityPermission (
|
||||
SecurityAction.LinkDemand,
|
||||
Flags = SecurityPermissionFlag.SerializationFormatter,
|
||||
SerializationFormatter = true
|
||||
)
|
||||
]
|
||||
void ISerializable.GetObjectData (
|
||||
SerializationInfo serializationInfo, StreamingContext streamingContext
|
||||
)
|
||||
{
|
||||
base.GetObjectData (serializationInfo, streamingContext);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#region License
|
||||
/*
|
||||
* CookieException.cs
|
||||
*
|
||||
* This code is derived from CookieException.cs (System.Net) of Mono
|
||||
* (http://www.mono-project.com).
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2019 sta.blockhead
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region Authors
|
||||
/*
|
||||
* Authors:
|
||||
* - Lawrence Pit <loz@cable.a2000.nl>
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Permissions;
|
||||
|
||||
namespace WebSocketSharp.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// The exception that is thrown when a <see cref="Cookie"/> gets an error.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class CookieException : FormatException, ISerializable
|
||||
{
|
||||
#region Internal Constructors
|
||||
|
||||
internal CookieException (string message)
|
||||
: base (message)
|
||||
{
|
||||
}
|
||||
|
||||
internal CookieException (string message, Exception innerException)
|
||||
: base (message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CookieException"/> class
|
||||
/// with the serialized data.
|
||||
/// </summary>
|
||||
/// <param name="serializationInfo">
|
||||
/// A <see cref="SerializationInfo"/> that holds the serialized object data.
|
||||
/// </param>
|
||||
/// <param name="streamingContext">
|
||||
/// A <see cref="StreamingContext"/> that specifies the source for
|
||||
/// the deserialization.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="serializationInfo"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
protected CookieException (
|
||||
SerializationInfo serializationInfo, StreamingContext streamingContext
|
||||
)
|
||||
: base (serializationInfo, streamingContext)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CookieException"/> class.
|
||||
/// </summary>
|
||||
public CookieException ()
|
||||
: base ()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Populates the specified <see cref="SerializationInfo"/> instance with
|
||||
/// the data needed to serialize the current instance.
|
||||
/// </summary>
|
||||
/// <param name="serializationInfo">
|
||||
/// A <see cref="SerializationInfo"/> that holds the serialized object data.
|
||||
/// </param>
|
||||
/// <param name="streamingContext">
|
||||
/// A <see cref="StreamingContext"/> that specifies the destination for
|
||||
/// the serialization.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="serializationInfo"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
[
|
||||
SecurityPermission (
|
||||
SecurityAction.LinkDemand,
|
||||
Flags = SecurityPermissionFlag.SerializationFormatter
|
||||
)
|
||||
]
|
||||
public override void GetObjectData (
|
||||
SerializationInfo serializationInfo, StreamingContext streamingContext
|
||||
)
|
||||
{
|
||||
base.GetObjectData (serializationInfo, streamingContext);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Explicit Interface Implementation
|
||||
|
||||
/// <summary>
|
||||
/// Populates the specified <see cref="SerializationInfo"/> instance with
|
||||
/// the data needed to serialize the current instance.
|
||||
/// </summary>
|
||||
/// <param name="serializationInfo">
|
||||
/// A <see cref="SerializationInfo"/> that holds the serialized object data.
|
||||
/// </param>
|
||||
/// <param name="streamingContext">
|
||||
/// A <see cref="StreamingContext"/> that specifies the destination for
|
||||
/// the serialization.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="serializationInfo"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
[
|
||||
SecurityPermission (
|
||||
SecurityAction.LinkDemand,
|
||||
Flags = SecurityPermissionFlag.SerializationFormatter,
|
||||
SerializationFormatter = true
|
||||
)
|
||||
]
|
||||
void ISerializable.GetObjectData (
|
||||
SerializationInfo serializationInfo, StreamingContext streamingContext
|
||||
)
|
||||
{
|
||||
base.GetObjectData (serializationInfo, streamingContext);
|
||||
}
|
||||
|
||||
#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