├── src
├── WebSocketSharper
│ ├── doc
│ │ ├── .gitignore
│ │ └── doc.sh
│ ├── icon.png
│ ├── IWebSocket.cs
│ ├── Server
│ │ ├── ServerState.cs
│ │ ├── WebSocketServiceHost`1.cs
│ │ ├── IWebSocketSession.cs
│ │ └── WebSocketServiceHost.cs
│ ├── Net
│ │ ├── HttpHeaderType.cs
│ │ ├── InputState.cs
│ │ ├── LineState.cs
│ │ ├── InputChunkState.cs
│ │ ├── AuthenticationSchemes.cs
│ │ ├── HttpVersion.cs
│ │ ├── Chunk.cs
│ │ ├── HttpBasicIdentity.cs
│ │ ├── ReadBufferState.cs
│ │ ├── HttpHeaderInfo.cs
│ │ ├── AuthenticationBase.cs
│ │ ├── HttpListenerException.cs
│ │ ├── QueryStringCollection.cs
│ │ ├── HttpStreamAsyncResult.cs
│ │ ├── AuthenticationChallenge.cs
│ │ ├── HttpListenerAsyncResult.cs
│ │ ├── CookieException.cs
│ │ ├── HttpDigestIdentity.cs
│ │ ├── HttpResponseHeader.cs
│ │ ├── ChunkedRequestStream.cs
│ │ ├── NetworkCredential.cs
│ │ ├── EndPointManager.cs
│ │ └── HttpRequestHeader.cs
│ ├── ByteOrder.cs
│ ├── CompressionMethod.cs
│ ├── Mask.cs
│ ├── Rsv.cs
│ ├── WebSocketSharper.csproj
│ ├── Fin.cs
│ ├── Opcode.cs
│ ├── WebSocketState.cs
│ ├── ErrorEventArgs.cs
│ ├── WebSocketException.cs
│ ├── CloseEventArgs.cs
│ ├── Interfaces.cs
│ ├── CloseStatusCode.cs
│ ├── MessageEventArgs.cs
│ ├── PayloadData.cs
│ ├── HttpResponse.cs
│ ├── HttpBase.cs
│ └── HttpRequest.cs
├── Samples
│ ├── SimpleClient
│ │ ├── client.pfx
│ │ ├── SimpleClient.csproj
│ │ ├── ProgramClient.cs
│ │ └── SimpleSecureClient.cs
│ └── SimpleServer
│ │ ├── localhost.pfx
│ │ ├── SimpleServer.csproj
│ │ ├── ProgramServer.cs
│ │ └── SimpleSecureServer.cs
└── Test
│ ├── TestSupport
│ ├── BaseSynchronised.cs
│ ├── BaseTest.cs
│ ├── TestSupport.csproj
│ ├── BaseDisposable.cs
│ ├── xUnitLogger.cs
│ ├── TestGate.cs
│ └── SafeLock.cs
│ └── WebSocketSharperTests
│ ├── WebSocketSharperTests.csproj
│ └── WebSocketTests.cs
├── websocketsharper_icon.pdn
├── websocketsharper_icon.png
├── version.json
├── .github
└── workflows
│ └── dotnetcore.yml
├── LICENSE.txt
├── websocket-sharper.sln
└── .gitignore
/src/WebSocketSharper/doc/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore MonoDevelop build results.
2 |
3 | html
4 | mdoc
5 |
--------------------------------------------------------------------------------
/websocketsharper_icon.pdn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ekwus/websocketsharper/HEAD/websocketsharper_icon.pdn
--------------------------------------------------------------------------------
/websocketsharper_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ekwus/websocketsharper/HEAD/websocketsharper_icon.png
--------------------------------------------------------------------------------
/src/WebSocketSharper/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ekwus/websocketsharper/HEAD/src/WebSocketSharper/icon.png
--------------------------------------------------------------------------------
/src/Samples/SimpleClient/client.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ekwus/websocketsharper/HEAD/src/Samples/SimpleClient/client.pfx
--------------------------------------------------------------------------------
/src/Samples/SimpleServer/localhost.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ekwus/websocketsharper/HEAD/src/Samples/SimpleServer/localhost.pfx
--------------------------------------------------------------------------------
/src/Test/TestSupport/BaseSynchronised.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace TestSupport
4 | {
5 | public abstract class BaseSynchronised
6 | {
7 | protected SafeLock SyncRoot { get; private set; }
8 |
9 | protected BaseSynchronised()
10 | {
11 | SyncRoot = new SafeLock();
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/version.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
3 | "version": "1.0",
4 | "publicReleaseRefSpec": [
5 | "^master$",
6 | "^refs/heads/master$",
7 | "^refs/tags/v\\d+\\.\\d+"
8 | ],
9 | "cloudBuild": {
10 | "setVersionVariables": true,
11 | "buildNumber": {
12 | "enabled": false,
13 | "includeCommitId": {
14 | "when": "nonPublicReleaseOnly",
15 | "where": "buildMetadata"
16 | }
17 | }
18 | },
19 | "inherit": false
20 | }
--------------------------------------------------------------------------------
/src/Test/TestSupport/BaseTest.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using Xunit.Abstractions;
3 |
4 | namespace TestSupport
5 | {
6 | public abstract class BaseTest
7 | {
8 | protected ILogger LOG { get; private set; }
9 | protected ILoggerProvider LoggerProvider { get; private set; }
10 |
11 | static BaseTest()
12 | {
13 |
14 | }
15 |
16 | public BaseTest(ITestOutputHelper testOutputHelper)
17 | {
18 | LoggerProvider = new xUnitLoggerProvider(testOutputHelper);
19 | LOG = LoggerProvider.CreateLogger("Unit Test");
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/doc/doc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # @(#) doc.sh ver.0.0.2 2013.01.24
4 | #
5 | # Usage:
6 | # doc.sh
7 | #
8 | # Description:
9 | # Creating documentation for websocket-sharp.
10 | #
11 | ###########################################################################
12 |
13 | SRC_DIR="../bin/Release_Ubuntu"
14 | XML="${SRC_DIR}/websocket-sharp.xml"
15 | DLL="${SRC_DIR}/websocket-sharp.dll"
16 |
17 | DOC_DIR="."
18 | MDOC_DIR="${DOC_DIR}/mdoc"
19 | HTML_DIR="${DOC_DIR}/html"
20 |
21 | createDir() {
22 | if [ ! -d $1 ]; then
23 | mkdir -p $1
24 | fi
25 | }
26 |
27 | set -e
28 | createDir ${MDOC_DIR}
29 | createDir ${HTML_DIR}
30 | mdoc update --delete -fno-assembly-versions -i ${XML} -o ${MDOC_DIR}/ ${DLL}
31 | mdoc export-html -o ${HTML_DIR}/ ${MDOC_DIR}/
32 |
--------------------------------------------------------------------------------
/src/Test/TestSupport/TestSupport.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | 7.3
6 |
7 |
8 |
9 | ../../../build/Test/TestSupport
10 |
11 |
12 |
13 | ../../../build/Test/TestSupport
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.github/workflows/dotnetcore.yml:
--------------------------------------------------------------------------------
1 | name: .NET Core
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | build_and_test:
10 | runs-on: ${{ matrix.os }}
11 | strategy:
12 | matrix:
13 | os: [ubuntu-18.04, windows-latest]
14 | steps:
15 | - uses: actions/checkout@v1
16 | - name: Setup .NET Core
17 | uses: actions/setup-dotnet@v1.2.0
18 | with:
19 | dotnet-version: 2.2.207
20 | if: matrix.os == 'macOS-latest' || matrix.os == 'ubuntu-latest'
21 | - name: Build with dotnet
22 | run: dotnet build websocket-sharper.sln --configuration Release
23 | # - name: Test with dotnet
24 | # run: dotnet test websocket-sharper.sln --configuration Release
25 | - name: Install nuget
26 | if: matrix.os == 'windows-latest'
27 | uses: nuget/setup-nuget@v1
28 | - name: Publish Nuget
29 | if: matrix.os == 'windows-latest'
30 | run: nuget push .\build\Release\WebSocketSharper\*.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -NoSymbols -ApiKey ${{ secrets.NUGET_KEY }}
31 |
--------------------------------------------------------------------------------
/src/Test/TestSupport/BaseDisposable.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace TestSupport
6 | {
7 | public abstract class BaseDisposable : BaseSynchronised, IDisposable
8 | {
9 | public bool IsDisposed { get; private set; }
10 | public bool IsDisposing { get; private set; }
11 |
12 | public void Dispose()
13 | {
14 | (this as IDisposable).Dispose();
15 | }
16 |
17 | protected abstract void Dispose(bool disposing);
18 |
19 | void IDisposable.Dispose()
20 | {
21 | using (SyncRoot.Enter())
22 | {
23 | if (IsDisposed || IsDisposing)
24 | {
25 | return;
26 | }
27 |
28 | IsDisposing = true;
29 | }
30 |
31 | try
32 | {
33 | Dispose(true);
34 | }
35 | catch (Exception)
36 | {
37 | // Disposing so not much we can do with this exception
38 | }
39 | finally
40 | {
41 | IsDisposed = true;
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2010-2019 sta.blockhead
4 | Copyright (c) 2019 Veracity UK Ltd
5 | Copyright (c) 2019 Ionot Ltd
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/src/Samples/SimpleClient/SimpleClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 |
7 |
8 |
9 | ../../../build/Debug/SimpleClient
10 |
11 |
12 |
13 | ../../../build/Release/SimpleClient
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Always
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/Samples/SimpleServer/SimpleServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 |
7 |
8 |
9 | ../../../build/Debug/SimpleServer
10 |
11 |
12 |
13 | ../../../build/Release/SimpleServer
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Always
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/Samples/SimpleServer/ProgramServer.cs:
--------------------------------------------------------------------------------
1 | using Autofac;
2 | using Autofac.Extensions.DependencyInjection;
3 | using Microsoft.Extensions.Hosting;
4 | using System;
5 | using System.Security.Cryptography.X509Certificates;
6 | using WebSocketSharper;
7 | using WebSocketSharper.Server;
8 | using Microsoft.Extensions.Logging;
9 |
10 | namespace SimpleServer
11 | {
12 | class Program
13 | {
14 | static void Main(string[] args)
15 | {
16 | Console.BackgroundColor = ConsoleColor.DarkBlue;
17 | Console.WindowWidth = 180;
18 | Console.WindowHeight = 60;
19 | Console.Clear();
20 |
21 | Console.WriteLine("WebSocketSharper Simple Server");
22 |
23 | CreateHostBuilder(args).Build().Run();
24 | }
25 |
26 | static IHostBuilder CreateHostBuilder(string[] args) =>
27 | Host.CreateDefaultBuilder(args)
28 | .UseServiceProviderFactory(new AutofacServiceProviderFactory())
29 | .ConfigureLogging(lb =>
30 | lb.AddConsole().SetMinimumLevel(LogLevel.Trace)
31 | )
32 | .ConfigureContainer(builder =>
33 | {
34 | //
35 | // Register our app
36 | //
37 | builder.RegisterType().As().InstancePerDependency();
38 | });
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/IWebSocket.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Threading.Tasks;
5 | using Microsoft.Extensions.Logging;
6 | using WebSocketSharper.Net;
7 |
8 | namespace WebSocketSharper
9 | {
10 | public interface IWebSocket
11 | {
12 | CompressionMethod Compression { get; set; }
13 | IEnumerable Cookies { get; }
14 | NetworkCredential Credentials { get; }
15 | bool EmitOnPing { get; set; }
16 | bool EnableRedirection { get; set; }
17 | string Extensions { get; }
18 | bool IsAlive { get; }
19 | bool IsSecure { get; }
20 | string Origin { get; set; }
21 | string Protocol { get; }
22 | WebSocketState ReadyState { get; }
23 | ClientSslConfiguration SslConfiguration { get; }
24 | Uri Url { get; }
25 | TimeSpan WaitTime { get; set; }
26 |
27 | IObservable MessageReceived { get; }
28 |
29 | event EventHandler OnClose;
30 | event EventHandler OnError;
31 | event EventHandler OnMessage;
32 | event EventHandler OnOpen;
33 |
34 | Task CloseTaskAsync(CloseStatusCode code, string reason);
35 | Task ConnectTaskAsync();
36 | Task PingTaskAsync(string message = null);
37 | Task SendTaskAsync(byte[] data);
38 | Task SendTaskAsync(string data);
39 | }
40 | }
--------------------------------------------------------------------------------
/src/Samples/SimpleClient/ProgramClient.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Security.Cryptography.X509Certificates;
3 | using WebSocketSharper;
4 | using WebSocketSharper.Server;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using Microsoft.Extensions.Hosting;
7 | using Microsoft.Extensions.Logging;
8 | using Autofac.Extensions.DependencyInjection;
9 | using Autofac;
10 |
11 | namespace SimpleClient
12 | {
13 | class Program
14 | {
15 | static void Main(string[] args)
16 | {
17 | Console.BackgroundColor = ConsoleColor.DarkMagenta;
18 | Console.WindowWidth = 180;
19 | Console.WindowHeight = 60;
20 | Console.Clear();
21 |
22 | Console.WriteLine("WebSocketSharper SimpleClient");
23 |
24 | System.Threading.Thread.Sleep(3000);
25 |
26 | CreateHostBuilder(args).Build().Run();
27 | }
28 |
29 | static IHostBuilder CreateHostBuilder(string[] args) =>
30 | Host.CreateDefaultBuilder(args)
31 | .UseServiceProviderFactory(new AutofacServiceProviderFactory())
32 | .ConfigureLogging(lb=>lb.AddConsole().SetMinimumLevel(LogLevel.Trace))
33 | .ConfigureContainer(builder =>
34 | {
35 | //
36 | // Register our app
37 | //
38 | builder.RegisterType().As().InstancePerDependency();
39 | });
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Server/ServerState.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * ServerState.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2013-2014 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 |
31 | namespace WebSocketSharper.Server
32 | {
33 | internal enum ServerState
34 | {
35 | Ready,
36 | Start,
37 | ShuttingDown,
38 | Stop
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Test/WebSocketSharperTests/WebSocketSharperTests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 |
6 | false
7 |
8 | 7.3
9 |
10 |
11 |
12 | ../../../build/Test/WebSocketSharperTests
13 |
14 |
15 |
16 | ../../../build/Test/WebSocketSharperTests
17 |
18 |
19 |
20 |
21 |
22 |
23 | all
24 | runtime; build; native; contentfiles; analyzers; buildtransitive
25 |
26 |
27 | all
28 | runtime; build; native; contentfiles; analyzers; buildtransitive
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/HttpHeaderType.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * HttpHeaderType.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2013-2014 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 |
31 | namespace WebSocketSharper.Net
32 | {
33 | [Flags]
34 | internal enum HttpHeaderType
35 | {
36 | Unspecified = 0,
37 | Request = 1,
38 | Response = 1 << 1,
39 | Restricted = 1 << 2,
40 | MultiValue = 1 << 3,
41 | MultiValueInRequest = 1 << 4,
42 | MultiValueInResponse = 1 << 5
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/ByteOrder.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * ByteOrder.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2012-2015 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 |
31 | namespace WebSocketSharper
32 | {
33 | ///
34 | /// Specifies the byte order.
35 | ///
36 | public enum ByteOrder
37 | {
38 | ///
39 | /// Specifies Little-endian.
40 | ///
41 | Little,
42 | ///
43 | /// Specifies Big-endian.
44 | ///
45 | Big
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/InputState.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * InputState.cs
4 | *
5 | * This code is derived from HttpConnection.cs (System.Net) of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
11 | * Copyright (c) 2014-2015 sta.blockhead
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy
14 | * of this software and associated documentation files (the "Software"), to deal
15 | * in the Software without restriction, including without limitation the rights
16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | * copies of the Software, and to permit persons to whom the Software is
18 | * furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | * THE SOFTWARE.
30 | */
31 | #endregion
32 |
33 | #region Authors
34 | /*
35 | * Authors:
36 | * - Gonzalo Paniagua Javier
37 | */
38 | #endregion
39 |
40 | using System;
41 |
42 | namespace WebSocketSharper.Net
43 | {
44 | internal enum InputState
45 | {
46 | RequestLine,
47 | Headers
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/LineState.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * LineState.cs
4 | *
5 | * This code is derived from HttpConnection.cs (System.Net) of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
11 | * Copyright (c) 2014-2015 sta.blockhead
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy
14 | * of this software and associated documentation files (the "Software"), to deal
15 | * in the Software without restriction, including without limitation the rights
16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | * copies of the Software, and to permit persons to whom the Software is
18 | * furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | * THE SOFTWARE.
30 | */
31 | #endregion
32 |
33 | #region Authors
34 | /*
35 | * Authors:
36 | * - Gonzalo Paniagua Javier
37 | */
38 | #endregion
39 |
40 | using System;
41 |
42 | namespace WebSocketSharper.Net
43 | {
44 | internal enum LineState
45 | {
46 | None,
47 | Cr,
48 | Lf
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/InputChunkState.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * InputChunkState.cs
4 | *
5 | * This code is derived from ChunkStream.cs (System.Net) of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2003 Ximian, Inc (http://www.ximian.com)
11 | * Copyright (c) 2014-2015 sta.blockhead
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy
14 | * of this software and associated documentation files (the "Software"), to deal
15 | * in the Software without restriction, including without limitation the rights
16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | * copies of the Software, and to permit persons to whom the Software is
18 | * furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | * THE SOFTWARE.
30 | */
31 | #endregion
32 |
33 | #region Authors
34 | /*
35 | * Authors:
36 | * - Gonzalo Paniagua Javier
37 | */
38 | #endregion
39 |
40 | using System;
41 |
42 | namespace WebSocketSharper.Net
43 | {
44 | internal enum InputChunkState
45 | {
46 | None,
47 | Data,
48 | DataEnded,
49 | Trailer,
50 | End
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Test/TestSupport/xUnitLogger.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using System;
3 | using Xunit.Abstractions;
4 |
5 | namespace TestSupport
6 | {
7 | public class xUnitLoggerProvider : ILoggerProvider
8 | {
9 | private readonly ITestOutputHelper _testOutputHelper;
10 |
11 | public xUnitLoggerProvider(ITestOutputHelper testOutputHelper)
12 | {
13 | _testOutputHelper = testOutputHelper;
14 | }
15 |
16 | public ILogger CreateLogger(string categoryName)
17 | => new xUnitLogger(_testOutputHelper, categoryName);
18 |
19 | public void Dispose()
20 | { }
21 | }
22 |
23 | public class xUnitLogger : ILogger
24 | {
25 | private readonly ITestOutputHelper _testOutputHelper;
26 | private readonly string _categoryName;
27 |
28 | public xUnitLogger(ITestOutputHelper testOutputHelper, string categoryName)
29 | {
30 | _testOutputHelper = testOutputHelper;
31 | _categoryName = categoryName;
32 | }
33 |
34 | public IDisposable BeginScope(TState state)
35 | => NoopDisposable.Instance;
36 |
37 | public bool IsEnabled(LogLevel logLevel)
38 | => true;
39 |
40 | public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter)
41 | {
42 | _testOutputHelper.WriteLine($"{_categoryName} [{eventId}] {formatter(state, exception)}");
43 | if (exception != null)
44 | _testOutputHelper.WriteLine(exception.ToString());
45 | }
46 |
47 | private class NoopDisposable : IDisposable
48 | {
49 | public static NoopDisposable Instance = new NoopDisposable();
50 | public void Dispose()
51 | { }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/CompressionMethod.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * CompressionMethod.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2013-2017 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 |
31 | namespace WebSocketSharper
32 | {
33 | ///
34 | /// Specifies the method for compression.
35 | ///
36 | ///
37 | /// The methods are defined in
38 | ///
39 | /// Compression Extensions for WebSocket.
40 | ///
41 | public enum CompressionMethod : byte
42 | {
43 | ///
44 | /// Specifies no compression.
45 | ///
46 | None,
47 | ///
48 | /// Specifies DEFLATE.
49 | ///
50 | Deflate
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Mask.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * Mask.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2012-2015 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 |
31 | namespace WebSocketSharper
32 | {
33 | ///
34 | /// Indicates whether the payload data of a WebSocket frame is masked.
35 | ///
36 | ///
37 | /// The values of this enumeration are defined in
38 | /// Section 5.2 of RFC 6455.
39 | ///
40 | internal enum Mask : byte
41 | {
42 | ///
43 | /// Equivalent to numeric value 0. Indicates not masked.
44 | ///
45 | Off = 0x0,
46 | ///
47 | /// Equivalent to numeric value 1. Indicates masked.
48 | ///
49 | On = 0x1
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Rsv.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * Rsv.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2012-2015 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 |
31 | namespace WebSocketSharper
32 | {
33 | ///
34 | /// Indicates whether each RSV (RSV1, RSV2, and RSV3) of a WebSocket frame is non-zero.
35 | ///
36 | ///
37 | /// The values of this enumeration are defined in
38 | /// Section 5.2 of RFC 6455.
39 | ///
40 | internal enum Rsv : byte
41 | {
42 | ///
43 | /// Equivalent to numeric value 0. Indicates zero.
44 | ///
45 | Off = 0x0,
46 | ///
47 | /// Equivalent to numeric value 1. Indicates non-zero.
48 | ///
49 | On = 0x1
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/WebSocketSharper.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | WebSocketSharper
6 | 7.3
7 | true
8 | https://github.com/ekwus/websocketsharper
9 | https://raw.githubusercontent.com/ekwus/websocketsharper/master/LICENSE.txt
10 | https://github.com/ekwus/websocketsharper
11 | websocket;
12 | WebSocketSharper
13 | WebSocket Client and Server library suitable for DI and Unit Testing.
14 |
15 | Based on WebSocketSharp, modified to target .NETStandard and support projects utilising DI
16 | https://github.com/ekwus/websocketsharper/blob/master/websocketsharper_icon.png?raw=true
17 |
18 |
19 |
20 | ../../build/Debug/WebSocketSharper
21 |
22 |
23 |
24 | ../../build/Release/WebSocketSharper
25 |
26 |
27 |
28 |
29 |
30 | all
31 | runtime; build; native; contentfiles; analyzers
32 |
33 |
34 |
35 |
36 |
37 |
38 | Always
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Fin.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * Fin.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2012-2015 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 |
31 | namespace WebSocketSharper
32 | {
33 | ///
34 | /// Indicates whether a WebSocket frame is the final frame of a message.
35 | ///
36 | ///
37 | /// The values of this enumeration are defined in
38 | /// Section 5.2 of RFC 6455.
39 | ///
40 | internal enum Fin : byte
41 | {
42 | ///
43 | /// Equivalent to numeric value 0. Indicates more frames of a message follow.
44 | ///
45 | More = 0x0,
46 | ///
47 | /// Equivalent to numeric value 1. Indicates the final frame of a message.
48 | ///
49 | Final = 0x1
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Test/TestSupport/TestGate.cs:
--------------------------------------------------------------------------------
1 | using NodaTime;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using System.Threading;
6 | using Xunit;
7 |
8 | namespace TestSupport
9 | {
10 | public class TestGate : BaseDisposable where T : Enum
11 | {
12 | private Dictionary m_signals;
13 |
14 | public TestGate()
15 | {
16 | m_signals = new Dictionary();
17 | }
18 |
19 | public void Set(T token)
20 | {
21 | using (SyncRoot.Enter())
22 | {
23 | var signal = GetSignal(token);
24 | signal.Set();
25 | }
26 | }
27 |
28 | public bool WaitFor(T token, Duration timeout)
29 | {
30 | return WaitFor(token, (int)timeout.TotalMilliseconds);
31 | }
32 |
33 | public bool WaitFor(T token, int milliseconds)
34 | {
35 | AutoResetEvent signal = GetSignal(token);
36 | return signal.WaitOne(milliseconds);
37 | }
38 |
39 | public void AssertWaitFor(T token, Duration timeout)
40 | {
41 | AssertWaitFor(token, (int)timeout.TotalMilliseconds);
42 | }
43 |
44 | public void AssertWaitFor(T token, int milliseconds)
45 | {
46 | Assert.True(WaitFor(token, milliseconds), token.ToString());
47 | }
48 |
49 | private AutoResetEvent GetSignal(T token)
50 | {
51 | using (SyncRoot.Enter())
52 | {
53 | if (!m_signals.ContainsKey(token))
54 | {
55 | m_signals[token] = new AutoResetEvent(false);
56 | }
57 |
58 | return m_signals[token];
59 | }
60 | }
61 |
62 | protected override void Dispose(bool disposing)
63 | {
64 | foreach(var signal in m_signals.Values)
65 | {
66 | signal?.Dispose();
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/AuthenticationSchemes.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * AuthenticationSchemes.cs
4 | *
5 | * This code is derived from AuthenticationSchemes.cs (System.Net) of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
11 | * Copyright (c) 2012-2016 sta.blockhead
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy
14 | * of this software and associated documentation files (the "Software"), to deal
15 | * in the Software without restriction, including without limitation the rights
16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | * copies of the Software, and to permit persons to whom the Software is
18 | * furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | * THE SOFTWARE.
30 | */
31 | #endregion
32 |
33 | #region Authors
34 | /*
35 | * Authors:
36 | * - Atsushi Enomoto
37 | */
38 | #endregion
39 |
40 | using System;
41 |
42 | namespace WebSocketSharper.Net
43 | {
44 | ///
45 | /// Specifies the scheme for authentication.
46 | ///
47 | public enum AuthenticationSchemes
48 | {
49 | ///
50 | /// No authentication is allowed.
51 | ///
52 | None,
53 | ///
54 | /// Specifies digest authentication.
55 | ///
56 | Digest = 1,
57 | ///
58 | /// Specifies basic authentication.
59 | ///
60 | Basic = 8,
61 | ///
62 | /// Specifies anonymous authentication.
63 | ///
64 | Anonymous = 0x8000
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/HttpVersion.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * HttpVersion.cs
4 | *
5 | * This code is derived from System.Net.HttpVersion.cs of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2012-2014 sta.blockhead
11 | *
12 | * Permission is hereby granted, free of charge, to any person obtaining a copy
13 | * of this software and associated documentation files (the "Software"), to deal
14 | * in the Software without restriction, including without limitation the rights
15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 | * copies of the Software, and to permit persons to whom the Software is
17 | * furnished to do so, subject to the following conditions:
18 | *
19 | * The above copyright notice and this permission notice shall be included in
20 | * all copies or substantial portions of the Software.
21 | *
22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 | * THE SOFTWARE.
29 | */
30 | #endregion
31 |
32 | #region Authors
33 | /*
34 | * Authors:
35 | * - Lawrence Pit
36 | */
37 | #endregion
38 |
39 | using System;
40 |
41 | namespace WebSocketSharper.Net
42 | {
43 | ///
44 | /// Provides the HTTP version numbers.
45 | ///
46 | public class HttpVersion
47 | {
48 | #region Public Fields
49 |
50 | ///
51 | /// Provides a instance for the HTTP/1.0.
52 | ///
53 | public static readonly Version Version10 = new Version (1, 0);
54 |
55 | ///
56 | /// Provides a instance for the HTTP/1.1.
57 | ///
58 | public static readonly Version Version11 = new Version (1, 1);
59 |
60 | #endregion
61 |
62 | #region Public Constructors
63 |
64 | ///
65 | /// Initializes a new instance of the class.
66 | ///
67 | public HttpVersion ()
68 | {
69 | }
70 |
71 | #endregion
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Opcode.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * Opcode.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2012-2016 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 |
31 | namespace WebSocketSharper
32 | {
33 | ///
34 | /// Indicates the WebSocket frame type.
35 | ///
36 | ///
37 | /// The values of this enumeration are defined in
38 | ///
39 | /// Section 5.2 of RFC 6455.
40 | ///
41 | internal enum Opcode : byte
42 | {
43 | ///
44 | /// Equivalent to numeric value 0. Indicates continuation frame.
45 | ///
46 | Cont = 0x0,
47 | ///
48 | /// Equivalent to numeric value 1. Indicates text frame.
49 | ///
50 | Text = 0x1,
51 | ///
52 | /// Equivalent to numeric value 2. Indicates binary frame.
53 | ///
54 | Binary = 0x2,
55 | ///
56 | /// Equivalent to numeric value 8. Indicates connection close frame.
57 | ///
58 | Close = 0x8,
59 | ///
60 | /// Equivalent to numeric value 9. Indicates ping frame.
61 | ///
62 | Ping = 0x9,
63 | ///
64 | /// Equivalent to numeric value 10. Indicates pong frame.
65 | ///
66 | Pong = 0xa
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/WebSocketState.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * WebSocketState.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2010-2016 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 |
31 | namespace WebSocketSharper
32 | {
33 | ///
34 | /// Indicates the state of a WebSocket connection.
35 | ///
36 | ///
37 | /// The values of this enumeration are defined in
38 | ///
39 | /// The WebSocket API.
40 | ///
41 | public enum WebSocketState : ushort
42 | {
43 | ///
44 | /// Equivalent to numeric value 0. Indicates that the connection has not
45 | /// yet been established.
46 | ///
47 | Connecting = 0,
48 | ///
49 | /// Equivalent to numeric value 1. Indicates that the connection has
50 | /// been established, and the communication is possible.
51 | ///
52 | Open = 1,
53 | ///
54 | /// Equivalent to numeric value 2. Indicates that the connection is
55 | /// going through the closing handshake, or the close method has
56 | /// been invoked.
57 | ///
58 | Closing = 2,
59 | ///
60 | /// Equivalent to numeric value 3. Indicates that the connection has
61 | /// been closed or could not be established.
62 | ///
63 | Closed = 3
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/Chunk.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * Chunk.cs
4 | *
5 | * This code is derived from ChunkStream.cs (System.Net) of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2003 Ximian, Inc (http://www.ximian.com)
11 | * Copyright (c) 2014-2015 sta.blockhead
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy
14 | * of this software and associated documentation files (the "Software"), to deal
15 | * in the Software without restriction, including without limitation the rights
16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | * copies of the Software, and to permit persons to whom the Software is
18 | * furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | * THE SOFTWARE.
30 | */
31 | #endregion
32 |
33 | #region Authors
34 | /*
35 | * Authors:
36 | * - Gonzalo Paniagua Javier
37 | */
38 | #endregion
39 |
40 | using System;
41 |
42 | namespace WebSocketSharper.Net
43 | {
44 | internal class Chunk
45 | {
46 | #region Private Fields
47 |
48 | private byte[] _data;
49 | private int _offset;
50 |
51 | #endregion
52 |
53 | #region Public Constructors
54 |
55 | public Chunk (byte[] data)
56 | {
57 | _data = data;
58 | }
59 |
60 | #endregion
61 |
62 | #region Public Properties
63 |
64 | public int ReadLeft {
65 | get {
66 | return _data.Length - _offset;
67 | }
68 | }
69 |
70 | #endregion
71 |
72 | #region Public Methods
73 |
74 | public int Read (byte[] buffer, int offset, int count)
75 | {
76 | var left = _data.Length - _offset;
77 | if (left == 0)
78 | return left;
79 |
80 | if (count > left)
81 | count = left;
82 |
83 | Buffer.BlockCopy (_data, _offset, buffer, offset, count);
84 | _offset += count;
85 |
86 | return count;
87 | }
88 |
89 | #endregion
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/HttpBasicIdentity.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * HttpBasicIdentity.cs
4 | *
5 | * This code is derived from HttpListenerBasicIdentity.cs (System.Net) of
6 | * Mono (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
11 | * Copyright (c) 2014-2017 sta.blockhead
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy
14 | * of this software and associated documentation files (the "Software"), to deal
15 | * in the Software without restriction, including without limitation the rights
16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | * copies of the Software, and to permit persons to whom the Software is
18 | * furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | * THE SOFTWARE.
30 | */
31 | #endregion
32 |
33 | #region Authors
34 | /*
35 | * Authors:
36 | * - Gonzalo Paniagua Javier
37 | */
38 | #endregion
39 |
40 | using System;
41 | using System.Security.Principal;
42 |
43 | namespace WebSocketSharper.Net
44 | {
45 | ///
46 | /// Holds the username and password from an HTTP Basic authentication attempt.
47 | ///
48 | public class HttpBasicIdentity : GenericIdentity
49 | {
50 | #region Private Fields
51 |
52 | private string _password;
53 |
54 | #endregion
55 |
56 | #region Internal Constructors
57 |
58 | internal HttpBasicIdentity (string username, string password)
59 | : base (username, "Basic")
60 | {
61 | _password = password;
62 | }
63 |
64 | #endregion
65 |
66 | #region Public Properties
67 |
68 | ///
69 | /// Gets the password from a basic authentication attempt.
70 | ///
71 | ///
72 | /// A that represents the password.
73 | ///
74 | public virtual string Password {
75 | get {
76 | return _password;
77 | }
78 | }
79 |
80 | #endregion
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/Test/TestSupport/SafeLock.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.Serialization;
4 | using System.Text;
5 | using System.Threading;
6 |
7 | namespace TestSupport
8 | {
9 | public class SafeLock
10 | {
11 | #if DEBUG
12 | private static TimeSpan sm_timeout = TimeSpan.FromMinutes(1.0);
13 | #else
14 | private static TimeSpan sm_timeout = TimeSpan.FromMinutes(10.0);
15 | #endif
16 | public static TimeSpan Timeout
17 | {
18 | get { return sm_timeout; }
19 | set { sm_timeout = value; }
20 | }
21 |
22 | private struct SafeLockDisposer : IDisposable
23 | {
24 | private SafeLock m_owner;
25 |
26 | public SafeLockDisposer(SafeLock owner)
27 | {
28 | m_owner = owner;
29 | }
30 |
31 | public void Dispose()
32 | {
33 | m_owner.Exit();
34 | }
35 | }
36 |
37 | private object m_synchronised = null;
38 | private Thread m_thread = null;
39 | private int m_ref = 0;
40 |
41 | public SafeLock()
42 | {
43 | m_synchronised = new object();
44 | }
45 |
46 | public bool TryEnter()
47 | {
48 | if (Monitor.TryEnter(m_synchronised, sm_timeout))
49 | {
50 | if (m_thread == null)
51 | {
52 | m_thread = Thread.CurrentThread;
53 | m_ref = 1;
54 | }
55 | else if (m_thread == Thread.CurrentThread)
56 | {
57 | m_ref++;
58 | }
59 | else
60 | {
61 | throw new Exception("SafeLock held by another Thread");
62 | }
63 |
64 | return true;
65 | }
66 | else
67 | {
68 | return false;
69 | }
70 | }
71 |
72 | public IDisposable Enter()
73 | {
74 | if (!TryEnter())
75 | {
76 | throw new TimeoutException("Timed out waiting for lock");
77 | }
78 |
79 | return new SafeLockDisposer(this);
80 | }
81 |
82 | public void Exit()
83 | {
84 | if (m_thread != Thread.CurrentThread)
85 | {
86 | throw new SafeLockException("Only the locks thread can release it");
87 | }
88 |
89 | m_ref--;
90 |
91 | if (m_ref == 0)
92 | {
93 | m_thread = null;
94 | }
95 |
96 | Monitor.Exit(m_synchronised);
97 | }
98 | }
99 |
100 | public class SafeLockException : Exception
101 | {
102 | public SafeLockException(string message) : base(message)
103 | {
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/Samples/SimpleServer/SimpleSecureServer.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Hosting;
2 | using Microsoft.Extensions.Logging;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Net.Security;
6 | using System.Security.Cryptography.X509Certificates;
7 | using System.Text;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using WebSocketSharper;
11 | using WebSocketSharper.Server;
12 |
13 | namespace SimpleServer
14 | {
15 | public class SimpleSecureServer : IHostedService
16 | {
17 | private readonly ILogger m_logger;
18 | private readonly IHostApplicationLifetime m_appLifetime;
19 | private WebSocketServer m_server;
20 |
21 | public SimpleSecureServer(ILogger logger, IHostApplicationLifetime appLifetime)
22 | {
23 | m_logger = logger;
24 | m_appLifetime = appLifetime;
25 | }
26 |
27 | public Task StartAsync(CancellationToken cancellationToken)
28 | {
29 | m_appLifetime.ApplicationStarted.Register(OnStarted);
30 | m_appLifetime.ApplicationStopping.Register(OnStopping);
31 | m_appLifetime.ApplicationStopped.Register(OnStopped);
32 |
33 | return Task.CompletedTask;
34 | }
35 |
36 | public Task StopAsync(CancellationToken cancellationToken)
37 | {
38 | return Task.CompletedTask;
39 | }
40 |
41 | private void OnStarted()
42 | {
43 | m_logger.LogDebug("OnStarted Called");
44 | m_server = new WebSocketServer(m_logger, 8855, true);
45 | m_server.SslConfiguration.ServerCertificate = new X509Certificate2("localhost.pfx", "password");
46 | m_server.SslConfiguration.ClientCertificateRequired = true;
47 | m_server.SslConfiguration.ClientCertificateValidationCallback += delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
48 | {
49 | // Only allow our specific client
50 | return certificate.GetCertHashString() == "A92F0F40ED8BF3F2CF857E9CF00A5BD6AB3184DF";
51 | };
52 |
53 | m_server.AddWebSocketService("/chat");
54 | m_server.Start();
55 |
56 | Console.WriteLine("Press Ctrl+C to exit");
57 | }
58 |
59 | private void OnStopping()
60 | {
61 | m_logger.LogDebug("OnStopping Called");
62 | m_server.Stop();
63 | }
64 |
65 | private void OnStopped()
66 | {
67 | m_logger.LogDebug("OnStopped Called");
68 | }
69 | }
70 |
71 | public class ChatBehaviour : WebSocketBehavior
72 | {
73 | public ChatBehaviour()
74 | {
75 |
76 | }
77 |
78 | protected override void OnMessage(MessageEventArgs e)
79 | {
80 | var chars = e.Data.ToCharArray();
81 | Array.Reverse(chars);
82 | Send(new String(chars));
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Server/WebSocketServiceHost`1.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * WebSocketServiceHost`1.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2015-2017 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using Microsoft.Extensions.Logging;
30 | using System;
31 |
32 | namespace WebSocketSharper.Server
33 | {
34 | internal class WebSocketServiceHost : WebSocketServiceHost
35 | where TBehavior : WebSocketBehavior
36 | {
37 | #region Private Fields
38 |
39 | private Func _creator;
40 |
41 | #endregion
42 |
43 | #region Internal Constructors
44 |
45 | internal WebSocketServiceHost (
46 | string path, Func creator, ILogger log
47 | )
48 | : this (path, creator, null, log)
49 | {
50 | }
51 |
52 | internal WebSocketServiceHost (
53 | string path,
54 | Func creator,
55 | Action initializer,
56 | ILogger log
57 | )
58 | : base (path, log)
59 | {
60 | _creator = createCreator (creator, initializer);
61 | }
62 |
63 | #endregion
64 |
65 | #region Public Properties
66 |
67 | public override Type BehaviorType {
68 | get {
69 | return typeof (TBehavior);
70 | }
71 | }
72 |
73 | #endregion
74 |
75 | #region Private Methods
76 |
77 | private Func createCreator (
78 | Func creator, Action initializer
79 | )
80 | {
81 | if (initializer == null)
82 | return creator;
83 |
84 | return () => {
85 | var ret = creator ();
86 | initializer (ret);
87 |
88 | return ret;
89 | };
90 | }
91 |
92 | #endregion
93 |
94 | #region Protected Methods
95 |
96 | protected override WebSocketBehavior CreateSession ()
97 | {
98 | return _creator ();
99 | }
100 |
101 | #endregion
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Server/IWebSocketSession.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * IWebSocketSession.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2013-2018 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 | using WebSocketSharper.Net.WebSockets;
31 |
32 | namespace WebSocketSharper.Server
33 | {
34 | ///
35 | /// Exposes the access to the information in a WebSocket session.
36 | ///
37 | public interface IWebSocketSession
38 | {
39 | #region Properties
40 |
41 | ///
42 | /// Gets the current state of the WebSocket connection for the session.
43 | ///
44 | ///
45 | ///
46 | /// One of the enum values.
47 | ///
48 | ///
49 | /// It indicates the current state of the connection.
50 | ///
51 | ///
52 | WebSocketState ConnectionState { get; }
53 |
54 | ///
55 | /// Gets the information in the WebSocket handshake request.
56 | ///
57 | ///
58 | /// A instance that provides the access to
59 | /// the information in the handshake request.
60 | ///
61 | WebSocketContext Context { get; }
62 |
63 | ///
64 | /// Gets the unique ID of the session.
65 | ///
66 | ///
67 | /// A that represents the unique ID of the session.
68 | ///
69 | string ID { get; }
70 |
71 | ///
72 | /// Gets the name of the WebSocket subprotocol for the session.
73 | ///
74 | ///
75 | /// A that represents the name of the subprotocol
76 | /// if present.
77 | ///
78 | string Protocol { get; }
79 |
80 | ///
81 | /// Gets the time that the session has started.
82 | ///
83 | ///
84 | /// A that represents the time that the session
85 | /// has started.
86 | ///
87 | DateTime StartTime { get; }
88 |
89 | #endregion
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/ReadBufferState.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * ReadBufferState.cs
4 | *
5 | * This code is derived from ChunkedInputStream.cs (System.Net) of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
11 | * Copyright (c) 2014-2015 sta.blockhead
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy
14 | * of this software and associated documentation files (the "Software"), to deal
15 | * in the Software without restriction, including without limitation the rights
16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | * copies of the Software, and to permit persons to whom the Software is
18 | * furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | * THE SOFTWARE.
30 | */
31 | #endregion
32 |
33 | #region Authors
34 | /*
35 | * Authors:
36 | * - Gonzalo Paniagua Javier
37 | */
38 | #endregion
39 |
40 | using System;
41 |
42 | namespace WebSocketSharper.Net
43 | {
44 | internal class ReadBufferState
45 | {
46 | #region Private Fields
47 |
48 | private HttpStreamAsyncResult _asyncResult;
49 | private byte[] _buffer;
50 | private int _count;
51 | private int _initialCount;
52 | private int _offset;
53 |
54 | #endregion
55 |
56 | #region Public Constructors
57 |
58 | public ReadBufferState (
59 | byte[] buffer, int offset, int count, HttpStreamAsyncResult asyncResult)
60 | {
61 | _buffer = buffer;
62 | _offset = offset;
63 | _count = count;
64 | _initialCount = count;
65 | _asyncResult = asyncResult;
66 | }
67 |
68 | #endregion
69 |
70 | #region Public Properties
71 |
72 | public HttpStreamAsyncResult AsyncResult {
73 | get {
74 | return _asyncResult;
75 | }
76 |
77 | set {
78 | _asyncResult = value;
79 | }
80 | }
81 |
82 | public byte[] Buffer {
83 | get {
84 | return _buffer;
85 | }
86 |
87 | set {
88 | _buffer = value;
89 | }
90 | }
91 |
92 | public int Count {
93 | get {
94 | return _count;
95 | }
96 |
97 | set {
98 | _count = value;
99 | }
100 | }
101 |
102 | public int InitialCount {
103 | get {
104 | return _initialCount;
105 | }
106 |
107 | set {
108 | _initialCount = value;
109 | }
110 | }
111 |
112 | public int Offset {
113 | get {
114 | return _offset;
115 | }
116 |
117 | set {
118 | _offset = value;
119 | }
120 | }
121 |
122 | #endregion
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/HttpHeaderInfo.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * HttpHeaderInfo.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2013-2014 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 |
31 | namespace WebSocketSharper.Net
32 | {
33 | internal class HttpHeaderInfo
34 | {
35 | #region Private Fields
36 |
37 | private string _name;
38 | private HttpHeaderType _type;
39 |
40 | #endregion
41 |
42 | #region Internal Constructors
43 |
44 | internal HttpHeaderInfo (string name, HttpHeaderType type)
45 | {
46 | _name = name;
47 | _type = type;
48 | }
49 |
50 | #endregion
51 |
52 | #region Internal Properties
53 |
54 | internal bool IsMultiValueInRequest {
55 | get {
56 | return (_type & HttpHeaderType.MultiValueInRequest) == HttpHeaderType.MultiValueInRequest;
57 | }
58 | }
59 |
60 | internal bool IsMultiValueInResponse {
61 | get {
62 | return (_type & HttpHeaderType.MultiValueInResponse) == HttpHeaderType.MultiValueInResponse;
63 | }
64 | }
65 |
66 | #endregion
67 |
68 | #region Public Properties
69 |
70 | public bool IsRequest {
71 | get {
72 | return (_type & HttpHeaderType.Request) == HttpHeaderType.Request;
73 | }
74 | }
75 |
76 | public bool IsResponse {
77 | get {
78 | return (_type & HttpHeaderType.Response) == HttpHeaderType.Response;
79 | }
80 | }
81 |
82 | public string Name {
83 | get {
84 | return _name;
85 | }
86 | }
87 |
88 | public HttpHeaderType Type {
89 | get {
90 | return _type;
91 | }
92 | }
93 |
94 | #endregion
95 |
96 | #region Public Methods
97 |
98 | public bool IsMultiValue (bool response)
99 | {
100 | return (_type & HttpHeaderType.MultiValue) == HttpHeaderType.MultiValue
101 | ? (response ? IsResponse : IsRequest)
102 | : (response ? IsMultiValueInResponse : IsMultiValueInRequest);
103 | }
104 |
105 | public bool IsRestricted (bool response)
106 | {
107 | return (_type & HttpHeaderType.Restricted) == HttpHeaderType.Restricted
108 | ? (response ? IsResponse : IsRequest)
109 | : false;
110 | }
111 |
112 | #endregion
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/ErrorEventArgs.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * ErrorEventArgs.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2012-2016 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | #region Contributors
30 | /*
31 | * Contributors:
32 | * - Frank Razenberg
33 | */
34 | #endregion
35 |
36 | using System;
37 |
38 | namespace WebSocketSharper
39 | {
40 | ///
41 | /// Represents the event data for the event.
42 | ///
43 | ///
44 | ///
45 | /// That event occurs when the gets an error.
46 | ///
47 | ///
48 | /// If you would like to get the error message, you should access
49 | /// the property.
50 | ///
51 | ///
52 | /// And if the error is due to an exception, you can get it by accessing
53 | /// the property.
54 | ///
55 | ///
56 | public class ErrorEventArgs : EventArgs
57 | {
58 | #region Private Fields
59 |
60 | private Exception _exception;
61 | private string _message;
62 |
63 | #endregion
64 |
65 | #region Internal Constructors
66 |
67 | internal ErrorEventArgs (string message)
68 | : this (message, null)
69 | {
70 | }
71 |
72 | internal ErrorEventArgs (string message, Exception exception)
73 | {
74 | _message = message;
75 | _exception = exception;
76 | }
77 |
78 | #endregion
79 |
80 | #region Public Properties
81 |
82 | ///
83 | /// Gets the exception that caused the error.
84 | ///
85 | ///
86 | /// An instance that represents the cause of
87 | /// the error if it is due to an exception; otherwise, .
88 | ///
89 | public Exception Exception {
90 | get {
91 | return _exception;
92 | }
93 | }
94 |
95 | ///
96 | /// Gets the error message.
97 | ///
98 | ///
99 | /// A that represents the error message.
100 | ///
101 | public string Message {
102 | get {
103 | return _message;
104 | }
105 | }
106 |
107 | #endregion
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/WebSocketException.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * WebSocketException.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2012-2016 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 |
31 | namespace WebSocketSharper
32 | {
33 | ///
34 | /// The exception that is thrown when a fatal error occurs in
35 | /// the WebSocket communication.
36 | ///
37 | public class WebSocketException : Exception
38 | {
39 | #region Private Fields
40 |
41 | private CloseStatusCode _code;
42 |
43 | #endregion
44 |
45 | #region Internal Constructors
46 |
47 | internal WebSocketException ()
48 | : this (CloseStatusCode.Abnormal, null, null)
49 | {
50 | }
51 |
52 | internal WebSocketException (Exception innerException)
53 | : this (CloseStatusCode.Abnormal, null, innerException)
54 | {
55 | }
56 |
57 | internal WebSocketException (string message)
58 | : this (CloseStatusCode.Abnormal, message, null)
59 | {
60 | }
61 |
62 | internal WebSocketException (CloseStatusCode code)
63 | : this (code, null, null)
64 | {
65 | }
66 |
67 | internal WebSocketException (string message, Exception innerException)
68 | : this (CloseStatusCode.Abnormal, message, innerException)
69 | {
70 | }
71 |
72 | internal WebSocketException (CloseStatusCode code, Exception innerException)
73 | : this (code, null, innerException)
74 | {
75 | }
76 |
77 | internal WebSocketException (CloseStatusCode code, string message)
78 | : this (code, message, null)
79 | {
80 | }
81 |
82 | internal WebSocketException (
83 | CloseStatusCode code, string message, Exception innerException
84 | )
85 | : base (message ?? code.GetMessage (), innerException)
86 | {
87 | _code = code;
88 | }
89 |
90 | #endregion
91 |
92 | #region Public Properties
93 |
94 | ///
95 | /// Gets the status code indicating the cause of the exception.
96 | ///
97 | ///
98 | /// One of the enum values that represents
99 | /// the status code indicating the cause of the exception.
100 | ///
101 | public CloseStatusCode Code {
102 | get {
103 | return _code;
104 | }
105 | }
106 |
107 | #endregion
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/Samples/SimpleClient/SimpleSecureClient.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Hosting;
2 | using Microsoft.Extensions.Logging;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Net.Security;
6 | using System.Security.Cryptography.X509Certificates;
7 | using System.Text;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using WebSocketSharper;
11 |
12 | namespace SimpleClient
13 | {
14 | public class SimpleSecureClient : IHostedService
15 | {
16 | private readonly ILogger m_logger;
17 | private readonly IHostApplicationLifetime m_appLifetime;
18 | private WebSocket m_client;
19 | private bool m_running;
20 |
21 | public SimpleSecureClient(ILogger logger, IHostApplicationLifetime appLifetime)
22 | {
23 | m_logger = logger;
24 | m_appLifetime = appLifetime;
25 | }
26 |
27 | public Task StartAsync(CancellationToken cancellationToken)
28 | {
29 | m_appLifetime.ApplicationStarted.Register(OnStarted);
30 | m_appLifetime.ApplicationStopping.Register(OnStopping);
31 | m_appLifetime.ApplicationStopped.Register(OnStopped);
32 |
33 | return Task.CompletedTask;
34 | }
35 |
36 | public Task StopAsync(CancellationToken cancellationToken)
37 | {
38 | return Task.CompletedTask;
39 | }
40 |
41 | private void OnStarted()
42 | {
43 | m_logger.LogDebug("OnStarted Called");
44 | m_running = true;
45 |
46 | m_client = new WebSocket(m_logger, "wss://localhost:8855/chat", false);
47 | m_client.SslConfiguration.ClientCertificates = new X509CertificateCollection();
48 | var localCert = new X509Certificate2("client.pfx", "password");
49 | m_client.SslConfiguration.ClientCertificates.Add(localCert);
50 | m_client.SslConfiguration.ClientCertificateSelectionCallback += (sender, host, certs, remote, issuers) =>
51 | {
52 | return localCert;
53 | };
54 | m_client.SslConfiguration.ServerCertificateValidationCallback += delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
55 | {
56 | // Validate this is our server
57 | return certificate.GetCertHashString() == "9C39BEDE53BC34F11609E6E8F8E56C0028E07213";
58 | };
59 | m_client.OnMessage += (sender, e) =>
60 | {
61 | m_logger.LogDebug(e.Data);
62 | };
63 |
64 | m_client.OnOpen += (sender, e) =>
65 | {
66 | m_client.Send("Hello");
67 | };
68 |
69 | m_client.Connect();
70 |
71 | Task.Run(() =>
72 | {
73 | string msg = null;
74 | while (m_running && !string.IsNullOrEmpty(msg = Console.ReadLine()))
75 | {
76 | if (!m_client.IsAlive)
77 | {
78 | m_logger.LogDebug("Connection to the server has been closed");
79 | break;
80 | }
81 | m_client.Send(msg);
82 | }
83 | });
84 | }
85 |
86 | private void OnStopping()
87 | {
88 | m_logger.LogDebug("OnStopping Called");
89 | m_running = false;
90 | m_client.Close();
91 | }
92 |
93 | private void OnStopped()
94 | {
95 | m_logger.LogDebug("OnStopped Called");
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/CloseEventArgs.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * CloseEventArgs.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2012-2019 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 |
31 | namespace WebSocketSharper
32 | {
33 | ///
34 | /// Represents the event data for the event.
35 | ///
36 | ///
37 | ///
38 | /// That event occurs when the WebSocket connection has been closed.
39 | ///
40 | ///
41 | /// If you would like to get the reason for the connection close, you should
42 | /// access the or property.
43 | ///
44 | ///
45 | public class CloseEventArgs : EventArgs
46 | {
47 | #region Private Fields
48 |
49 | private bool _clean;
50 | private PayloadData _payloadData;
51 |
52 | #endregion
53 |
54 | #region Internal Constructors
55 |
56 | internal CloseEventArgs (PayloadData payloadData, bool clean)
57 | {
58 | _payloadData = payloadData;
59 | _clean = clean;
60 | }
61 |
62 | internal CloseEventArgs (ushort code, string reason, bool clean)
63 | {
64 | _payloadData = new PayloadData (code, reason);
65 | _clean = clean;
66 | }
67 |
68 | #endregion
69 |
70 | #region Public Properties
71 |
72 | ///
73 | /// Gets the status code for the connection close.
74 | ///
75 | ///
76 | /// A that represents the status code for
77 | /// the connection close if present.
78 | ///
79 | public ushort Code {
80 | get {
81 | return _payloadData.Code;
82 | }
83 | }
84 |
85 | ///
86 | /// Gets the reason for the connection close.
87 | ///
88 | ///
89 | /// A that represents the reason for
90 | /// the connection close if present.
91 | ///
92 | public string Reason {
93 | get {
94 | return _payloadData.Reason;
95 | }
96 | }
97 |
98 | ///
99 | /// Gets a value indicating whether the connection has been closed cleanly.
100 | ///
101 | ///
102 | /// true if the connection has been closed cleanly; otherwise,
103 | /// false.
104 | ///
105 | public bool WasClean {
106 | get {
107 | return _clean;
108 | }
109 | }
110 |
111 | #endregion
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/websocket-sharper.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.489
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{1B665784-B1EC-48FA-B34D-FC6648BFBFE9}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSocketSharperTests", "src\Test\WebSocketSharperTests\WebSocketSharperTests.csproj", "{AB3912E0-EAFA-444E-9EAF-1BD58B934E61}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestSupport", "src\Test\TestSupport\TestSupport.csproj", "{95E6F7AA-A502-47E8-9128-FBCD3F7DD808}"
11 | EndProject
12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{23363961-7A28-4C38-A962-B8D32FFCC5B1}"
13 | EndProject
14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleServer", "src\Samples\SimpleServer\SimpleServer.csproj", "{448068B5-366C-49D0-B9F4-F0C366335295}"
15 | EndProject
16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleClient", "src\Samples\SimpleClient\SimpleClient.csproj", "{9365E23F-DCDF-4D96-A4C6-F3406CEEF6F3}"
17 | EndProject
18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSocketSharper", "src\WebSocketSharper\WebSocketSharper.csproj", "{F67428E9-5257-4858-A724-C7920084256B}"
19 | EndProject
20 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DC9331F6-D9B5-4B28-84A2-00A2498633AF}"
21 | ProjectSection(SolutionItems) = preProject
22 | .gitignore = .gitignore
23 | .github\workflows\dotnetcore.yml = .github\workflows\dotnetcore.yml
24 | LICENSE.txt = LICENSE.txt
25 | README.md = README.md
26 | version.json = version.json
27 | EndProjectSection
28 | EndProject
29 | Global
30 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
31 | Debug|Any CPU = Debug|Any CPU
32 | Release|Any CPU = Release|Any CPU
33 | EndGlobalSection
34 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
35 | {AB3912E0-EAFA-444E-9EAF-1BD58B934E61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
36 | {AB3912E0-EAFA-444E-9EAF-1BD58B934E61}.Debug|Any CPU.Build.0 = Debug|Any CPU
37 | {AB3912E0-EAFA-444E-9EAF-1BD58B934E61}.Release|Any CPU.ActiveCfg = Release|Any CPU
38 | {AB3912E0-EAFA-444E-9EAF-1BD58B934E61}.Release|Any CPU.Build.0 = Release|Any CPU
39 | {95E6F7AA-A502-47E8-9128-FBCD3F7DD808}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
40 | {95E6F7AA-A502-47E8-9128-FBCD3F7DD808}.Debug|Any CPU.Build.0 = Debug|Any CPU
41 | {95E6F7AA-A502-47E8-9128-FBCD3F7DD808}.Release|Any CPU.ActiveCfg = Release|Any CPU
42 | {95E6F7AA-A502-47E8-9128-FBCD3F7DD808}.Release|Any CPU.Build.0 = Release|Any CPU
43 | {448068B5-366C-49D0-B9F4-F0C366335295}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44 | {448068B5-366C-49D0-B9F4-F0C366335295}.Debug|Any CPU.Build.0 = Debug|Any CPU
45 | {448068B5-366C-49D0-B9F4-F0C366335295}.Release|Any CPU.ActiveCfg = Release|Any CPU
46 | {448068B5-366C-49D0-B9F4-F0C366335295}.Release|Any CPU.Build.0 = Release|Any CPU
47 | {9365E23F-DCDF-4D96-A4C6-F3406CEEF6F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
48 | {9365E23F-DCDF-4D96-A4C6-F3406CEEF6F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
49 | {9365E23F-DCDF-4D96-A4C6-F3406CEEF6F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
50 | {9365E23F-DCDF-4D96-A4C6-F3406CEEF6F3}.Release|Any CPU.Build.0 = Release|Any CPU
51 | {F67428E9-5257-4858-A724-C7920084256B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
52 | {F67428E9-5257-4858-A724-C7920084256B}.Debug|Any CPU.Build.0 = Debug|Any CPU
53 | {F67428E9-5257-4858-A724-C7920084256B}.Release|Any CPU.ActiveCfg = Release|Any CPU
54 | {F67428E9-5257-4858-A724-C7920084256B}.Release|Any CPU.Build.0 = Release|Any CPU
55 | EndGlobalSection
56 | GlobalSection(SolutionProperties) = preSolution
57 | HideSolutionNode = FALSE
58 | EndGlobalSection
59 | GlobalSection(NestedProjects) = preSolution
60 | {AB3912E0-EAFA-444E-9EAF-1BD58B934E61} = {1B665784-B1EC-48FA-B34D-FC6648BFBFE9}
61 | {95E6F7AA-A502-47E8-9128-FBCD3F7DD808} = {1B665784-B1EC-48FA-B34D-FC6648BFBFE9}
62 | {448068B5-366C-49D0-B9F4-F0C366335295} = {23363961-7A28-4C38-A962-B8D32FFCC5B1}
63 | {9365E23F-DCDF-4D96-A4C6-F3406CEEF6F3} = {23363961-7A28-4C38-A962-B8D32FFCC5B1}
64 | EndGlobalSection
65 | GlobalSection(ExtensibilityGlobals) = postSolution
66 | SolutionGuid = {D5E684ED-D278-44BB-91A3-4ACD742F7FDB}
67 | EndGlobalSection
68 | EndGlobal
69 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Interfaces.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Net.WebSockets;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using WebSocketSharper.Net;
7 | using WebSocketSharper.Server;
8 |
9 | namespace WebSocketSharper
10 | {
11 | public interface IWebSocketServer : IDisposable
12 | {
13 | Task StartTaskAsync();
14 | Task AddWebSocketServiceTaskAsync(string path, Action initialise) where TBehaviour : WebSocketBehavior, new();
15 | Task AddWebSocketServiceTaskAsync(string path, Func factory) where TBehaviour : WebSocketBehavior;
16 | Task StopTaskAsync();
17 | bool AllowForwardedRequest { get; set; }
18 | }
19 |
20 | public enum ReconnectionType
21 | {
22 | ///
23 | /// Type used for initial connection to websocket stream
24 | ///
25 | Initial = 0,
26 |
27 | ///
28 | /// Type used when connection to websocket was lost in meantime
29 | ///
30 | Lost = 1,
31 |
32 | ///
33 | /// Type used when connection to websocket was lost by not receiving any message in given time-range
34 | ///
35 | NoMessageReceived = 2,
36 |
37 | ///
38 | /// Type used after unsuccessful previous reconnection
39 | ///
40 | Error = 3,
41 |
42 | ///
43 | /// Type used when reconnection was requested by user
44 | ///
45 | ByUser = 4
46 | }
47 |
48 | public enum DisconnectionType
49 | {
50 | ///
51 | /// Type used for exit event, disposing of the websocket client
52 | ///
53 | Exit = 0,
54 |
55 | ///
56 | /// Type used when connection to websocket was lost in meantime
57 | ///
58 | Lost = 1,
59 |
60 | ///
61 | /// Type used when connection to websocket was lost by not receiving any message in given time-range
62 | ///
63 | NoMessageReceived = 2,
64 |
65 | ///
66 | /// Type used when connection or reconnection returned error
67 | ///
68 | Error = 3,
69 |
70 | ///
71 | /// Type used when disconnection was requested by user
72 | ///
73 | ByUser = 4
74 | }
75 |
76 | public class WebMessage
77 | {
78 | private WebMessage(byte[] binary, string text, WebSocketMessageType messageType)
79 | {
80 | Binary = binary;
81 | Text = text;
82 | MessageType = messageType;
83 | }
84 |
85 | ///
86 | /// Received text message (only if type = WebSocketMessageType.Text)
87 | ///
88 | public string Text { get; }
89 |
90 | ///
91 | /// Received text message (only if type = WebSocketMessageType.Binary)
92 | ///
93 | public byte[] Binary { get; }
94 |
95 | ///
96 | /// Current message type (Text or Binary)
97 | ///
98 | public WebSocketMessageType MessageType { get; }
99 |
100 | ///
101 | /// Return string info about the message
102 | ///
103 | public override string ToString()
104 | {
105 | if (MessageType == WebSocketMessageType.Text)
106 | {
107 | return Text;
108 | }
109 |
110 | return $"Type binary, length: {Binary?.Length}";
111 | }
112 |
113 | ///
114 | /// Create text response message
115 | ///
116 | public static WebMessage TextMessage(string data)
117 | {
118 | return new WebMessage(null, data, WebSocketMessageType.Text);
119 | }
120 |
121 | ///
122 | /// Create binary response message
123 | ///
124 | public static WebMessage BinaryMessage(byte[] data)
125 | {
126 | return new WebMessage(data, null, WebSocketMessageType.Binary);
127 | }
128 | }
129 |
130 | }
131 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/AuthenticationBase.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * AuthenticationBase.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2014 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 | using System.Collections.Specialized;
31 | using System.Text;
32 |
33 | namespace WebSocketSharper.Net
34 | {
35 | internal abstract class AuthenticationBase
36 | {
37 | #region Private Fields
38 |
39 | private AuthenticationSchemes _scheme;
40 |
41 | #endregion
42 |
43 | #region Internal Fields
44 |
45 | internal NameValueCollection Parameters;
46 |
47 | #endregion
48 |
49 | #region Protected Constructors
50 |
51 | protected AuthenticationBase (AuthenticationSchemes scheme, NameValueCollection parameters)
52 | {
53 | _scheme = scheme;
54 | Parameters = parameters;
55 | }
56 |
57 | #endregion
58 |
59 | #region Public Properties
60 |
61 | public string Algorithm {
62 | get {
63 | return Parameters["algorithm"];
64 | }
65 | }
66 |
67 | public string Nonce {
68 | get {
69 | return Parameters["nonce"];
70 | }
71 | }
72 |
73 | public string Opaque {
74 | get {
75 | return Parameters["opaque"];
76 | }
77 | }
78 |
79 | public string Qop {
80 | get {
81 | return Parameters["qop"];
82 | }
83 | }
84 |
85 | public string Realm {
86 | get {
87 | return Parameters["realm"];
88 | }
89 | }
90 |
91 | public AuthenticationSchemes Scheme {
92 | get {
93 | return _scheme;
94 | }
95 | }
96 |
97 | #endregion
98 |
99 | #region Internal Methods
100 |
101 | internal static string CreateNonceValue ()
102 | {
103 | var src = new byte[16];
104 | var rand = new Random ();
105 | rand.NextBytes (src);
106 |
107 | var res = new StringBuilder (32);
108 | foreach (var b in src)
109 | res.Append (b.ToString ("x2"));
110 |
111 | return res.ToString ();
112 | }
113 |
114 | internal static NameValueCollection ParseParameters (string value)
115 | {
116 | var res = new NameValueCollection ();
117 | foreach (var param in value.SplitHeaderValue (',')) {
118 | var i = param.IndexOf ('=');
119 | var name = i > 0 ? param.Substring (0, i).Trim () : null;
120 | var val = i < 0
121 | ? param.Trim ().Trim ('"')
122 | : i < param.Length - 1
123 | ? param.Substring (i + 1).Trim ().Trim ('"')
124 | : String.Empty;
125 |
126 | res.Add (name, val);
127 | }
128 |
129 | return res;
130 | }
131 |
132 | internal abstract string ToBasicString ();
133 |
134 | internal abstract string ToDigestString ();
135 |
136 | #endregion
137 |
138 | #region Public Methods
139 |
140 | public override string ToString ()
141 | {
142 | return _scheme == AuthenticationSchemes.Basic
143 | ? ToBasicString ()
144 | : _scheme == AuthenticationSchemes.Digest
145 | ? ToDigestString ()
146 | : String.Empty;
147 | }
148 |
149 | #endregion
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/HttpListenerException.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * HttpListenerException.cs
4 | *
5 | * This code is derived from System.Net.HttpListenerException.cs of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
11 | * Copyright (c) 2012-2014 sta.blockhead
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy
14 | * of this software and associated documentation files (the "Software"), to deal
15 | * in the Software without restriction, including without limitation the rights
16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | * copies of the Software, and to permit persons to whom the Software is
18 | * furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | * THE SOFTWARE.
30 | */
31 | #endregion
32 |
33 | #region Authors
34 | /*
35 | * Authors:
36 | * - Gonzalo Paniagua Javier
37 | */
38 | #endregion
39 |
40 | using System;
41 | using System.ComponentModel;
42 | using System.Runtime.Serialization;
43 |
44 | namespace WebSocketSharper.Net
45 | {
46 | ///
47 | /// The exception that is thrown when a gets an error
48 | /// processing an HTTP request.
49 | ///
50 | [Serializable]
51 | public class HttpListenerException : Win32Exception
52 | {
53 | #region Protected Constructors
54 |
55 | ///
56 | /// Initializes a new instance of the class from
57 | /// the specified and .
58 | ///
59 | ///
60 | /// A that contains the serialized object data.
61 | ///
62 | ///
63 | /// A that specifies the source for the deserialization.
64 | ///
65 | protected HttpListenerException (
66 | SerializationInfo serializationInfo, StreamingContext streamingContext)
67 | : base (serializationInfo, streamingContext)
68 | {
69 | }
70 |
71 | #endregion
72 |
73 | #region Public Constructors
74 |
75 | ///
76 | /// Initializes a new instance of the class.
77 | ///
78 | public HttpListenerException ()
79 | {
80 | }
81 |
82 | ///
83 | /// Initializes a new instance of the class
84 | /// with the specified .
85 | ///
86 | ///
87 | /// An that identifies the error.
88 | ///
89 | public HttpListenerException (int errorCode)
90 | : base (errorCode)
91 | {
92 | }
93 |
94 | ///
95 | /// Initializes a new instance of the class
96 | /// with the specified and .
97 | ///
98 | ///
99 | /// An that identifies the error.
100 | ///
101 | ///
102 | /// A that describes the error.
103 | ///
104 | public HttpListenerException (int errorCode, string message)
105 | : base (errorCode, message)
106 | {
107 | }
108 |
109 | #endregion
110 |
111 | #region Public Properties
112 |
113 | ///
114 | /// Gets the error code that identifies the error that occurred.
115 | ///
116 | ///
117 | /// An that identifies the error.
118 | ///
119 | public override int ErrorCode {
120 | get {
121 | return NativeErrorCode;
122 | }
123 | }
124 |
125 | #endregion
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/QueryStringCollection.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * QueryStringCollection.cs
4 | *
5 | * This code is derived from HttpUtility.cs (System.Net) of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2005-2009 Novell, Inc. (http://www.novell.com)
11 | * Copyright (c) 2018 sta.blockhead
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy
14 | * of this software and associated documentation files (the "Software"), to deal
15 | * in the Software without restriction, including without limitation the rights
16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | * copies of the Software, and to permit persons to whom the Software is
18 | * furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | * THE SOFTWARE.
30 | */
31 | #endregion
32 |
33 | #region Authors
34 | /*
35 | * Authors:
36 | * - Patrik Torstensson
37 | * - Wictor Wilén (decode/encode functions)
38 | * - Tim Coleman
39 | * - Gonzalo Paniagua Javier
40 | */
41 | #endregion
42 |
43 | using System;
44 | using System.Collections.Specialized;
45 | using System.Text;
46 |
47 | namespace WebSocketSharper.Net
48 | {
49 | internal sealed class QueryStringCollection : NameValueCollection
50 | {
51 | #region Public Constructors
52 |
53 | public QueryStringCollection ()
54 | {
55 | }
56 |
57 | public QueryStringCollection (int capacity)
58 | : base (capacity)
59 | {
60 | }
61 |
62 | #endregion
63 |
64 | #region Private Methods
65 |
66 | private static string urlDecode (string s, Encoding encoding)
67 | {
68 | return s.IndexOfAny (new[] { '%', '+' }) > -1
69 | ? HttpUtility.UrlDecode (s, encoding)
70 | : s;
71 | }
72 |
73 | #endregion
74 |
75 | #region Public Methods
76 |
77 | public static QueryStringCollection Parse (string query)
78 | {
79 | return Parse (query, Encoding.UTF8);
80 | }
81 |
82 | public static QueryStringCollection Parse (string query, Encoding encoding)
83 | {
84 | if (query == null)
85 | return new QueryStringCollection (1);
86 |
87 | var len = query.Length;
88 | if (len == 0)
89 | return new QueryStringCollection (1);
90 |
91 | if (query == "?")
92 | return new QueryStringCollection (1);
93 |
94 | if (query[0] == '?')
95 | query = query.Substring (1);
96 |
97 | if (encoding == null)
98 | encoding = Encoding.UTF8;
99 |
100 | var ret = new QueryStringCollection ();
101 |
102 | var components = query.Split ('&');
103 | foreach (var component in components) {
104 | len = component.Length;
105 | if (len == 0)
106 | continue;
107 |
108 | if (component == "=")
109 | continue;
110 |
111 | var i = component.IndexOf ('=');
112 | if (i < 0) {
113 | ret.Add (null, urlDecode (component, encoding));
114 | continue;
115 | }
116 |
117 | if (i == 0) {
118 | ret.Add (null, urlDecode (component.Substring (1), encoding));
119 | continue;
120 | }
121 |
122 | var name = urlDecode (component.Substring (0, i), encoding);
123 |
124 | var start = i + 1;
125 | var val = start < len
126 | ? urlDecode (component.Substring (start), encoding)
127 | : String.Empty;
128 |
129 | ret.Add (name, val);
130 | }
131 |
132 | return ret;
133 | }
134 |
135 | public override string ToString ()
136 | {
137 | var buff = new StringBuilder ();
138 |
139 | foreach (var key in AllKeys)
140 | buff.AppendFormat ("{0}={1}&", key, this[key]);
141 |
142 | if (buff.Length > 0)
143 | buff.Length--;
144 |
145 | return buff.ToString ();
146 | }
147 |
148 | #endregion
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 | !src/*/build/
25 |
26 | # Visual Studio 2015 cache/options directory
27 | .vs/
28 | # Visual Studio Code cache/options directory
29 | .vscode/
30 | # Uncomment if you have tasks that create the project's static files in wwwroot
31 | #wwwroot/
32 |
33 | # MSTest test Results
34 | [Tt]est[Rr]esult*/
35 | [Bb]uild[Ll]og.*
36 |
37 | # NUNIT
38 | *.VisualState.xml
39 | TestResult.xml
40 |
41 | # Build Results of an ATL Project
42 | [Dd]ebugPS/
43 | [Rr]eleasePS/
44 | dlldata.c
45 |
46 | # DNX
47 | project.lock.json
48 | artifacts/
49 |
50 | *_i.c
51 | *_p.c
52 | *_i.h
53 | *.ilk
54 | *.meta
55 | *.obj
56 | *.pch
57 | *.pdb
58 | *.pgc
59 | *.pgd
60 | *.rsp
61 | *.sbr
62 | *.tlb
63 | *.tli
64 | *.tlh
65 | *.tmp
66 | *.tmp_proj
67 | *.log
68 | *.vspscc
69 | *.vssscc
70 | .builds
71 | *.pidb
72 | *.svclog
73 | *.scc
74 |
75 | # Chutzpah Test files
76 | _Chutzpah*
77 |
78 | # Visual C++ cache files
79 | ipch/
80 | *.aps
81 | *.ncb
82 | *.opensdf
83 | *.sdf
84 | *.cachefile
85 |
86 | # Visual Studio profiler
87 | *.psess
88 | *.vsp
89 | *.vspx
90 | *.sap
91 |
92 | # TFS 2012 Local Workspace
93 | $tf/
94 |
95 | # Guidance Automation Toolkit
96 | *.gpState
97 |
98 | # ReSharper is a .NET coding add-in
99 | _ReSharper*/
100 | *.[Rr]e[Ss]harper
101 | *.DotSettings.user
102 |
103 | # JustCode is a .NET coding add-in
104 | .JustCode
105 |
106 | # TeamCity is a build add-in
107 | _TeamCity*
108 |
109 | # DotCover is a Code Coverage Tool
110 | *.dotCover
111 |
112 | # NCrunch
113 | _NCrunch_*
114 | .*crunch*.local.xml
115 | nCrunchTemp_*
116 |
117 | # MightyMoose
118 | *.mm.*
119 | AutoTest.Net/
120 |
121 | # Web workbench (sass)
122 | .sass-cache/
123 |
124 | # Installshield output folder
125 | [Ee]xpress/
126 |
127 | # DocProject is a documentation generator add-in
128 | DocProject/buildhelp/
129 | DocProject/Help/*.HxT
130 | DocProject/Help/*.HxC
131 | DocProject/Help/*.hhc
132 | DocProject/Help/*.hhk
133 | DocProject/Help/*.hhp
134 | DocProject/Help/Html2
135 | DocProject/Help/html
136 |
137 | # Click-Once directory
138 | publish/
139 |
140 | # Publish Web Output
141 | *.[Pp]ublish.xml
142 | *.azurePubxml
143 | # TODO: Comment the next line if you want to checkin your web deploy settings
144 | # but database connection strings (with potential passwords) will be unencrypted
145 | #*.pubxml
146 | *.publishproj
147 |
148 | # NuGet Packages
149 | *.nupkg
150 | # The packages folder can be ignored because of Package Restore
151 | **/packages/*
152 | # except build/, which is used as an MSBuild target.
153 | !**/packages/build/
154 | # Uncomment if necessary however generally it will be regenerated when needed
155 | #!**/packages/repositories.config
156 |
157 | # Windows Azure Build Output
158 | csx/
159 | *.build.csdef
160 |
161 | # Windows Store app package directory
162 | AppPackages/
163 |
164 | # Visual Studio cache files
165 | # files ending in .cache can be ignored
166 | *.[Cc]ache
167 | # but keep track of directories ending in .cache
168 | !*.[Cc]ache/
169 |
170 | # Others
171 | ClientBin/
172 | [Ss]tyle[Cc]op.*
173 | ~$*
174 | *~
175 | *.dbmdl
176 | *.dbproj.schemaview
177 | *.pfx
178 | *.publishsettings
179 | node_modules/
180 | orleans.codegen.cs
181 |
182 | # RIA/Silverlight projects
183 | Generated_Code/
184 |
185 | # Backup & report files from converting an old project file
186 | # to a newer Visual Studio version. Backup files are not needed,
187 | # because we have git ;-)
188 | _UpgradeReport_Files/
189 | Backup*/
190 | UpgradeLog*.XML
191 | UpgradeLog*.htm
192 |
193 | # SQL Server files
194 | *.mdf
195 | *.ldf
196 |
197 | # Business Intelligence projects
198 | *.rdl.data
199 | *.bim.layout
200 | *.bim_*.settings
201 |
202 | # Microsoft Fakes
203 | FakesAssemblies/
204 |
205 | # Node.js Tools for Visual Studio
206 | .ntvs_analysis.dat
207 |
208 | # Visual Studio 6 build log
209 | *.plg
210 |
211 | # Visual Studio 6 workspace options file
212 | *.opt
213 |
214 | # Visual Studio LightSwitch build output
215 | **/*.HTMLClient/GeneratedArtifacts
216 | **/*.DesktopClient/GeneratedArtifacts
217 | **/*.DesktopClient/ModelManifest.xml
218 | **/*.Server/GeneratedArtifacts
219 | **/*.Server/ModelManifest.xml
220 | _Pvt_Extensions
221 |
222 | # Project Cherry generated items to ignore...
223 | **/audit.json
224 | **/build/config.json
225 | **/log.txt
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/HttpStreamAsyncResult.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * HttpStreamAsyncResult.cs
4 | *
5 | * This code is derived from HttpStreamAsyncResult.cs (System.Net) of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
11 | * Copyright (c) 2012-2015 sta.blockhead
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy
14 | * of this software and associated documentation files (the "Software"), to deal
15 | * in the Software without restriction, including without limitation the rights
16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | * copies of the Software, and to permit persons to whom the Software is
18 | * furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | * THE SOFTWARE.
30 | */
31 | #endregion
32 |
33 | #region Authors
34 | /*
35 | * Authors:
36 | * - Gonzalo Paniagua Javier
37 | */
38 | #endregion
39 |
40 | using System;
41 | using System.Threading;
42 |
43 | namespace WebSocketSharper.Net
44 | {
45 | internal class HttpStreamAsyncResult : IAsyncResult
46 | {
47 | #region Private Fields
48 |
49 | private byte[] _buffer;
50 | private AsyncCallback _callback;
51 | private bool _completed;
52 | private int _count;
53 | private Exception _exception;
54 | private int _offset;
55 | private object _state;
56 | private object _sync;
57 | private int _syncRead;
58 | private ManualResetEvent _waitHandle;
59 |
60 | #endregion
61 |
62 | #region Internal Constructors
63 |
64 | internal HttpStreamAsyncResult (AsyncCallback callback, object state)
65 | {
66 | _callback = callback;
67 | _state = state;
68 | _sync = new object ();
69 | }
70 |
71 | #endregion
72 |
73 | #region Internal Properties
74 |
75 | internal byte[] Buffer {
76 | get {
77 | return _buffer;
78 | }
79 |
80 | set {
81 | _buffer = value;
82 | }
83 | }
84 |
85 | internal int Count {
86 | get {
87 | return _count;
88 | }
89 |
90 | set {
91 | _count = value;
92 | }
93 | }
94 |
95 | internal Exception Exception {
96 | get {
97 | return _exception;
98 | }
99 | }
100 |
101 | internal bool HasException {
102 | get {
103 | return _exception != null;
104 | }
105 | }
106 |
107 | internal int Offset {
108 | get {
109 | return _offset;
110 | }
111 |
112 | set {
113 | _offset = value;
114 | }
115 | }
116 |
117 | internal int SyncRead {
118 | get {
119 | return _syncRead;
120 | }
121 |
122 | set {
123 | _syncRead = value;
124 | }
125 | }
126 |
127 | #endregion
128 |
129 | #region Public Properties
130 |
131 | public object AsyncState {
132 | get {
133 | return _state;
134 | }
135 | }
136 |
137 | public WaitHandle AsyncWaitHandle {
138 | get {
139 | lock (_sync)
140 | return _waitHandle ?? (_waitHandle = new ManualResetEvent (_completed));
141 | }
142 | }
143 |
144 | public bool CompletedSynchronously {
145 | get {
146 | return _syncRead == _count;
147 | }
148 | }
149 |
150 | public bool IsCompleted {
151 | get {
152 | lock (_sync)
153 | return _completed;
154 | }
155 | }
156 |
157 | #endregion
158 |
159 | #region Internal Methods
160 |
161 | internal void Complete ()
162 | {
163 | lock (_sync) {
164 | if (_completed)
165 | return;
166 |
167 | _completed = true;
168 | if (_waitHandle != null)
169 | _waitHandle.Set ();
170 |
171 | if (_callback != null)
172 | _callback.BeginInvoke (this, ar => _callback.EndInvoke (ar), null);
173 | }
174 | }
175 |
176 | internal void Complete (Exception exception)
177 | {
178 | _exception = exception;
179 | Complete ();
180 | }
181 |
182 | #endregion
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/AuthenticationChallenge.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * AuthenticationChallenge.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2013-2014 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 | using System.Collections.Specialized;
31 | using System.Text;
32 |
33 | namespace WebSocketSharper.Net
34 | {
35 | internal class AuthenticationChallenge : AuthenticationBase
36 | {
37 | #region Private Constructors
38 |
39 | private AuthenticationChallenge (AuthenticationSchemes scheme, NameValueCollection parameters)
40 | : base (scheme, parameters)
41 | {
42 | }
43 |
44 | #endregion
45 |
46 | #region Internal Constructors
47 |
48 | internal AuthenticationChallenge (AuthenticationSchemes scheme, string realm)
49 | : base (scheme, new NameValueCollection ())
50 | {
51 | Parameters["realm"] = realm;
52 | if (scheme == AuthenticationSchemes.Digest) {
53 | Parameters["nonce"] = CreateNonceValue ();
54 | Parameters["algorithm"] = "MD5";
55 | Parameters["qop"] = "auth";
56 | }
57 | }
58 |
59 | #endregion
60 |
61 | #region Public Properties
62 |
63 | public string Domain {
64 | get {
65 | return Parameters["domain"];
66 | }
67 | }
68 |
69 | public string Stale {
70 | get {
71 | return Parameters["stale"];
72 | }
73 | }
74 |
75 | #endregion
76 |
77 | #region Internal Methods
78 |
79 | internal static AuthenticationChallenge CreateBasicChallenge (string realm)
80 | {
81 | return new AuthenticationChallenge (AuthenticationSchemes.Basic, realm);
82 | }
83 |
84 | internal static AuthenticationChallenge CreateDigestChallenge (string realm)
85 | {
86 | return new AuthenticationChallenge (AuthenticationSchemes.Digest, realm);
87 | }
88 |
89 | internal static AuthenticationChallenge Parse (string value)
90 | {
91 | var chal = value.Split (new[] { ' ' }, 2);
92 | if (chal.Length != 2)
93 | return null;
94 |
95 | var schm = chal[0].ToLower ();
96 | return schm == "basic"
97 | ? new AuthenticationChallenge (
98 | AuthenticationSchemes.Basic, ParseParameters (chal[1]))
99 | : schm == "digest"
100 | ? new AuthenticationChallenge (
101 | AuthenticationSchemes.Digest, ParseParameters (chal[1]))
102 | : null;
103 | }
104 |
105 | internal override string ToBasicString ()
106 | {
107 | return String.Format ("Basic realm=\"{0}\"", Parameters["realm"]);
108 | }
109 |
110 | internal override string ToDigestString ()
111 | {
112 | var output = new StringBuilder (128);
113 |
114 | var domain = Parameters["domain"];
115 | if (domain != null)
116 | output.AppendFormat (
117 | "Digest realm=\"{0}\", domain=\"{1}\", nonce=\"{2}\"",
118 | Parameters["realm"],
119 | domain,
120 | Parameters["nonce"]);
121 | else
122 | output.AppendFormat (
123 | "Digest realm=\"{0}\", nonce=\"{1}\"", Parameters["realm"], Parameters["nonce"]);
124 |
125 | var opaque = Parameters["opaque"];
126 | if (opaque != null)
127 | output.AppendFormat (", opaque=\"{0}\"", opaque);
128 |
129 | var stale = Parameters["stale"];
130 | if (stale != null)
131 | output.AppendFormat (", stale={0}", stale);
132 |
133 | var algo = Parameters["algorithm"];
134 | if (algo != null)
135 | output.AppendFormat (", algorithm={0}", algo);
136 |
137 | var qop = Parameters["qop"];
138 | if (qop != null)
139 | output.AppendFormat (", qop=\"{0}\"", qop);
140 |
141 | return output.ToString ();
142 | }
143 |
144 | #endregion
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/CloseStatusCode.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * CloseStatusCode.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2012-2016 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 |
31 | namespace WebSocketSharper
32 | {
33 | ///
34 | /// Indicates the status code for the WebSocket connection close.
35 | ///
36 | ///
37 | ///
38 | /// The values of this enumeration are defined in
39 | ///
40 | /// Section 7.4 of RFC 6455.
41 | ///
42 | ///
43 | /// "Reserved value" cannot be sent as a status code in
44 | /// closing handshake by an endpoint.
45 | ///
46 | ///
47 | public enum CloseStatusCode : ushort
48 | {
49 | ///
50 | /// Equivalent to close status 1000. Indicates normal close.
51 | ///
52 | Normal = 1000,
53 | ///
54 | /// Equivalent to close status 1001. Indicates that an endpoint is
55 | /// going away.
56 | ///
57 | Away = 1001,
58 | ///
59 | /// Equivalent to close status 1002. Indicates that an endpoint is
60 | /// terminating the connection due to a protocol error.
61 | ///
62 | ProtocolError = 1002,
63 | ///
64 | /// Equivalent to close status 1003. Indicates that an endpoint is
65 | /// terminating the connection because it has received a type of
66 | /// data that it cannot accept.
67 | ///
68 | UnsupportedData = 1003,
69 | ///
70 | /// Equivalent to close status 1004. Still undefined. A Reserved value.
71 | ///
72 | Undefined = 1004,
73 | ///
74 | /// Equivalent to close status 1005. Indicates that no status code was
75 | /// actually present. A Reserved value.
76 | ///
77 | NoStatus = 1005,
78 | ///
79 | /// Equivalent to close status 1006. Indicates that the connection was
80 | /// closed abnormally. A Reserved value.
81 | ///
82 | Abnormal = 1006,
83 | ///
84 | /// Equivalent to close status 1007. Indicates that an endpoint is
85 | /// terminating the connection because it has received a message that
86 | /// contains data that is not consistent with the type of the message.
87 | ///
88 | InvalidData = 1007,
89 | ///
90 | /// Equivalent to close status 1008. Indicates that an endpoint is
91 | /// terminating the connection because it has received a message that
92 | /// violates its policy.
93 | ///
94 | PolicyViolation = 1008,
95 | ///
96 | /// Equivalent to close status 1009. Indicates that an endpoint is
97 | /// terminating the connection because it has received a message that
98 | /// is too big to process.
99 | ///
100 | TooBig = 1009,
101 | ///
102 | /// Equivalent to close status 1010. Indicates that a client is
103 | /// terminating the connection because it has expected the server to
104 | /// negotiate one or more extension, but the server did not return
105 | /// them in the handshake response.
106 | ///
107 | MandatoryExtension = 1010,
108 | ///
109 | /// Equivalent to close status 1011. Indicates that a server is
110 | /// terminating the connection because it has encountered an unexpected
111 | /// condition that prevented it from fulfilling the request.
112 | ///
113 | ServerError = 1011,
114 | ///
115 | /// Equivalent to close status 1015. Indicates that the connection was
116 | /// closed due to a failure to perform a TLS handshake. A Reserved value.
117 | ///
118 | TlsHandshakeFailure = 1015
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/src/Test/WebSocketSharperTests/WebSocketTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using TestSupport;
4 | using WebSocketSharper;
5 | using WebSocketSharper.Server;
6 | using Xunit;
7 | using Xunit.Abstractions;
8 | using Microsoft.Extensions.Logging;
9 |
10 | namespace WebSocketSharpererTests
11 | {
12 | public class WebSocketTests : BaseTest
13 | {
14 | public WebSocketTests(ITestOutputHelper outputHelper)
15 | : base(outputHelper)
16 | {
17 |
18 | }
19 |
20 | public enum CheckPoint
21 | {
22 | ClientReceived,
23 | ClientConnectionClosed
24 | }
25 |
26 | [Fact]
27 | public void TestConnect()
28 | {
29 | var gate = new TestGate();
30 | var wss = new WebSocketServer(LOG, 8844);
31 | wss.AddWebSocketService("/test");
32 | wss.Start();
33 |
34 |
35 | using (var wsc = new WebSocket(LOG, "ws://localhost:8844/test", true))
36 | {
37 | wsc.OnMessage += (sender, e) =>
38 | {
39 | gate.Set(CheckPoint.ClientReceived);
40 | };
41 |
42 | wsc.Connect();
43 |
44 | wsc.Send("BALUS");
45 |
46 | gate.AssertWaitFor(CheckPoint.ClientReceived, 5000);
47 | }
48 |
49 |
50 | wss.Stop();
51 | }
52 |
53 |
54 | [Fact]
55 | public void TestWithObservableMessages()
56 | {
57 | var gate = new TestGate();
58 | var wss = new WebSocketServer(LOG, 8844);
59 | wss.AddWebSocketService("/test");
60 | wss.Start();
61 |
62 |
63 | using (var wsc = new WebSocket(LOG, "ws://localhost:8844/test", true))
64 | {
65 | wsc.MessageReceived.Subscribe((m) =>
66 | {
67 | gate.Set(CheckPoint.ClientReceived);
68 | });
69 |
70 | wsc.Connect();
71 |
72 | wsc.Send("Check Observable route works!");
73 |
74 | gate.AssertWaitFor(CheckPoint.ClientReceived, 5000);
75 | }
76 |
77 |
78 | wss.Stop();
79 | }
80 |
81 | [Fact]
82 | public void TestConnectClientFirst()
83 | {
84 | var gate = new TestGate();
85 |
86 |
87 | // Create client
88 | int clientMessageCount = 0;
89 | int clientCloseCount = 0;
90 | int clientRetryCount = 0;
91 | var wsc = new WebSocket(LOG, "ws://localhost:8844/test", true);
92 | wsc.ReconnectDelay = TimeSpan.FromSeconds(3);
93 | wsc.OnMessage += (sender, e) =>
94 | {
95 | clientMessageCount++;
96 | gate.Set(CheckPoint.ClientReceived);
97 | };
98 |
99 | wsc.OnError += (sender, e) =>
100 | {
101 | };
102 |
103 | wsc.OnOpen += (sender, e) =>
104 | {
105 |
106 | };
107 |
108 | wsc.OnClose += (sender, e) =>
109 | {
110 | var code = (CloseStatusCode)e.Code;
111 |
112 | if (
113 | (code == CloseStatusCode.Normal) ||
114 | (code == CloseStatusCode.NoStatus)
115 | )
116 | {
117 | clientCloseCount++;
118 | gate.Set(CheckPoint.ClientConnectionClosed);
119 | }
120 | else
121 | {
122 | clientRetryCount++;
123 | }
124 | };
125 |
126 | wsc.ConnectTaskAsync();
127 |
128 | Thread.Sleep(3000);
129 |
130 | // Create server
131 | var wss = new WebSocketServer(LOG, 8844);
132 | wss.AddWebSocketService("/test");
133 | wss.Start();
134 |
135 | Thread.Sleep(6000);
136 |
137 | wsc.Send("BALUS");
138 |
139 | gate.AssertWaitFor(CheckPoint.ClientReceived, 5000);
140 |
141 | wss.Stop();
142 | Thread.Sleep(3000);
143 |
144 | // Create a second server
145 | var wss2 = new WebSocketServer(LOG, 8844);
146 | wss2.AddWebSocketService("/test");
147 | wss2.Start();
148 |
149 | Thread.Sleep(6000);
150 |
151 | wsc.Send("New server, old client");
152 |
153 | gate.AssertWaitFor(CheckPoint.ClientReceived, 5000);
154 |
155 | Assert.Equal(2, clientMessageCount);
156 |
157 | wsc.CloseTaskAsync(CloseStatusCode.Normal, "Finished Tests");
158 |
159 | gate.AssertWaitFor(CheckPoint.ClientConnectionClosed, 50000);
160 | Assert.Equal(1, clientCloseCount);
161 |
162 | // Now close the second sever
163 | wss2.Stop();
164 | }
165 | }
166 |
167 | public class WebSocketTestBehaviour : WebSocketBehavior
168 | {
169 | protected override void OnMessage(MessageEventArgs e)
170 | {
171 | var msg = e.Data == "BALUS"
172 | ? "I've been balused already..."
173 | : "I'm not available now.";
174 |
175 | Send(msg);
176 | }
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/HttpListenerAsyncResult.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * HttpListenerAsyncResult.cs
4 | *
5 | * This code is derived from ListenerAsyncResult.cs (System.Net) of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2005 Ximian, Inc. (http://www.ximian.com)
11 | * Copyright (c) 2012-2016 sta.blockhead
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy
14 | * of this software and associated documentation files (the "Software"), to deal
15 | * in the Software without restriction, including without limitation the rights
16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | * copies of the Software, and to permit persons to whom the Software is
18 | * furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | * THE SOFTWARE.
30 | */
31 | #endregion
32 |
33 | #region Authors
34 | /*
35 | * Authors:
36 | * - Gonzalo Paniagua Javier
37 | */
38 | #endregion
39 |
40 | #region Contributors
41 | /*
42 | * Contributors:
43 | * - Nicholas Devenish
44 | */
45 | #endregion
46 |
47 | using System;
48 | using System.Threading;
49 |
50 | namespace WebSocketSharper.Net
51 | {
52 | internal class HttpListenerAsyncResult : IAsyncResult
53 | {
54 | #region Private Fields
55 |
56 | private AsyncCallback _callback;
57 | private bool _completed;
58 | private HttpListenerContext _context;
59 | private bool _endCalled;
60 | private Exception _exception;
61 | private bool _inGet;
62 | private object _state;
63 | private object _sync;
64 | private bool _syncCompleted;
65 | private ManualResetEvent _waitHandle;
66 |
67 | #endregion
68 |
69 | #region Internal Constructors
70 |
71 | internal HttpListenerAsyncResult (AsyncCallback callback, object state)
72 | {
73 | _callback = callback;
74 | _state = state;
75 | _sync = new object ();
76 | }
77 |
78 | #endregion
79 |
80 | #region Internal Properties
81 |
82 | internal bool EndCalled {
83 | get {
84 | return _endCalled;
85 | }
86 |
87 | set {
88 | _endCalled = value;
89 | }
90 | }
91 |
92 | internal bool InGet {
93 | get {
94 | return _inGet;
95 | }
96 |
97 | set {
98 | _inGet = value;
99 | }
100 | }
101 |
102 | #endregion
103 |
104 | #region Public Properties
105 |
106 | public object AsyncState {
107 | get {
108 | return _state;
109 | }
110 | }
111 |
112 | public WaitHandle AsyncWaitHandle {
113 | get {
114 | lock (_sync)
115 | return _waitHandle ?? (_waitHandle = new ManualResetEvent (_completed));
116 | }
117 | }
118 |
119 | public bool CompletedSynchronously {
120 | get {
121 | return _syncCompleted;
122 | }
123 | }
124 |
125 | public bool IsCompleted {
126 | get {
127 | lock (_sync)
128 | return _completed;
129 | }
130 | }
131 |
132 | #endregion
133 |
134 | #region Private Methods
135 |
136 | private static void complete (HttpListenerAsyncResult asyncResult)
137 | {
138 | lock (asyncResult._sync) {
139 | asyncResult._completed = true;
140 |
141 | var waitHandle = asyncResult._waitHandle;
142 | if (waitHandle != null)
143 | waitHandle.Set ();
144 | }
145 |
146 | var callback = asyncResult._callback;
147 | if (callback == null)
148 | return;
149 |
150 | ThreadPool.QueueUserWorkItem (
151 | state => {
152 | try {
153 | callback (asyncResult);
154 | }
155 | catch {
156 | }
157 | },
158 | null
159 | );
160 | }
161 |
162 | #endregion
163 |
164 | #region Internal Methods
165 |
166 | internal void Complete (Exception exception)
167 | {
168 | _exception = _inGet && (exception is ObjectDisposedException)
169 | ? new HttpListenerException (995, "The listener is closed.")
170 | : exception;
171 |
172 | complete (this);
173 | }
174 |
175 | internal void Complete (HttpListenerContext context)
176 | {
177 | Complete (context, false);
178 | }
179 |
180 | internal void Complete (HttpListenerContext context, bool syncCompleted)
181 | {
182 | _context = context;
183 | _syncCompleted = syncCompleted;
184 |
185 | complete (this);
186 | }
187 |
188 | internal HttpListenerContext GetContext ()
189 | {
190 | if (_exception != null)
191 | throw _exception;
192 |
193 | return _context;
194 | }
195 |
196 | #endregion
197 | }
198 | }
199 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/MessageEventArgs.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * MessageEventArgs.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2012-2016 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 |
31 | namespace WebSocketSharper
32 | {
33 | ///
34 | /// Represents the event data for the event.
35 | ///
36 | ///
37 | ///
38 | /// That event occurs when the receives
39 | /// a message or a ping if the
40 | /// property is set to true.
41 | ///
42 | ///
43 | /// If you would like to get the message data, you should access
44 | /// the or property.
45 | ///
46 | ///
47 | public class MessageEventArgs : EventArgs
48 | {
49 | #region Private Fields
50 |
51 | private string _data;
52 | private bool _dataSet;
53 | private Opcode _opcode;
54 | private byte[] _rawData;
55 |
56 | #endregion
57 |
58 | #region Internal Constructors
59 |
60 | internal MessageEventArgs (WebSocketFrame frame)
61 | {
62 | _opcode = frame.Opcode;
63 | _rawData = frame.PayloadData.ApplicationData;
64 | }
65 |
66 | internal MessageEventArgs (Opcode opcode, byte[] rawData)
67 | {
68 | if ((ulong) rawData.LongLength > PayloadData.MaxLength)
69 | throw new WebSocketException (CloseStatusCode.TooBig);
70 |
71 | _opcode = opcode;
72 | _rawData = rawData;
73 | }
74 |
75 | #endregion
76 |
77 | #region Internal Properties
78 |
79 | ///
80 | /// Gets the opcode for the message.
81 | ///
82 | ///
83 | /// , ,
84 | /// or .
85 | ///
86 | internal Opcode Opcode {
87 | get {
88 | return _opcode;
89 | }
90 | }
91 |
92 | #endregion
93 |
94 | #region Public Properties
95 |
96 | ///
97 | /// Gets the message data as a .
98 | ///
99 | ///
100 | /// A that represents the message data if its type is
101 | /// text or ping and if decoding it to a string has successfully done;
102 | /// otherwise, .
103 | ///
104 | public string Data {
105 | get {
106 | setData ();
107 | return _data;
108 | }
109 | }
110 |
111 | ///
112 | /// Gets a value indicating whether the message type is binary.
113 | ///
114 | ///
115 | /// true if the message type is binary; otherwise, false.
116 | ///
117 | public bool IsBinary {
118 | get {
119 | return _opcode == Opcode.Binary;
120 | }
121 | }
122 |
123 | ///
124 | /// Gets a value indicating whether the message type is ping.
125 | ///
126 | ///
127 | /// true if the message type is ping; otherwise, false.
128 | ///
129 | public bool IsPing {
130 | get {
131 | return _opcode == Opcode.Ping;
132 | }
133 | }
134 |
135 | ///
136 | /// Gets a value indicating whether the message type is text.
137 | ///
138 | ///
139 | /// true if the message type is text; otherwise, false.
140 | ///
141 | public bool IsText {
142 | get {
143 | return _opcode == Opcode.Text;
144 | }
145 | }
146 |
147 | ///
148 | /// Gets the message data as an array of .
149 | ///
150 | ///
151 | /// An array of that represents the message data.
152 | ///
153 | public byte[] RawData {
154 | get {
155 | setData ();
156 | return _rawData;
157 | }
158 | }
159 |
160 | #endregion
161 |
162 | #region Private Methods
163 |
164 | private void setData ()
165 | {
166 | if (_dataSet)
167 | return;
168 |
169 | if (_opcode == Opcode.Binary) {
170 | _dataSet = true;
171 | return;
172 | }
173 |
174 | string data;
175 | if (_rawData.TryGetUTF8DecodedString (out data))
176 | _data = data;
177 |
178 | _dataSet = true;
179 | }
180 |
181 | #endregion
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/PayloadData.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * PayloadData.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2012-2019 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 | using System.Collections;
31 | using System.Collections.Generic;
32 |
33 | namespace WebSocketSharper
34 | {
35 | internal class PayloadData : IEnumerable
36 | {
37 | #region Private Fields
38 |
39 | private byte[] _data;
40 | private long _extDataLength;
41 | private long _length;
42 |
43 | #endregion
44 |
45 | #region Public Fields
46 |
47 | ///
48 | /// Represents the empty payload data.
49 | ///
50 | public static readonly PayloadData Empty;
51 |
52 | ///
53 | /// Represents the allowable max length of payload data.
54 | ///
55 | ///
56 | ///
57 | /// A will occur when the length of
58 | /// incoming payload data is greater than the value of this field.
59 | ///
60 | ///
61 | /// If you would like to change the value of this field, it must be
62 | /// a number between and
63 | /// inclusive.
64 | ///
65 | ///
66 | public static readonly ulong MaxLength;
67 |
68 | #endregion
69 |
70 | #region Static Constructor
71 |
72 | static PayloadData ()
73 | {
74 | Empty = new PayloadData (WebSocket.EmptyBytes, 0);
75 | MaxLength = Int64.MaxValue;
76 | }
77 |
78 | #endregion
79 |
80 | #region Internal Constructors
81 |
82 | internal PayloadData (byte[] data)
83 | : this (data, data.LongLength)
84 | {
85 | }
86 |
87 | internal PayloadData (byte[] data, long length)
88 | {
89 | _data = data;
90 | _length = length;
91 | }
92 |
93 | internal PayloadData (ushort code, string reason)
94 | {
95 | _data = code.Append (reason);
96 | _length = _data.LongLength;
97 | }
98 |
99 | #endregion
100 |
101 | #region Internal Properties
102 |
103 | internal ushort Code {
104 | get {
105 | return _length >= 2
106 | ? _data.SubArray (0, 2).ToUInt16 (ByteOrder.Big)
107 | : (ushort) 1005;
108 | }
109 | }
110 |
111 | internal long ExtensionDataLength {
112 | get {
113 | return _extDataLength;
114 | }
115 |
116 | set {
117 | _extDataLength = value;
118 | }
119 | }
120 |
121 | internal bool HasReservedCode {
122 | get {
123 | return _length >= 2 && Code.IsReserved ();
124 | }
125 | }
126 |
127 | internal string Reason {
128 | get {
129 | if (_length <= 2)
130 | return String.Empty;
131 |
132 | var raw = _data.SubArray (2, _length - 2);
133 |
134 | string reason;
135 | return raw.TryGetUTF8DecodedString (out reason)
136 | ? reason
137 | : String.Empty;
138 | }
139 | }
140 |
141 | #endregion
142 |
143 | #region Public Properties
144 |
145 | public byte[] ApplicationData {
146 | get {
147 | return _extDataLength > 0
148 | ? _data.SubArray (_extDataLength, _length - _extDataLength)
149 | : _data;
150 | }
151 | }
152 |
153 | public byte[] ExtensionData {
154 | get {
155 | return _extDataLength > 0
156 | ? _data.SubArray (0, _extDataLength)
157 | : WebSocket.EmptyBytes;
158 | }
159 | }
160 |
161 | public ulong Length {
162 | get {
163 | return (ulong) _length;
164 | }
165 | }
166 |
167 | #endregion
168 |
169 | #region Internal Methods
170 |
171 | internal void Mask (byte[] key)
172 | {
173 | for (long i = 0; i < _length; i++)
174 | _data[i] = (byte) (_data[i] ^ key[i % 4]);
175 | }
176 |
177 | #endregion
178 |
179 | #region Public Methods
180 |
181 | public IEnumerator GetEnumerator ()
182 | {
183 | foreach (var b in _data)
184 | yield return b;
185 | }
186 |
187 | public byte[] ToArray ()
188 | {
189 | return _data;
190 | }
191 |
192 | public override string ToString ()
193 | {
194 | return BitConverter.ToString (_data);
195 | }
196 |
197 | #endregion
198 |
199 | #region Explicit Interface Implementations
200 |
201 | IEnumerator IEnumerable.GetEnumerator ()
202 | {
203 | return GetEnumerator ();
204 | }
205 |
206 | #endregion
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/CookieException.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * CookieException.cs
4 | *
5 | * This code is derived from CookieException.cs (System.Net) of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2012-2019 sta.blockhead
11 | *
12 | * Permission is hereby granted, free of charge, to any person obtaining a copy
13 | * of this software and associated documentation files (the "Software"), to deal
14 | * in the Software without restriction, including without limitation the rights
15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 | * copies of the Software, and to permit persons to whom the Software is
17 | * furnished to do so, subject to the following conditions:
18 | *
19 | * The above copyright notice and this permission notice shall be included in
20 | * all copies or substantial portions of the Software.
21 | *
22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 | * THE SOFTWARE.
29 | */
30 | #endregion
31 |
32 | #region Authors
33 | /*
34 | * Authors:
35 | * - Lawrence Pit
36 | */
37 | #endregion
38 |
39 | using System;
40 | using System.Runtime.Serialization;
41 | using System.Security.Permissions;
42 |
43 | namespace WebSocketSharper.Net
44 | {
45 | ///
46 | /// The exception that is thrown when a gets an error.
47 | ///
48 | [Serializable]
49 | public class CookieException : FormatException, ISerializable
50 | {
51 | #region Internal Constructors
52 |
53 | internal CookieException (string message)
54 | : base (message)
55 | {
56 | }
57 |
58 | internal CookieException (string message, Exception innerException)
59 | : base (message, innerException)
60 | {
61 | }
62 |
63 | #endregion
64 |
65 | #region Protected Constructors
66 |
67 | ///
68 | /// Initializes a new instance of the class
69 | /// with the serialized data.
70 | ///
71 | ///
72 | /// A that holds the serialized object data.
73 | ///
74 | ///
75 | /// A that specifies the source for
76 | /// the deserialization.
77 | ///
78 | ///
79 | /// is .
80 | ///
81 | protected CookieException (
82 | SerializationInfo serializationInfo, StreamingContext streamingContext
83 | )
84 | : base (serializationInfo, streamingContext)
85 | {
86 | }
87 |
88 | #endregion
89 |
90 | #region Public Constructors
91 |
92 | ///
93 | /// Initializes a new instance of the class.
94 | ///
95 | public CookieException ()
96 | : base ()
97 | {
98 | }
99 |
100 | #endregion
101 |
102 | #region Public Methods
103 |
104 | ///
105 | /// Populates the specified instance with
106 | /// the data needed to serialize the current instance.
107 | ///
108 | ///
109 | /// A that holds the serialized object data.
110 | ///
111 | ///
112 | /// A that specifies the destination for
113 | /// the serialization.
114 | ///
115 | ///
116 | /// is .
117 | ///
118 | [
119 | SecurityPermission (
120 | SecurityAction.LinkDemand,
121 | Flags = SecurityPermissionFlag.SerializationFormatter
122 | )
123 | ]
124 | public override void GetObjectData (
125 | SerializationInfo serializationInfo, StreamingContext streamingContext
126 | )
127 | {
128 | base.GetObjectData (serializationInfo, streamingContext);
129 | }
130 |
131 | #endregion
132 |
133 | #region Explicit Interface Implementation
134 |
135 | ///
136 | /// Populates the specified instance with
137 | /// the data needed to serialize the current instance.
138 | ///
139 | ///
140 | /// A that holds the serialized object data.
141 | ///
142 | ///
143 | /// A that specifies the destination for
144 | /// the serialization.
145 | ///
146 | ///
147 | /// is .
148 | ///
149 | [
150 | SecurityPermission (
151 | SecurityAction.LinkDemand,
152 | Flags = SecurityPermissionFlag.SerializationFormatter,
153 | SerializationFormatter = true
154 | )
155 | ]
156 | void ISerializable.GetObjectData (
157 | SerializationInfo serializationInfo, StreamingContext streamingContext
158 | )
159 | {
160 | base.GetObjectData (serializationInfo, streamingContext);
161 | }
162 |
163 | #endregion
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/HttpDigestIdentity.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * HttpDigestIdentity.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2014-2017 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 | using System.Collections.Specialized;
31 | using System.Security.Principal;
32 |
33 | namespace WebSocketSharper.Net
34 | {
35 | ///
36 | /// Holds the username and other parameters from
37 | /// an HTTP Digest authentication attempt.
38 | ///
39 | public class HttpDigestIdentity : GenericIdentity
40 | {
41 | #region Private Fields
42 |
43 | private NameValueCollection _parameters;
44 |
45 | #endregion
46 |
47 | #region Internal Constructors
48 |
49 | internal HttpDigestIdentity (NameValueCollection parameters)
50 | : base (parameters["username"], "Digest")
51 | {
52 | _parameters = parameters;
53 | }
54 |
55 | #endregion
56 |
57 | #region Public Properties
58 |
59 | ///
60 | /// Gets the algorithm parameter from a digest authentication attempt.
61 | ///
62 | ///
63 | /// A that represents the algorithm parameter.
64 | ///
65 | public string Algorithm {
66 | get {
67 | return _parameters["algorithm"];
68 | }
69 | }
70 |
71 | ///
72 | /// Gets the cnonce parameter from a digest authentication attempt.
73 | ///
74 | ///
75 | /// A that represents the cnonce parameter.
76 | ///
77 | public string Cnonce {
78 | get {
79 | return _parameters["cnonce"];
80 | }
81 | }
82 |
83 | ///
84 | /// Gets the nc parameter from a digest authentication attempt.
85 | ///
86 | ///
87 | /// A that represents the nc parameter.
88 | ///
89 | public string Nc {
90 | get {
91 | return _parameters["nc"];
92 | }
93 | }
94 |
95 | ///
96 | /// Gets the nonce parameter from a digest authentication attempt.
97 | ///
98 | ///
99 | /// A that represents the nonce parameter.
100 | ///
101 | public string Nonce {
102 | get {
103 | return _parameters["nonce"];
104 | }
105 | }
106 |
107 | ///
108 | /// Gets the opaque parameter from a digest authentication attempt.
109 | ///
110 | ///
111 | /// A that represents the opaque parameter.
112 | ///
113 | public string Opaque {
114 | get {
115 | return _parameters["opaque"];
116 | }
117 | }
118 |
119 | ///
120 | /// Gets the qop parameter from a digest authentication attempt.
121 | ///
122 | ///
123 | /// A that represents the qop parameter.
124 | ///
125 | public string Qop {
126 | get {
127 | return _parameters["qop"];
128 | }
129 | }
130 |
131 | ///
132 | /// Gets the realm parameter from a digest authentication attempt.
133 | ///
134 | ///
135 | /// A that represents the realm parameter.
136 | ///
137 | public string Realm {
138 | get {
139 | return _parameters["realm"];
140 | }
141 | }
142 |
143 | ///
144 | /// Gets the response parameter from a digest authentication attempt.
145 | ///
146 | ///
147 | /// A that represents the response parameter.
148 | ///
149 | public string Response {
150 | get {
151 | return _parameters["response"];
152 | }
153 | }
154 |
155 | ///
156 | /// Gets the uri parameter from a digest authentication attempt.
157 | ///
158 | ///
159 | /// A that represents the uri parameter.
160 | ///
161 | public string Uri {
162 | get {
163 | return _parameters["uri"];
164 | }
165 | }
166 |
167 | #endregion
168 |
169 | #region Internal Methods
170 |
171 | internal bool IsValid (
172 | string password, string realm, string method, string entity
173 | )
174 | {
175 | var copied = new NameValueCollection (_parameters);
176 | copied["password"] = password;
177 | copied["realm"] = realm;
178 | copied["method"] = method;
179 | copied["entity"] = entity;
180 |
181 | var expected = AuthenticationResponse.CreateRequestDigest (copied);
182 | return _parameters["response"] == expected;
183 | }
184 |
185 | #endregion
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/HttpResponseHeader.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * HttpResponseHeader.cs
4 | *
5 | * This code is derived from System.Net.HttpResponseHeader.cs of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
11 | * Copyright (c) 2014 sta.blockhead
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy
14 | * of this software and associated documentation files (the "Software"), to deal
15 | * in the Software without restriction, including without limitation the rights
16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | * copies of the Software, and to permit persons to whom the Software is
18 | * furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | * THE SOFTWARE.
30 | */
31 | #endregion
32 |
33 | #region Authors
34 | /*
35 | * Authors:
36 | * - Gonzalo Paniagua Javier
37 | */
38 | #endregion
39 |
40 | namespace WebSocketSharper.Net
41 | {
42 | ///
43 | /// Contains the HTTP headers that can be specified in a server response.
44 | ///
45 | ///
46 | /// The HttpResponseHeader enumeration contains the HTTP response headers defined in
47 | /// RFC 2616 for the HTTP/1.1 and
48 | /// RFC 6455 for the WebSocket.
49 | ///
50 | public enum HttpResponseHeader
51 | {
52 | ///
53 | /// Indicates the Cache-Control header.
54 | ///
55 | CacheControl,
56 | ///
57 | /// Indicates the Connection header.
58 | ///
59 | Connection,
60 | ///
61 | /// Indicates the Date header.
62 | ///
63 | Date,
64 | ///
65 | /// Indicates the Keep-Alive header.
66 | ///
67 | KeepAlive,
68 | ///
69 | /// Indicates the Pragma header.
70 | ///
71 | Pragma,
72 | ///
73 | /// Indicates the Trailer header.
74 | ///
75 | Trailer,
76 | ///
77 | /// Indicates the Transfer-Encoding header.
78 | ///
79 | TransferEncoding,
80 | ///
81 | /// Indicates the Upgrade header.
82 | ///
83 | Upgrade,
84 | ///
85 | /// Indicates the Via header.
86 | ///
87 | Via,
88 | ///
89 | /// Indicates the Warning header.
90 | ///
91 | Warning,
92 | ///
93 | /// Indicates the Allow header.
94 | ///
95 | Allow,
96 | ///
97 | /// Indicates the Content-Length header.
98 | ///
99 | ContentLength,
100 | ///
101 | /// Indicates the Content-Type header.
102 | ///
103 | ContentType,
104 | ///
105 | /// Indicates the Content-Encoding header.
106 | ///
107 | ContentEncoding,
108 | ///
109 | /// Indicates the Content-Language header.
110 | ///
111 | ContentLanguage,
112 | ///
113 | /// Indicates the Content-Location header.
114 | ///
115 | ContentLocation,
116 | ///
117 | /// Indicates the Content-MD5 header.
118 | ///
119 | ContentMd5,
120 | ///
121 | /// Indicates the Content-Range header.
122 | ///
123 | ContentRange,
124 | ///
125 | /// Indicates the Expires header.
126 | ///
127 | Expires,
128 | ///
129 | /// Indicates the Last-Modified header.
130 | ///
131 | LastModified,
132 | ///
133 | /// Indicates the Accept-Ranges header.
134 | ///
135 | AcceptRanges,
136 | ///
137 | /// Indicates the Age header.
138 | ///
139 | Age,
140 | ///
141 | /// Indicates the ETag header.
142 | ///
143 | ETag,
144 | ///
145 | /// Indicates the Location header.
146 | ///
147 | Location,
148 | ///
149 | /// Indicates the Proxy-Authenticate header.
150 | ///
151 | ProxyAuthenticate,
152 | ///
153 | /// Indicates the Retry-After header.
154 | ///
155 | RetryAfter,
156 | ///
157 | /// Indicates the Server header.
158 | ///
159 | Server,
160 | ///
161 | /// Indicates the Set-Cookie header.
162 | ///
163 | SetCookie,
164 | ///
165 | /// Indicates the Vary header.
166 | ///
167 | Vary,
168 | ///
169 | /// Indicates the WWW-Authenticate header.
170 | ///
171 | WwwAuthenticate,
172 | ///
173 | /// Indicates the Sec-WebSocket-Extensions header.
174 | ///
175 | SecWebSocketExtensions,
176 | ///
177 | /// Indicates the Sec-WebSocket-Accept header.
178 | ///
179 | SecWebSocketAccept,
180 | ///
181 | /// Indicates the Sec-WebSocket-Protocol header.
182 | ///
183 | SecWebSocketProtocol,
184 | ///
185 | /// Indicates the Sec-WebSocket-Version header.
186 | ///
187 | SecWebSocketVersion
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/HttpResponse.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * HttpResponse.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2012-2014 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 | using System.Collections.Specialized;
31 | using System.IO;
32 | using System.Text;
33 | using WebSocketSharper.Net;
34 |
35 | namespace WebSocketSharper
36 | {
37 | internal class HttpResponse : HttpBase
38 | {
39 | #region Private Fields
40 |
41 | private string _code;
42 | private string _reason;
43 |
44 | #endregion
45 |
46 | #region Private Constructors
47 |
48 | private HttpResponse (string code, string reason, Version version, NameValueCollection headers)
49 | : base (version, headers)
50 | {
51 | _code = code;
52 | _reason = reason;
53 | }
54 |
55 | #endregion
56 |
57 | #region Internal Constructors
58 |
59 | internal HttpResponse (HttpStatusCode code)
60 | : this (code, code.GetDescription ())
61 | {
62 | }
63 |
64 | internal HttpResponse (HttpStatusCode code, string reason)
65 | : this (((int) code).ToString (), reason, HttpVersion.Version11, new NameValueCollection ())
66 | {
67 | Headers["Server"] = "websocket-sharp/1.0";
68 | }
69 |
70 | #endregion
71 |
72 | #region Public Properties
73 |
74 | public CookieCollection Cookies {
75 | get {
76 | return Headers.GetCookies (true);
77 | }
78 | }
79 |
80 | public bool HasConnectionClose {
81 | get {
82 | var comparison = StringComparison.OrdinalIgnoreCase;
83 | return Headers.Contains ("Connection", "close", comparison);
84 | }
85 | }
86 |
87 | public bool IsProxyAuthenticationRequired {
88 | get {
89 | return _code == "407";
90 | }
91 | }
92 |
93 | public bool IsRedirect {
94 | get {
95 | return _code == "301" || _code == "302";
96 | }
97 | }
98 |
99 | public bool IsUnauthorized {
100 | get {
101 | return _code == "401";
102 | }
103 | }
104 |
105 | public bool IsWebSocketResponse {
106 | get {
107 | return ProtocolVersion > HttpVersion.Version10
108 | && _code == "101"
109 | && Headers.Upgrades ("websocket");
110 | }
111 | }
112 |
113 | public string Reason {
114 | get {
115 | return _reason;
116 | }
117 | }
118 |
119 | public string StatusCode {
120 | get {
121 | return _code;
122 | }
123 | }
124 |
125 | #endregion
126 |
127 | #region Internal Methods
128 |
129 | internal static HttpResponse CreateCloseResponse (HttpStatusCode code)
130 | {
131 | var res = new HttpResponse (code);
132 | res.Headers["Connection"] = "close";
133 |
134 | return res;
135 | }
136 |
137 | internal static HttpResponse CreateUnauthorizedResponse (string challenge)
138 | {
139 | var res = new HttpResponse (HttpStatusCode.Unauthorized);
140 | res.Headers["WWW-Authenticate"] = challenge;
141 |
142 | return res;
143 | }
144 |
145 | internal static HttpResponse CreateWebSocketResponse ()
146 | {
147 | var res = new HttpResponse (HttpStatusCode.SwitchingProtocols);
148 |
149 | var headers = res.Headers;
150 | headers["Upgrade"] = "websocket";
151 | headers["Connection"] = "Upgrade";
152 |
153 | return res;
154 | }
155 |
156 | internal static HttpResponse Parse (string[] headerParts)
157 | {
158 | var statusLine = headerParts[0].Split (new[] { ' ' }, 3);
159 | if (statusLine.Length != 3)
160 | throw new ArgumentException ("Invalid status line: " + headerParts[0]);
161 |
162 | var headers = new WebHeaderCollection ();
163 | for (int i = 1; i < headerParts.Length; i++)
164 | headers.InternalSet (headerParts[i], true);
165 |
166 | return new HttpResponse (
167 | statusLine[1], statusLine[2], new Version (statusLine[0].Substring (5)), headers);
168 | }
169 |
170 | internal static HttpResponse Read (Stream stream, int millisecondsTimeout)
171 | {
172 | return Read (stream, Parse, millisecondsTimeout);
173 | }
174 |
175 | #endregion
176 |
177 | #region Public Methods
178 |
179 | public void SetCookies (CookieCollection cookies)
180 | {
181 | if (cookies == null || cookies.Count == 0)
182 | return;
183 |
184 | var headers = Headers;
185 | foreach (var cookie in cookies.Sorted)
186 | headers.Add ("Set-Cookie", cookie.ToResponseString ());
187 | }
188 |
189 | public override string ToString ()
190 | {
191 | var output = new StringBuilder (64);
192 | output.AppendFormat ("HTTP/{0} {1} {2}{3}", ProtocolVersion, _code, _reason, CrLf);
193 |
194 | var headers = Headers;
195 | foreach (var key in headers.AllKeys)
196 | output.AppendFormat ("{0}: {1}{2}", key, headers[key], CrLf);
197 |
198 | output.Append (CrLf);
199 |
200 | var entity = EntityBody;
201 | if (entity.Length > 0)
202 | output.Append (entity);
203 |
204 | return output.ToString ();
205 | }
206 |
207 | #endregion
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/HttpBase.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * HttpBase.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2012-2014 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 | using System.Collections.Generic;
31 | using System.Collections.Specialized;
32 | using System.IO;
33 | using System.Text;
34 | using System.Threading;
35 | using WebSocketSharper.Net;
36 |
37 | namespace WebSocketSharper
38 | {
39 | internal abstract class HttpBase
40 | {
41 | #region Private Fields
42 |
43 | private NameValueCollection _headers;
44 | private const int _headersMaxLength = 8192;
45 | private Version _version;
46 |
47 | #endregion
48 |
49 | #region Internal Fields
50 |
51 | internal byte[] EntityBodyData;
52 |
53 | #endregion
54 |
55 | #region Protected Fields
56 |
57 | protected const string CrLf = "\r\n";
58 |
59 | #endregion
60 |
61 | #region Protected Constructors
62 |
63 | protected HttpBase (Version version, NameValueCollection headers)
64 | {
65 | _version = version;
66 | _headers = headers;
67 | }
68 |
69 | #endregion
70 |
71 | #region Public Properties
72 |
73 | public string EntityBody {
74 | get {
75 | if (EntityBodyData == null || EntityBodyData.LongLength == 0)
76 | return String.Empty;
77 |
78 | Encoding enc = null;
79 |
80 | var contentType = _headers["Content-Type"];
81 | if (contentType != null && contentType.Length > 0)
82 | enc = HttpUtility.GetEncoding (contentType);
83 |
84 | return (enc ?? Encoding.UTF8).GetString (EntityBodyData);
85 | }
86 | }
87 |
88 | public NameValueCollection Headers {
89 | get {
90 | return _headers;
91 | }
92 | }
93 |
94 | public Version ProtocolVersion {
95 | get {
96 | return _version;
97 | }
98 | }
99 |
100 | #endregion
101 |
102 | #region Private Methods
103 |
104 | private static byte[] readEntityBody (Stream stream, string length)
105 | {
106 | long len;
107 | if (!Int64.TryParse (length, out len))
108 | throw new ArgumentException ("Cannot be parsed.", "length");
109 |
110 | if (len < 0)
111 | throw new ArgumentOutOfRangeException ("length", "Less than zero.");
112 |
113 | return len > 1024
114 | ? stream.ReadBytes (len, 1024)
115 | : len > 0
116 | ? stream.ReadBytes ((int) len)
117 | : null;
118 | }
119 |
120 | private static string[] readHeaders (Stream stream, int maxLength)
121 | {
122 | var buff = new List ();
123 | var cnt = 0;
124 | Action add = i => {
125 | if (i == -1)
126 | throw new EndOfStreamException ("The header cannot be read from the data source.");
127 |
128 | buff.Add ((byte) i);
129 | cnt++;
130 | };
131 |
132 | var read = false;
133 | while (cnt < maxLength) {
134 | if (stream.ReadByte ().EqualsWith ('\r', add) &&
135 | stream.ReadByte ().EqualsWith ('\n', add) &&
136 | stream.ReadByte ().EqualsWith ('\r', add) &&
137 | stream.ReadByte ().EqualsWith ('\n', add)) {
138 | read = true;
139 | break;
140 | }
141 | }
142 |
143 | if (!read)
144 | throw new WebSocketException ("The length of header part is greater than the max length.");
145 |
146 | return Encoding.UTF8.GetString (buff.ToArray ())
147 | .Replace (CrLf + " ", " ")
148 | .Replace (CrLf + "\t", " ")
149 | .Split (new[] { CrLf }, StringSplitOptions.RemoveEmptyEntries);
150 | }
151 |
152 | #endregion
153 |
154 | #region Protected Methods
155 |
156 | protected static T Read (Stream stream, Func parser, int millisecondsTimeout)
157 | where T : HttpBase
158 | {
159 | var timeout = false;
160 | var timer = new Timer (
161 | state => {
162 | timeout = true;
163 | stream.Close ();
164 | },
165 | null,
166 | millisecondsTimeout,
167 | -1);
168 |
169 | T http = null;
170 | Exception exception = null;
171 | try {
172 | http = parser (readHeaders (stream, _headersMaxLength));
173 | var contentLen = http.Headers["Content-Length"];
174 | if (contentLen != null && contentLen.Length > 0)
175 | http.EntityBodyData = readEntityBody (stream, contentLen);
176 | }
177 | catch (Exception ex) {
178 | exception = ex;
179 | }
180 | finally {
181 | timer.Change (-1, -1);
182 | timer.Dispose ();
183 | }
184 |
185 | var msg = timeout
186 | ? "A timeout has occurred while reading an HTTP request/response."
187 | : exception != null
188 | ? "An exception has occurred while reading an HTTP request/response."
189 | : null;
190 |
191 | if (msg != null)
192 | throw new WebSocketException (msg, exception);
193 |
194 | return http;
195 | }
196 |
197 | #endregion
198 |
199 | #region Public Methods
200 |
201 | public byte[] ToByteArray ()
202 | {
203 | return Encoding.UTF8.GetBytes (ToString ());
204 | }
205 |
206 | #endregion
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/HttpRequest.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * HttpRequest.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2012-2015 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | #region Contributors
30 | /*
31 | * Contributors:
32 | * - David Burhans
33 | */
34 | #endregion
35 |
36 | using System;
37 | using System.Collections.Specialized;
38 | using System.IO;
39 | using System.Text;
40 | using WebSocketSharper.Net;
41 |
42 | namespace WebSocketSharper
43 | {
44 | internal class HttpRequest : HttpBase
45 | {
46 | #region Private Fields
47 |
48 | private CookieCollection _cookies;
49 | private string _method;
50 | private string _uri;
51 |
52 | #endregion
53 |
54 | #region Private Constructors
55 |
56 | private HttpRequest (string method, string uri, Version version, NameValueCollection headers)
57 | : base (version, headers)
58 | {
59 | _method = method;
60 | _uri = uri;
61 | }
62 |
63 | #endregion
64 |
65 | #region Internal Constructors
66 |
67 | internal HttpRequest (string method, string uri)
68 | : this (method, uri, HttpVersion.Version11, new NameValueCollection ())
69 | {
70 | Headers["User-Agent"] = "websocket-sharp/1.0";
71 | }
72 |
73 | #endregion
74 |
75 | #region Public Properties
76 |
77 | public AuthenticationResponse AuthenticationResponse {
78 | get {
79 | var res = Headers["Authorization"];
80 | return res != null && res.Length > 0
81 | ? AuthenticationResponse.Parse (res)
82 | : null;
83 | }
84 | }
85 |
86 | public CookieCollection Cookies {
87 | get {
88 | if (_cookies == null)
89 | _cookies = Headers.GetCookies (false);
90 |
91 | return _cookies;
92 | }
93 | }
94 |
95 | public string HttpMethod {
96 | get {
97 | return _method;
98 | }
99 | }
100 |
101 | public bool IsWebSocketRequest {
102 | get {
103 | return _method == "GET"
104 | && ProtocolVersion > HttpVersion.Version10
105 | && Headers.Upgrades ("websocket");
106 | }
107 | }
108 |
109 | public string RequestUri {
110 | get {
111 | return _uri;
112 | }
113 | }
114 |
115 | #endregion
116 |
117 | #region Internal Methods
118 |
119 | internal static HttpRequest CreateConnectRequest (Uri uri)
120 | {
121 | var host = uri.DnsSafeHost;
122 | var port = uri.Port;
123 | var authority = String.Format ("{0}:{1}", host, port);
124 | var req = new HttpRequest ("CONNECT", authority);
125 | req.Headers["Host"] = port == 80 ? host : authority;
126 |
127 | return req;
128 | }
129 |
130 | internal static HttpRequest CreateWebSocketRequest (Uri uri)
131 | {
132 | var req = new HttpRequest ("GET", uri.PathAndQuery);
133 | var headers = req.Headers;
134 |
135 | // Only includes a port number in the Host header value if it's non-default.
136 | // See: https://tools.ietf.org/html/rfc6455#page-17
137 | var port = uri.Port;
138 | var schm = uri.Scheme;
139 | headers["Host"] = (port == 80 && schm == "ws") || (port == 443 && schm == "wss")
140 | ? uri.DnsSafeHost
141 | : uri.Authority;
142 |
143 | headers["Upgrade"] = "websocket";
144 | headers["Connection"] = "Upgrade";
145 |
146 | return req;
147 | }
148 |
149 | internal HttpResponse GetResponse (Stream stream, int millisecondsTimeout)
150 | {
151 | var buff = ToByteArray ();
152 | stream.Write (buff, 0, buff.Length);
153 |
154 | return Read (stream, HttpResponse.Parse, millisecondsTimeout);
155 | }
156 |
157 | internal static HttpRequest Parse (string[] headerParts)
158 | {
159 | var requestLine = headerParts[0].Split (new[] { ' ' }, 3);
160 | if (requestLine.Length != 3)
161 | throw new ArgumentException ("Invalid request line: " + headerParts[0]);
162 |
163 | var headers = new WebHeaderCollection ();
164 | for (int i = 1; i < headerParts.Length; i++)
165 | headers.InternalSet (headerParts[i], false);
166 |
167 | return new HttpRequest (
168 | requestLine[0], requestLine[1], new Version (requestLine[2].Substring (5)), headers);
169 | }
170 |
171 | internal static HttpRequest Read (Stream stream, int millisecondsTimeout)
172 | {
173 | return Read (stream, Parse, millisecondsTimeout);
174 | }
175 |
176 | #endregion
177 |
178 | #region Public Methods
179 |
180 | public void SetCookies (CookieCollection cookies)
181 | {
182 | if (cookies == null || cookies.Count == 0)
183 | return;
184 |
185 | var buff = new StringBuilder (64);
186 | foreach (var cookie in cookies.Sorted)
187 | if (!cookie.Expired)
188 | buff.AppendFormat ("{0}; ", cookie.ToString ());
189 |
190 | var len = buff.Length;
191 | if (len > 2) {
192 | buff.Length = len - 2;
193 | Headers["Cookie"] = buff.ToString ();
194 | }
195 | }
196 |
197 | public override string ToString ()
198 | {
199 | var output = new StringBuilder (64);
200 | output.AppendFormat ("{0} {1} HTTP/{2}{3}", _method, _uri, ProtocolVersion, CrLf);
201 |
202 | var headers = Headers;
203 | foreach (var key in headers.AllKeys)
204 | output.AppendFormat ("{0}: {1}{2}", key, headers[key], CrLf);
205 |
206 | output.Append (CrLf);
207 |
208 | var entity = EntityBody;
209 | if (entity.Length > 0)
210 | output.Append (entity);
211 |
212 | return output.ToString ();
213 | }
214 |
215 | #endregion
216 | }
217 | }
218 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/ChunkedRequestStream.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * ChunkedRequestStream.cs
4 | *
5 | * This code is derived from ChunkedInputStream.cs (System.Net) of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
11 | * Copyright (c) 2012-2015 sta.blockhead
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy
14 | * of this software and associated documentation files (the "Software"), to deal
15 | * in the Software without restriction, including without limitation the rights
16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | * copies of the Software, and to permit persons to whom the Software is
18 | * furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | * THE SOFTWARE.
30 | */
31 | #endregion
32 |
33 | #region Authors
34 | /*
35 | * Authors:
36 | * - Gonzalo Paniagua Javier
37 | */
38 | #endregion
39 |
40 | using System;
41 | using System.IO;
42 |
43 | namespace WebSocketSharper.Net
44 | {
45 | internal class ChunkedRequestStream : RequestStream
46 | {
47 | #region Private Fields
48 |
49 | private const int _bufferLength = 8192;
50 | private HttpListenerContext _context;
51 | private ChunkStream _decoder;
52 | private bool _disposed;
53 | private bool _noMoreData;
54 |
55 | #endregion
56 |
57 | #region Internal Constructors
58 |
59 | internal ChunkedRequestStream (
60 | Stream stream, byte[] buffer, int offset, int count, HttpListenerContext context)
61 | : base (stream, buffer, offset, count)
62 | {
63 | _context = context;
64 | _decoder = new ChunkStream ((WebHeaderCollection) context.Request.Headers);
65 | }
66 |
67 | #endregion
68 |
69 | #region Internal Properties
70 |
71 | internal ChunkStream Decoder {
72 | get {
73 | return _decoder;
74 | }
75 |
76 | set {
77 | _decoder = value;
78 | }
79 | }
80 |
81 | #endregion
82 |
83 | #region Private Methods
84 |
85 | private void onRead (IAsyncResult asyncResult)
86 | {
87 | var rstate = (ReadBufferState) asyncResult.AsyncState;
88 | var ares = rstate.AsyncResult;
89 | try {
90 | var nread = base.EndRead (asyncResult);
91 | _decoder.Write (ares.Buffer, ares.Offset, nread);
92 | nread = _decoder.Read (rstate.Buffer, rstate.Offset, rstate.Count);
93 | rstate.Offset += nread;
94 | rstate.Count -= nread;
95 | if (rstate.Count == 0 || !_decoder.WantMore || nread == 0) {
96 | _noMoreData = !_decoder.WantMore && nread == 0;
97 | ares.Count = rstate.InitialCount - rstate.Count;
98 | ares.Complete ();
99 |
100 | return;
101 | }
102 |
103 | ares.Offset = 0;
104 | ares.Count = Math.Min (_bufferLength, _decoder.ChunkLeft + 6);
105 | base.BeginRead (ares.Buffer, ares.Offset, ares.Count, onRead, rstate);
106 | }
107 | catch (Exception ex) {
108 | _context.Connection.SendError (ex.Message, 400);
109 | ares.Complete (ex);
110 | }
111 | }
112 |
113 | #endregion
114 |
115 | #region Public Methods
116 |
117 | public override IAsyncResult BeginRead (
118 | byte[] buffer, int offset, int count, AsyncCallback callback, object state)
119 | {
120 | if (_disposed)
121 | throw new ObjectDisposedException (GetType ().ToString ());
122 |
123 | if (buffer == null)
124 | throw new ArgumentNullException ("buffer");
125 |
126 | if (offset < 0)
127 | throw new ArgumentOutOfRangeException ("offset", "A negative value.");
128 |
129 | if (count < 0)
130 | throw new ArgumentOutOfRangeException ("count", "A negative value.");
131 |
132 | var len = buffer.Length;
133 | if (offset + count > len)
134 | throw new ArgumentException (
135 | "The sum of 'offset' and 'count' is greater than 'buffer' length.");
136 |
137 | var ares = new HttpStreamAsyncResult (callback, state);
138 | if (_noMoreData) {
139 | ares.Complete ();
140 | return ares;
141 | }
142 |
143 | var nread = _decoder.Read (buffer, offset, count);
144 | offset += nread;
145 | count -= nread;
146 | if (count == 0) {
147 | // Got all we wanted, no need to bother the decoder yet.
148 | ares.Count = nread;
149 | ares.Complete ();
150 |
151 | return ares;
152 | }
153 |
154 | if (!_decoder.WantMore) {
155 | _noMoreData = nread == 0;
156 | ares.Count = nread;
157 | ares.Complete ();
158 |
159 | return ares;
160 | }
161 |
162 | ares.Buffer = new byte[_bufferLength];
163 | ares.Offset = 0;
164 | ares.Count = _bufferLength;
165 |
166 | var rstate = new ReadBufferState (buffer, offset, count, ares);
167 | rstate.InitialCount += nread;
168 | base.BeginRead (ares.Buffer, ares.Offset, ares.Count, onRead, rstate);
169 |
170 | return ares;
171 | }
172 |
173 | public override void Close ()
174 | {
175 | if (_disposed)
176 | return;
177 |
178 | _disposed = true;
179 | base.Close ();
180 | }
181 |
182 | public override int EndRead (IAsyncResult asyncResult)
183 | {
184 | if (_disposed)
185 | throw new ObjectDisposedException (GetType ().ToString ());
186 |
187 | if (asyncResult == null)
188 | throw new ArgumentNullException ("asyncResult");
189 |
190 | var ares = asyncResult as HttpStreamAsyncResult;
191 | if (ares == null)
192 | throw new ArgumentException ("A wrong IAsyncResult.", "asyncResult");
193 |
194 | if (!ares.IsCompleted)
195 | ares.AsyncWaitHandle.WaitOne ();
196 |
197 | if (ares.HasException)
198 | throw new HttpListenerException (400, "I/O operation aborted.");
199 |
200 | return ares.Count;
201 | }
202 |
203 | public override int Read (byte[] buffer, int offset, int count)
204 | {
205 | var ares = BeginRead (buffer, offset, count, null, null);
206 | return EndRead (ares);
207 | }
208 |
209 | #endregion
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Server/WebSocketServiceHost.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * WebSocketServiceHost.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2012-2017 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | #region Contributors
30 | /*
31 | * Contributors:
32 | * - Juan Manuel Lallana
33 | */
34 | #endregion
35 |
36 | using Microsoft.Extensions.Logging;
37 | using System;
38 | using WebSocketSharper.Net.WebSockets;
39 |
40 | namespace WebSocketSharper.Server
41 | {
42 | ///
43 | /// Exposes the methods and properties used to access the information in
44 | /// a WebSocket service provided by the or
45 | /// .
46 | ///
47 | ///
48 | /// This class is an abstract class.
49 | ///
50 | public abstract class WebSocketServiceHost
51 | {
52 | #region Private Fields
53 |
54 | private ILogger _log;
55 | private string _path;
56 | private WebSocketSessionManager _sessions;
57 |
58 | #endregion
59 |
60 | #region Protected Constructors
61 |
62 | ///
63 | /// Initializes a new instance of the class
64 | /// with the specified and .
65 | ///
66 | ///
67 | /// A that represents the absolute path to the service.
68 | ///
69 | ///
70 | /// A that represents the logging function for the service.
71 | ///
72 | protected WebSocketServiceHost (string path, ILogger log)
73 | {
74 | _path = path;
75 | _log = log;
76 |
77 | _sessions = new WebSocketSessionManager (log);
78 | }
79 |
80 | #endregion
81 |
82 | #region Internal Properties
83 |
84 | internal ServerState State {
85 | get {
86 | return _sessions.State;
87 | }
88 | }
89 |
90 | #endregion
91 |
92 | #region Protected Properties
93 |
94 | ///
95 | /// Gets the logging function for the service.
96 | ///
97 | ///
98 | /// A that provides the logging function.
99 | ///
100 | protected ILogger Log {
101 | get {
102 | return _log;
103 | }
104 | }
105 |
106 | #endregion
107 |
108 | #region Public Properties
109 |
110 | ///
111 | /// Gets or sets a value indicating whether the service cleans up
112 | /// the inactive sessions periodically.
113 | ///
114 | ///
115 | /// The set operation does nothing if the service has already started or
116 | /// it is shutting down.
117 | ///
118 | ///
119 | /// true if the service cleans up the inactive sessions every
120 | /// 60 seconds; otherwise, false.
121 | ///
122 | public bool KeepClean {
123 | get {
124 | return _sessions.KeepClean;
125 | }
126 |
127 | set {
128 | _sessions.KeepClean = value;
129 | }
130 | }
131 |
132 | ///
133 | /// Gets the path to the service.
134 | ///
135 | ///
136 | /// A that represents the absolute path to
137 | /// the service.
138 | ///
139 | public string Path {
140 | get {
141 | return _path;
142 | }
143 | }
144 |
145 | ///
146 | /// Gets the management function for the sessions in the service.
147 | ///
148 | ///
149 | /// A that manages the sessions in
150 | /// the service.
151 | ///
152 | public WebSocketSessionManager Sessions {
153 | get {
154 | return _sessions;
155 | }
156 | }
157 |
158 | ///
159 | /// Gets the of the behavior of the service.
160 | ///
161 | ///
162 | /// A that represents the type of the behavior of
163 | /// the service.
164 | ///
165 | public abstract Type BehaviorType { get; }
166 |
167 | ///
168 | /// Gets or sets the time to wait for the response to the WebSocket Ping or
169 | /// Close.
170 | ///
171 | ///
172 | /// The set operation does nothing if the service has already started or
173 | /// it is shutting down.
174 | ///
175 | ///
176 | /// A to wait for the response.
177 | ///
178 | ///
179 | /// The value specified for a set operation is zero or less.
180 | ///
181 | public TimeSpan WaitTime {
182 | get {
183 | return _sessions.WaitTime;
184 | }
185 |
186 | set {
187 | _sessions.WaitTime = value;
188 | }
189 | }
190 |
191 | #endregion
192 |
193 | #region Internal Methods
194 |
195 | internal void Start ()
196 | {
197 | _sessions.Start ();
198 | }
199 |
200 | internal void StartSession (WebSocketContext context)
201 | {
202 | CreateSession ().Start (context, _sessions);
203 | }
204 |
205 | internal void Stop (ushort code, string reason)
206 | {
207 | _sessions.Stop (code, reason);
208 | }
209 |
210 | #endregion
211 |
212 | #region Protected Methods
213 |
214 | ///
215 | /// Creates a new session for the service.
216 | ///
217 | ///
218 | /// A instance that represents
219 | /// the new session.
220 | ///
221 | protected abstract WebSocketBehavior CreateSession ();
222 |
223 | #endregion
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/NetworkCredential.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * NetworkCredential.cs
4 | *
5 | * The MIT License
6 | *
7 | * Copyright (c) 2014-2017 sta.blockhead
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to deal
11 | * in the Software without restriction, including without limitation the rights
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | * copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | * THE SOFTWARE.
26 | */
27 | #endregion
28 |
29 | using System;
30 |
31 | namespace WebSocketSharper.Net
32 | {
33 | ///
34 | /// Provides the credentials for the password-based authentication.
35 | ///
36 | public class NetworkCredential
37 | {
38 | #region Private Fields
39 |
40 | private string _domain;
41 | private static readonly string[] _noRoles;
42 | private string _password;
43 | private string[] _roles;
44 | private string _username;
45 |
46 | #endregion
47 |
48 | #region Static Constructor
49 |
50 | static NetworkCredential ()
51 | {
52 | _noRoles = new string[0];
53 | }
54 |
55 | #endregion
56 |
57 | #region Public Constructors
58 |
59 | ///
60 | /// Initializes a new instance of the class with
61 | /// the specified and .
62 | ///
63 | ///
64 | /// A that represents the username associated with
65 | /// the credentials.
66 | ///
67 | ///
68 | /// A that represents the password for the username
69 | /// associated with the credentials.
70 | ///
71 | ///
72 | /// is .
73 | ///
74 | ///
75 | /// is empty.
76 | ///
77 | public NetworkCredential (string username, string password)
78 | : this (username, password, null, null)
79 | {
80 | }
81 |
82 | ///
83 | /// Initializes a new instance of the class with
84 | /// the specified , ,
85 | /// and .
86 | ///
87 | ///
88 | /// A that represents the username associated with
89 | /// the credentials.
90 | ///
91 | ///
92 | /// A that represents the password for the username
93 | /// associated with the credentials.
94 | ///
95 | ///
96 | /// A that represents the domain associated with
97 | /// the credentials.
98 | ///
99 | ///
100 | /// An array of that represents the roles
101 | /// associated with the credentials if any.
102 | ///
103 | ///
104 | /// is .
105 | ///
106 | ///
107 | /// is empty.
108 | ///
109 | public NetworkCredential (
110 | string username, string password, string domain, params string[] roles
111 | )
112 | {
113 | if (username == null)
114 | throw new ArgumentNullException ("username");
115 |
116 | if (username.Length == 0)
117 | throw new ArgumentException ("An empty string.", "username");
118 |
119 | _username = username;
120 | _password = password;
121 | _domain = domain;
122 | _roles = roles;
123 | }
124 |
125 | #endregion
126 |
127 | #region Public Properties
128 |
129 | ///
130 | /// Gets the domain associated with the credentials.
131 | ///
132 | ///
133 | /// This property returns an empty string if the domain was
134 | /// initialized with .
135 | ///
136 | ///
137 | /// A that represents the domain name
138 | /// to which the username belongs.
139 | ///
140 | public string Domain {
141 | get {
142 | return _domain ?? String.Empty;
143 | }
144 |
145 | internal set {
146 | _domain = value;
147 | }
148 | }
149 |
150 | ///
151 | /// Gets the password for the username associated with the credentials.
152 | ///
153 | ///
154 | /// This property returns an empty string if the password was
155 | /// initialized with .
156 | ///
157 | ///
158 | /// A that represents the password.
159 | ///
160 | public string Password {
161 | get {
162 | return _password ?? String.Empty;
163 | }
164 |
165 | internal set {
166 | _password = value;
167 | }
168 | }
169 |
170 | ///
171 | /// Gets the roles associated with the credentials.
172 | ///
173 | ///
174 | /// This property returns an empty array if the roles were
175 | /// initialized with .
176 | ///
177 | ///
178 | /// An array of that represents the role names
179 | /// to which the username belongs.
180 | ///
181 | public string[] Roles {
182 | get {
183 | return _roles ?? _noRoles;
184 | }
185 |
186 | internal set {
187 | _roles = value;
188 | }
189 | }
190 |
191 | ///
192 | /// Gets the username associated with the credentials.
193 | ///
194 | ///
195 | /// A that represents the username.
196 | ///
197 | public string Username {
198 | get {
199 | return _username;
200 | }
201 |
202 | internal set {
203 | _username = value;
204 | }
205 | }
206 |
207 | #endregion
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/EndPointManager.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * EndPointManager.cs
4 | *
5 | * This code is derived from EndPointManager.cs (System.Net) of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
11 | * Copyright (c) 2012-2016 sta.blockhead
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy
14 | * of this software and associated documentation files (the "Software"), to deal
15 | * in the Software without restriction, including without limitation the rights
16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | * copies of the Software, and to permit persons to whom the Software is
18 | * furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | * THE SOFTWARE.
30 | */
31 | #endregion
32 |
33 | #region Authors
34 | /*
35 | * Authors:
36 | * - Gonzalo Paniagua Javier
37 | */
38 | #endregion
39 |
40 | #region Contributors
41 | /*
42 | * Contributors:
43 | * - Liryna
44 | */
45 | #endregion
46 |
47 | using System;
48 | using System.Collections;
49 | using System.Collections.Generic;
50 | using System.Net;
51 |
52 | namespace WebSocketSharper.Net
53 | {
54 | internal sealed class EndPointManager
55 | {
56 | #region Private Fields
57 |
58 | private static readonly Dictionary _endpoints;
59 |
60 | #endregion
61 |
62 | #region Static Constructor
63 |
64 | static EndPointManager ()
65 | {
66 | _endpoints = new Dictionary ();
67 | }
68 |
69 | #endregion
70 |
71 | #region Private Constructors
72 |
73 | private EndPointManager ()
74 | {
75 | }
76 |
77 | #endregion
78 |
79 | #region Private Methods
80 |
81 | private static void addPrefix (string uriPrefix, HttpListener listener)
82 | {
83 | var pref = new HttpListenerPrefix (uriPrefix);
84 |
85 | var addr = convertToIPAddress (pref.Host);
86 | if (addr == null)
87 | throw new HttpListenerException (87, "Includes an invalid host.");
88 |
89 | if (!addr.IsLocal ())
90 | throw new HttpListenerException (87, "Includes an invalid host.");
91 |
92 | int port;
93 | if (!Int32.TryParse (pref.Port, out port))
94 | throw new HttpListenerException (87, "Includes an invalid port.");
95 |
96 | if (!port.IsPortNumber ())
97 | throw new HttpListenerException (87, "Includes an invalid port.");
98 |
99 | var path = pref.Path;
100 | if (path.IndexOf ('%') != -1)
101 | throw new HttpListenerException (87, "Includes an invalid path.");
102 |
103 | if (path.IndexOf ("//", StringComparison.Ordinal) != -1)
104 | throw new HttpListenerException (87, "Includes an invalid path.");
105 |
106 | var endpoint = new IPEndPoint (addr, port);
107 |
108 | EndPointListener lsnr;
109 | if (_endpoints.TryGetValue (endpoint, out lsnr)) {
110 | if (lsnr.IsSecure ^ pref.IsSecure)
111 | throw new HttpListenerException (87, "Includes an invalid scheme.");
112 | }
113 | else {
114 | lsnr =
115 | new EndPointListener (
116 | endpoint,
117 | pref.IsSecure,
118 | listener.CertificateFolderPath,
119 | listener.SslConfiguration,
120 | listener.ReuseAddress
121 | );
122 |
123 | _endpoints.Add (endpoint, lsnr);
124 | }
125 |
126 | lsnr.AddPrefix (pref, listener);
127 | }
128 |
129 | private static IPAddress convertToIPAddress (string hostname)
130 | {
131 | if (hostname == "*")
132 | return IPAddress.Any;
133 |
134 | if (hostname == "+")
135 | return IPAddress.Any;
136 |
137 | return hostname.ToIPAddress ();
138 | }
139 |
140 | private static void removePrefix (string uriPrefix, HttpListener listener)
141 | {
142 | var pref = new HttpListenerPrefix (uriPrefix);
143 |
144 | var addr = convertToIPAddress (pref.Host);
145 | if (addr == null)
146 | return;
147 |
148 | if (!addr.IsLocal ())
149 | return;
150 |
151 | int port;
152 | if (!Int32.TryParse (pref.Port, out port))
153 | return;
154 |
155 | if (!port.IsPortNumber ())
156 | return;
157 |
158 | var path = pref.Path;
159 | if (path.IndexOf ('%') != -1)
160 | return;
161 |
162 | if (path.IndexOf ("//", StringComparison.Ordinal) != -1)
163 | return;
164 |
165 | var endpoint = new IPEndPoint (addr, port);
166 |
167 | EndPointListener lsnr;
168 | if (!_endpoints.TryGetValue (endpoint, out lsnr))
169 | return;
170 |
171 | if (lsnr.IsSecure ^ pref.IsSecure)
172 | return;
173 |
174 | lsnr.RemovePrefix (pref, listener);
175 | }
176 |
177 | #endregion
178 |
179 | #region Internal Methods
180 |
181 | internal static bool RemoveEndPoint (IPEndPoint endpoint)
182 | {
183 | lock (((ICollection) _endpoints).SyncRoot) {
184 | EndPointListener lsnr;
185 | if (!_endpoints.TryGetValue (endpoint, out lsnr))
186 | return false;
187 |
188 | _endpoints.Remove (endpoint);
189 | lsnr.Close ();
190 |
191 | return true;
192 | }
193 | }
194 |
195 | #endregion
196 |
197 | #region Public Methods
198 |
199 | public static void AddListener (HttpListener listener)
200 | {
201 | var added = new List ();
202 | lock (((ICollection) _endpoints).SyncRoot) {
203 | try {
204 | foreach (var pref in listener.Prefixes) {
205 | addPrefix (pref, listener);
206 | added.Add (pref);
207 | }
208 | }
209 | catch {
210 | foreach (var pref in added)
211 | removePrefix (pref, listener);
212 |
213 | throw;
214 | }
215 | }
216 | }
217 |
218 | public static void AddPrefix (string uriPrefix, HttpListener listener)
219 | {
220 | lock (((ICollection) _endpoints).SyncRoot)
221 | addPrefix (uriPrefix, listener);
222 | }
223 |
224 | public static void RemoveListener (HttpListener listener)
225 | {
226 | lock (((ICollection) _endpoints).SyncRoot) {
227 | foreach (var pref in listener.Prefixes)
228 | removePrefix (pref, listener);
229 | }
230 | }
231 |
232 | public static void RemovePrefix (string uriPrefix, HttpListener listener)
233 | {
234 | lock (((ICollection) _endpoints).SyncRoot)
235 | removePrefix (uriPrefix, listener);
236 | }
237 |
238 | #endregion
239 | }
240 | }
241 |
--------------------------------------------------------------------------------
/src/WebSocketSharper/Net/HttpRequestHeader.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | * HttpRequestHeader.cs
4 | *
5 | * This code is derived from System.Net.HttpRequestHeader.cs of Mono
6 | * (http://www.mono-project.com).
7 | *
8 | * The MIT License
9 | *
10 | * Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
11 | * Copyright (c) 2014 sta.blockhead
12 | *
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy
14 | * of this software and associated documentation files (the "Software"), to deal
15 | * in the Software without restriction, including without limitation the rights
16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | * copies of the Software, and to permit persons to whom the Software is
18 | * furnished to do so, subject to the following conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be included in
21 | * all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 | * THE SOFTWARE.
30 | */
31 | #endregion
32 |
33 | #region Authors
34 | /*
35 | * Authors:
36 | * - Gonzalo Paniagua Javier
37 | */
38 | #endregion
39 |
40 | namespace WebSocketSharper.Net
41 | {
42 | ///
43 | /// Contains the HTTP headers that may be specified in a client request.
44 | ///
45 | ///
46 | /// The HttpRequestHeader enumeration contains the HTTP request headers defined in
47 | /// RFC 2616 for the HTTP/1.1 and
48 | /// RFC 6455 for the WebSocket.
49 | ///
50 | public enum HttpRequestHeader
51 | {
52 | ///
53 | /// Indicates the Cache-Control header.
54 | ///
55 | CacheControl,
56 | ///
57 | /// Indicates the Connection header.
58 | ///
59 | Connection,
60 | ///
61 | /// Indicates the Date header.
62 | ///
63 | Date,
64 | ///
65 | /// Indicates the Keep-Alive header.
66 | ///
67 | KeepAlive,
68 | ///
69 | /// Indicates the Pragma header.
70 | ///
71 | Pragma,
72 | ///
73 | /// Indicates the Trailer header.
74 | ///
75 | Trailer,
76 | ///
77 | /// Indicates the Transfer-Encoding header.
78 | ///
79 | TransferEncoding,
80 | ///
81 | /// Indicates the Upgrade header.
82 | ///
83 | Upgrade,
84 | ///
85 | /// Indicates the Via header.
86 | ///
87 | Via,
88 | ///
89 | /// Indicates the Warning header.
90 | ///
91 | Warning,
92 | ///
93 | /// Indicates the Allow header.
94 | ///
95 | Allow,
96 | ///
97 | /// Indicates the Content-Length header.
98 | ///
99 | ContentLength,
100 | ///
101 | /// Indicates the Content-Type header.
102 | ///
103 | ContentType,
104 | ///
105 | /// Indicates the Content-Encoding header.
106 | ///
107 | ContentEncoding,
108 | ///
109 | /// Indicates the Content-Language header.
110 | ///
111 | ContentLanguage,
112 | ///
113 | /// Indicates the Content-Location header.
114 | ///
115 | ContentLocation,
116 | ///
117 | /// Indicates the Content-MD5 header.
118 | ///
119 | ContentMd5,
120 | ///
121 | /// Indicates the Content-Range header.
122 | ///
123 | ContentRange,
124 | ///
125 | /// Indicates the Expires header.
126 | ///
127 | Expires,
128 | ///
129 | /// Indicates the Last-Modified header.
130 | ///
131 | LastModified,
132 | ///
133 | /// Indicates the Accept header.
134 | ///
135 | Accept,
136 | ///
137 | /// Indicates the Accept-Charset header.
138 | ///
139 | AcceptCharset,
140 | ///
141 | /// Indicates the Accept-Encoding header.
142 | ///
143 | AcceptEncoding,
144 | ///
145 | /// Indicates the Accept-Language header.
146 | ///
147 | AcceptLanguage,
148 | ///
149 | /// Indicates the Authorization header.
150 | ///
151 | Authorization,
152 | ///
153 | /// Indicates the Cookie header.
154 | ///
155 | Cookie,
156 | ///
157 | /// Indicates the Expect header.
158 | ///
159 | Expect,
160 | ///
161 | /// Indicates the From header.
162 | ///
163 | From,
164 | ///
165 | /// Indicates the Host header.
166 | ///
167 | Host,
168 | ///
169 | /// Indicates the If-Match header.
170 | ///
171 | IfMatch,
172 | ///
173 | /// Indicates the If-Modified-Since header.
174 | ///
175 | IfModifiedSince,
176 | ///
177 | /// Indicates the If-None-Match header.
178 | ///
179 | IfNoneMatch,
180 | ///
181 | /// Indicates the If-Range header.
182 | ///
183 | IfRange,
184 | ///
185 | /// Indicates the If-Unmodified-Since header.
186 | ///
187 | IfUnmodifiedSince,
188 | ///
189 | /// Indicates the Max-Forwards header.
190 | ///
191 | MaxForwards,
192 | ///
193 | /// Indicates the Proxy-Authorization header.
194 | ///
195 | ProxyAuthorization,
196 | ///
197 | /// Indicates the Referer header.
198 | ///
199 | Referer,
200 | ///
201 | /// Indicates the Range header.
202 | ///
203 | Range,
204 | ///
205 | /// Indicates the TE header.
206 | ///
207 | Te,
208 | ///
209 | /// Indicates the Translate header.
210 | ///
211 | Translate,
212 | ///
213 | /// Indicates the User-Agent header.
214 | ///
215 | UserAgent,
216 | ///
217 | /// Indicates the Sec-WebSocket-Key header.
218 | ///
219 | SecWebSocketKey,
220 | ///
221 | /// Indicates the Sec-WebSocket-Extensions header.
222 | ///
223 | SecWebSocketExtensions,
224 | ///
225 | /// Indicates the Sec-WebSocket-Protocol header.
226 | ///
227 | SecWebSocketProtocol,
228 | ///
229 | /// Indicates the Sec-WebSocket-Version header.
230 | ///
231 | SecWebSocketVersion
232 | }
233 | }
234 |
--------------------------------------------------------------------------------