├── .gitignore
├── LICENSE
├── Nuget
└── SocketHttpListener.nuspec
├── README.md
├── SocketHttpListener.Test
├── HttpConnectionTest.cs
├── LoggerFactory.cs
├── Properties
│ └── AssemblyInfo.cs
├── SocketHttpListener.Test.csproj
├── Utility.cs
├── WebsocketTest.cs
├── localhost.pfx
└── packages.config
├── SocketHttpListener.sln
├── SocketHttpListener.sln.GhostDoc.xml
├── SocketHttpListener
├── ByteOrder.cs
├── CloseEventArgs.cs
├── CloseStatusCode.cs
├── CompressionMethod.cs
├── ErrorEventArgs.cs
├── Ext.cs
├── Fin.cs
├── HttpBase.cs
├── HttpResponse.cs
├── Mask.cs
├── MessageEventArgs.cs
├── Net
│ ├── AuthenticationSchemeSelector.cs
│ ├── ChunkStream.cs
│ ├── ChunkedInputStream.cs
│ ├── CookieHelper.cs
│ ├── EndPointListener.cs
│ ├── EndPointManager.cs
│ ├── HttpConnection.cs
│ ├── HttpListener.cs
│ ├── HttpListenerBasicIdentity.cs
│ ├── HttpListenerContext.cs
│ ├── HttpListenerPrefixCollection.cs
│ ├── HttpListenerRequest.cs
│ ├── HttpListenerResponse.cs
│ ├── HttpStatusCode.cs
│ ├── HttpStreamAsyncResult.cs
│ ├── HttpVersion.cs
│ ├── ListenerPrefix.cs
│ ├── RequestStream.cs
│ ├── ResponseStream.cs
│ ├── WebHeaderCollection.cs
│ └── WebSockets
│ │ ├── HttpListenerWebSocketContext.cs
│ │ └── WebSocketContext.cs
├── Opcode.cs
├── PayloadData.cs
├── Properties
│ └── AssemblyInfo.cs
├── Rsv.cs
├── SocketHttpListener.csproj
├── WebSocket.cs
├── WebSocketException.cs
├── WebSocketFrame.cs
├── WebSocketState.cs
└── packages.config
└── packages
├── Moq.4.2.1502.0911
├── Moq.4.2.1502.0911.nupkg
└── lib
│ ├── net35
│ ├── Moq.dll
│ └── Moq.xml
│ ├── net40
│ ├── Moq.dll
│ └── Moq.xml
│ └── sl4
│ ├── Moq.Silverlight.dll
│ └── Moq.Silverlight.xml
├── Patterns.Logging.1.0.0.6
├── Patterns.Logging.1.0.0.6.nupkg
└── lib
│ └── portable-net45+win8
│ └── Patterns.Logging.dll
├── WebSocket4Net.0.12
├── WebSocket4Net.0.12.nupkg
├── lib
│ ├── monoandroid22
│ │ └── WebSocket4Net.dll
│ ├── monotouch10
│ │ └── WebSocket4Net.dll
│ ├── net20
│ │ └── WebSocket4Net.dll
│ ├── net35
│ │ └── WebSocket4Net.dll
│ ├── net40
│ │ └── WebSocket4Net.dll
│ ├── net45
│ │ └── WebSocket4Net.dll
│ ├── sl40-windowsphone71
│ │ └── WebSocket4Net.dll
│ ├── sl40
│ │ └── WebSocket4Net.dll
│ ├── sl50-windowsphone80
│ │ └── WebSocket4Net.dll
│ └── sl50
│ │ └── WebSocket4Net.dll
└── nuget.key
└── repositories.config
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Visual Studio
3 | #################
4 |
5 | ## Ignore Visual Studio temporary files, build results, and
6 | ## files generated by popular Visual Studio add-ons.
7 |
8 | # User-specific files
9 | *.suo
10 | *.user
11 | *.sln.docstates
12 |
13 | # Build results
14 |
15 | [Dd]ebug/
16 | [Rr]elease/
17 | build/
18 | [Bb]in/
19 | [Oo]bj/
20 |
21 | # MSTest test Results
22 | [Tt]est[Rr]esult*/
23 | [Bb]uild[Ll]og.*
24 |
25 | *_i.c
26 | *_p.c
27 | *.ilk
28 | *.meta
29 | *.obj
30 | *.pch
31 | *.pdb
32 | *.pgc
33 | *.pgd
34 | *.rsp
35 | *.sbr
36 | *.tlb
37 | *.tli
38 | *.tlh
39 | *.tmp
40 | *.tmp_proj
41 | *.log
42 | *.vspscc
43 | *.vssscc
44 | .builds
45 | *.pidb
46 | *.log
47 | *.scc
48 | *.scc
49 | *.psess
50 | *.vsp
51 | *.vspx
52 | *.orig
53 | *.rej
54 | *.sdf
55 | *.opensdf
56 | *.ipch
57 |
58 | # Visual C++ cache files
59 | ipch/
60 | *.aps
61 | *.ncb
62 | *.opensdf
63 | *.sdf
64 | *.cachefile
65 |
66 | # Visual Studio profiler
67 | *.psess
68 | *.vsp
69 | *.vspx
70 |
71 | # Guidance Automation Toolkit
72 | *.gpState
73 |
74 | # ReSharper is a .NET coding add-in
75 | _ReSharper*/
76 | *.[Rr]e[Ss]harper
77 |
78 | # TeamCity is a build add-in
79 | _TeamCity*
80 |
81 | # DotCover is a Code Coverage Tool
82 | *.dotCover
83 |
84 | # NCrunch
85 | *.ncrunch*
86 | .*crunch*.local.xml
87 |
88 | # Installshield output folder
89 | [Ee]xpress/
90 |
91 | # DocProject is a documentation generator add-in
92 | DocProject/buildhelp/
93 | DocProject/Help/*.HxT
94 | DocProject/Help/*.HxC
95 | DocProject/Help/*.hhc
96 | DocProject/Help/*.hhk
97 | DocProject/Help/*.hhp
98 | DocProject/Help/Html2
99 | DocProject/Help/html
100 |
101 | # Click-Once directory
102 | publish/
103 |
104 | # Publish Web Output
105 | *.Publish.xml
106 | *.pubxml
107 |
108 | # NuGet Packages Directory
109 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
110 | # packages/
111 | dlls/
112 | dllssigned/
113 |
114 | # Windows Azure Build Output
115 | csx
116 | *.build.csdef
117 |
118 | # Windows Store app package directory
119 | AppPackages/
120 |
121 | # Others
122 | sql/
123 | *.Cache
124 | ClientBin/
125 | [Ss]tyle[Cc]op.*
126 | ~$*
127 | *~
128 | *.dbmdl
129 | *.[Pp]ublish.xml
130 | *.publishsettings
131 |
132 | # RIA/Silverlight projects
133 | Generated_Code/
134 |
135 | # Backup & report files from converting an old project file to a newer
136 | # Visual Studio version. Backup files are not needed, because we have git ;-)
137 | _UpgradeReport_Files/
138 | Backup*/
139 | UpgradeLog*.XML
140 | UpgradeLog*.htm
141 |
142 | # SQL Server files
143 | App_Data/*.mdf
144 | App_Data/*.ldf
145 |
146 | #############
147 | ## Windows detritus
148 | #############
149 |
150 | # Windows image file caches
151 | Thumbs.db
152 | ehthumbs.db
153 |
154 | # Folder config file
155 | Desktop.ini
156 |
157 | # Recycle Bin used on file shares
158 | $RECYCLE.BIN/
159 |
160 | # Mac crap
161 | .DS_Store
162 |
163 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Media Browser
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Nuget/SocketHttpListener.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SocketHttpListener
5 | 1.0.0.44
6 | SocketHttpListener
7 | Emby Team
8 | ebr,Luke,scottisafool
9 | https://github.com/MediaBrowser/SocketHttpListener
10 | http://www.mb3admin.com/images/mb3icons1-1.png
11 | false
12 | A standalone HttpListener with support for SSL, WebSockets and Mono.
13 | Copyright © Emby 2013
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SocketHttpListener
2 | ==================
3 |
4 | A standalone HttpListener with support for SSL, WebSockets and Mono
5 |
6 | As part of Media Browser Server we needed an http server implementation that could support both WebSockets and Mono together on a single port.
7 |
8 | This code was originally forked from websocket-sharp:
9 |
10 | https://github.com/sta/websocket-sharp
11 |
12 | websocket-sharp was originally a clone of the mono HttpListener found here:
13 |
14 | https://github.com/mono/mono/tree/master/mcs/class/System/System.Net
15 |
16 | It also added WebSocket support. Over time websocket-sharp began to introduce a lot of refactoring whereas I prefer a straight clone of the mono implementation with added web socket support. So I rebased from the mono version and added web socket support.
17 |
18 | In addition, there are a few very minor differences with the mono HttpListener:
19 |
20 | * Added ILogger dependency for application logging
21 | * Resolved an issue parsing http headers from Upnp devices. (We need to submit a pull request to mono for this).
22 | * Worked around a known issue with Socket.AcceptAsync and windows (Also need to submit a pull request). See: https://github.com/MediaBrowser/SocketHttpListener/blob/master/SocketHttpListener/Net/EndPointListener.cs#L170
23 | * I have replaced the BeginGetContext with a simple Action delegate. Unlike the .NET HttpListener this is not hooking into http.sys, therefore the only reason for the internal queue was to match the api. Now the consumer can decide how to handle this.
24 |
25 | ## Available on Nuget
26 |
27 | https://www.nuget.org/packages/SocketHttpListener
28 |
--------------------------------------------------------------------------------
/SocketHttpListener.Test/HttpConnectionTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using System.Net.Http;
5 | using System.Reflection;
6 | using System.Security.Cryptography.X509Certificates;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using Microsoft.VisualStudio.TestTools.UnitTesting;
10 | using Moq;
11 | using Patterns.Logging;
12 | using HttpListener = SocketHttpListener.Net.HttpListener;
13 |
14 | namespace SocketHttpListener.Test
15 | {
16 | [TestClass]
17 | public class HttpConnectionTest
18 | {
19 | private static readonly byte[] BYTES_TO_WRITE = Encoding.UTF8.GetBytes(Utility.TEXT_TO_WRITE);
20 |
21 | private static string pfxLocation;
22 |
23 | private Mock logger;
24 | private HttpListener listener;
25 | private HttpClient httpClient;
26 |
27 | [ClassInitialize]
28 | public static void ClassInit(TestContext context)
29 | {
30 | pfxLocation = Utility.GetCertificateFilePath();
31 | }
32 |
33 | [ClassCleanup]
34 | public static void ClassCleanup()
35 | {
36 | if (File.Exists(pfxLocation))
37 | {
38 | File.Delete(pfxLocation);
39 | }
40 | }
41 |
42 | [TestInitialize]
43 | public void TestInit()
44 | {
45 | this.logger = LoggerFactory.CreateLogger();
46 | this.httpClient = new HttpClient();
47 |
48 | ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
49 | }
50 |
51 | [TestCleanup]
52 | public void TestCleanup()
53 | {
54 | ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => false;
55 |
56 | this.logger = null;
57 | ((IDisposable)this.listener).Dispose();
58 | this.httpClient.Dispose();
59 | }
60 |
61 | [TestMethod]
62 | public async Task TestHttpsListenAndConnect()
63 | {
64 | CreateListener(pfxLocation);
65 |
66 | await TestListenAndConnect("https");
67 | }
68 |
69 | [TestMethod]
70 | public async Task TestHttpListenAndConnect()
71 | {
72 | CreateListener(pfxLocation);
73 |
74 | await TestListenAndConnect("http");
75 | }
76 |
77 | [TestMethod]
78 | public async Task TestHttpListenAndConnectMissingCert()
79 | {
80 | CreateListener(@"C:\d.pfx");
81 |
82 | await TestListenAndConnect("http");
83 | }
84 |
85 | [TestMethod]
86 | public async Task TestHttpListenAndConnectNoPrivateKeyCert()
87 | {
88 | string certWithoutKey = Path.GetTempFileName();
89 |
90 | try
91 | {
92 | RemovePrivateKeyAndWrite(pfxLocation, certWithoutKey);
93 |
94 | CreateListener(certWithoutKey);
95 |
96 | await TestListenAndConnect("http");
97 | }
98 | finally
99 | {
100 | File.Delete(certWithoutKey);
101 | }
102 | }
103 |
104 | [TestMethod]
105 | public async Task TestHttpListenAndConnectCorruptedCert()
106 | {
107 |
108 | string corruptedCert = Path.GetTempFileName();
109 |
110 | try
111 | {
112 | File.WriteAllBytes(corruptedCert, new byte[] { 0x01, 0x02 });
113 |
114 | CreateListener(corruptedCert);
115 |
116 | await TestListenAndConnect("http");
117 | }
118 | finally
119 | {
120 | File.Delete(corruptedCert);
121 | }
122 | }
123 |
124 | private void RemovePrivateKeyAndWrite(string sourceCertFile, string destCertFile)
125 | {
126 | X509Certificate2 sourceCert = new X509Certificate2(sourceCertFile);
127 |
128 | sourceCert.PrivateKey = null;
129 |
130 | File.WriteAllBytes(destCertFile, sourceCert.Export(X509ContentType.Pfx, (string)null));
131 | }
132 |
133 | private void CreateListener(string pfxLocationLocal)
134 | {
135 | this.listener = new HttpListener(this.logger.Object, pfxLocationLocal);
136 | }
137 |
138 | private async Task TestListenAndConnect(string prefix)
139 | {
140 | string url = string.Format("{0}://{1}", prefix, Utility.SITE_URL);
141 | this.listener.Prefixes.Add(url);
142 | this.listener.Start();
143 | this.listener.OnContext = async x =>
144 | {
145 | await x.Response.OutputStream.WriteAsync(BYTES_TO_WRITE, 0, BYTES_TO_WRITE.Length);
146 | x.Response.Close();
147 | };
148 |
149 | string result = await this.httpClient.GetStringAsync(url);
150 | Assert.AreEqual(Utility.TEXT_TO_WRITE, result);
151 | }
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/SocketHttpListener.Test/LoggerFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Moq;
8 | using Patterns.Logging;
9 |
10 | namespace SocketHttpListener.Test
11 | {
12 | internal static class LoggerFactory
13 | {
14 | internal static Mock CreateLogger()
15 | {
16 | Mock logger = new Mock();
17 |
18 | SetupConsoleOutput(logger, x => x.Debug(It.IsAny(), It.IsAny