Skip to content

Commit ade78b1

Browse files
committed
#1 - Implement Autobahn test client & server.
1 parent 86822d5 commit ade78b1

File tree

9 files changed

+284
-1
lines changed

9 files changed

+284
-1
lines changed

WebSockets.sln

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 14
4-
VisualStudioVersion = 14.0.22013.1
4+
VisualStudioVersion = 14.0.22216.0
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestServer", "test\TestServer\TestServer.csproj", "{4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}"
77
EndProject
@@ -28,6 +28,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
2828
global.json = global.json
2929
EndProjectSection
3030
EndProject
31+
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AutobahnTestServer", "test\AutobahnTestServer\AutobahnTestServer.kproj", "{C03C43FE-9201-48A6-B434-AD67EF627D67}"
32+
EndProject
33+
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AutobahnTestClient", "test\AutobahnTestClient\AutobahnTestClient.kproj", "{BC4D2BB1-05A8-4816-8BC1-3A664F09EE32}"
34+
EndProject
3135
Global
3236
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3337
Debug|Any CPU = Debug|Any CPU
@@ -62,6 +66,14 @@ Global
6266
{78A097D0-C0A4-4AED-93E2-84A65392FB52}.Debug|Any CPU.Build.0 = Debug|Any CPU
6367
{78A097D0-C0A4-4AED-93E2-84A65392FB52}.Release|Any CPU.ActiveCfg = Release|Any CPU
6468
{78A097D0-C0A4-4AED-93E2-84A65392FB52}.Release|Any CPU.Build.0 = Release|Any CPU
69+
{C03C43FE-9201-48A6-B434-AD67EF627D67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
70+
{C03C43FE-9201-48A6-B434-AD67EF627D67}.Debug|Any CPU.Build.0 = Debug|Any CPU
71+
{C03C43FE-9201-48A6-B434-AD67EF627D67}.Release|Any CPU.ActiveCfg = Release|Any CPU
72+
{C03C43FE-9201-48A6-B434-AD67EF627D67}.Release|Any CPU.Build.0 = Release|Any CPU
73+
{BC4D2BB1-05A8-4816-8BC1-3A664F09EE32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
74+
{BC4D2BB1-05A8-4816-8BC1-3A664F09EE32}.Debug|Any CPU.Build.0 = Debug|Any CPU
75+
{BC4D2BB1-05A8-4816-8BC1-3A664F09EE32}.Release|Any CPU.ActiveCfg = Release|Any CPU
76+
{BC4D2BB1-05A8-4816-8BC1-3A664F09EE32}.Release|Any CPU.Build.0 = Release|Any CPU
6577
EndGlobalSection
6678
GlobalSection(SolutionProperties) = preSolution
6779
HideSolutionNode = FALSE
@@ -74,5 +86,7 @@ Global
7486
{4A1C4875-AE21-4A78-979A-F0E4DF5EB518} = {2C7947A5-9FBD-4267-97C1-2D726D7B3BAF}
7587
{6604D154-817F-4BC5-BE95-FF7E851179D9} = {C45106D0-76C8-4776-A140-F7DD83CA2958}
7688
{78A097D0-C0A4-4AED-93E2-84A65392FB52} = {2C7947A5-9FBD-4267-97C1-2D726D7B3BAF}
89+
{C03C43FE-9201-48A6-B434-AD67EF627D67} = {C45106D0-76C8-4776-A140-F7DD83CA2958}
90+
{BC4D2BB1-05A8-4816-8BC1-3A664F09EE32} = {C45106D0-76C8-4776-A140-F7DD83CA2958}
7791
EndGlobalSection
7892
EndGlobal
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
5+
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
6+
</PropertyGroup>
7+
8+
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.Props" Condition="'$(VSToolsPath)' != ''" />
9+
<PropertyGroup Label="Globals">
10+
<ProjectGuid>bc4d2bb1-05a8-4816-8bc1-3a664f09ee32</ProjectGuid>
11+
<RootNamespace>AutobahnTestClient</RootNamespace>
12+
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
13+
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
14+
</PropertyGroup>
15+
16+
<PropertyGroup>
17+
<SchemaVersion>2.0</SchemaVersion>
18+
</PropertyGroup>
19+
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
20+
</Project>

test/AutobahnTestClient/Program.cs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Net.WebSockets;
6+
using System.Text;
7+
using System.Threading;
8+
using System.Threading.Tasks;
9+
using Microsoft.AspNet.WebSockets.Client;
10+
11+
namespace AutobahnTestClient
12+
{
13+
public class Program
14+
{
15+
public async Task Main(string[] args)
16+
{
17+
try
18+
{
19+
string serverAddress = "ws://localhost:9001";
20+
string agent =
21+
"ManagedWebSockets";
22+
// "NativeWebSockets";
23+
24+
Console.WriteLine("Getting case count.");
25+
var caseCount = await GetCaseCountAsync(serverAddress, agent);
26+
Console.WriteLine(caseCount + " case(s).");
27+
28+
for (int i = 1; i <= caseCount; i++)
29+
{
30+
await RunCaseAsync(serverAddress, i, agent);
31+
}
32+
33+
await UpdateReportsAsync(serverAddress, agent);
34+
}
35+
catch (Exception ex)
36+
{
37+
Console.WriteLine(ex);
38+
}
39+
40+
Console.WriteLine("Done");
41+
Console.ReadLine();
42+
}
43+
44+
private async Task<WebSocket> ConnectAsync(string address, string agent)
45+
{
46+
if (string.Equals(agent, "NativeWebSockets"))
47+
{
48+
var client = new ClientWebSocket();
49+
await client.ConnectAsync(new Uri(address), CancellationToken.None);
50+
return client;
51+
}
52+
else
53+
{
54+
// TODO: BUG: Require ws or wss schemes
55+
var client = new WebSocketClient();
56+
return await client.ConnectAsync(new Uri(address), CancellationToken.None);
57+
}
58+
}
59+
60+
private async Task<int> GetCaseCountAsync(string serverAddress, string agent)
61+
{
62+
var webSocket = await ConnectAsync(serverAddress + "/getCaseCount", agent);
63+
byte[] buffer = new byte[1024 * 4];
64+
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
65+
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
66+
var caseCountText = Encoding.UTF8.GetString(buffer, 0, result.Count);
67+
return int.Parse(caseCountText);
68+
}
69+
70+
private async Task RunCaseAsync(string serverAddress, int caseId, string agent)
71+
{
72+
try
73+
{
74+
Console.WriteLine("Running case " + caseId);
75+
var webSocket = await ConnectAsync(serverAddress + "/runCase?case=" + caseId + "&agent=" + agent, agent);
76+
await Echo(webSocket);
77+
}
78+
catch (Exception ex)
79+
{
80+
Console.WriteLine(ex);
81+
}
82+
}
83+
84+
private async Task Echo(WebSocket webSocket)
85+
{
86+
byte[] buffer = new byte[1024 * 4];
87+
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
88+
while (!result.CloseStatus.HasValue)
89+
{
90+
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
91+
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
92+
}
93+
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
94+
}
95+
96+
private async Task UpdateReportsAsync(string serverAddress, string agent)
97+
{
98+
var webSocket = await ConnectAsync(serverAddress + "/updateReports?agent=" + agent, agent);
99+
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
100+
}
101+
}
102+
}

test/AutobahnTestClient/Project.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"dependencies": {
3+
"Microsoft.AspNet.WebSockets.Client": "1.0.0-*"
4+
},
5+
"commands": {
6+
"run" : "run"
7+
},
8+
"frameworks" : {
9+
"aspnet50" : { }
10+
}
11+
}

test/AutobahnTestClient/ReadMe.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
This test server is for use in testing client side implementations of the WebSocekt protocol. It is currently implemented to test
2+
Microsoft.AspNet.WebSockets.Client.WebSocketClient and System.Net.WebSockets.ClientWebSocket.
3+
4+
See http://autobahn.ws/ to download and install the test framework.
5+
6+
Usage:
7+
Run the test server:
8+
"C:\Program Files\Python\2.7.6\Scripts\wstest" -d -m fuzzingserver -s fuzzingserver.json
9+
Where fuzzingserver.json contains the following:
10+
11+
{
12+
"url": "ws://127.0.0.1:9001",
13+
14+
"options": {"failByDrop": false},
15+
"outdir": "./reports/clients",
16+
"webport": 8080,
17+
18+
"cases": ["*"],
19+
"exclude-cases": [],
20+
"exclude-agent-cases": {}
21+
}
22+
23+
Then run the client of your choice, taking care to update the serverAddress and agent fields in the client code.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
5+
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
6+
</PropertyGroup>
7+
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.Props" Condition="'$(VSToolsPath)' != ''" />
8+
<PropertyGroup Label="Globals">
9+
<ProjectGuid>c03c43fe-9201-48a6-b434-ad67ef627d67</ProjectGuid>
10+
<RootNamespace>AutobahnTestServer</RootNamespace>
11+
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
12+
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
13+
</PropertyGroup>
14+
<PropertyGroup>
15+
<SchemaVersion>2.0</SchemaVersion>
16+
<DevelopmentServerPort>60351</DevelopmentServerPort>
17+
</PropertyGroup>
18+
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
19+
</Project>

test/AutobahnTestServer/Project.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"webroot": "wwwroot",
3+
"exclude": "wwwroot/**/*",
4+
"dependencies": {
5+
"Microsoft.AspNet.Server.IIS": "1.0.0-beta1-*",
6+
"Microsoft.AspNet.Server.WebListener": "1.0.0-beta1-*",
7+
"Microsoft.AspNet.WebSockets.Server": "1.0.0-beta1-*"
8+
},
9+
"commands": { "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:12345" },
10+
"frameworks" : {
11+
"aspnet50" : { },
12+
"aspnetcore50" : { }
13+
}
14+
}

test/AutobahnTestServer/ReadMe.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
This test server is for use in testing server side implementations of the WebSocekt protocol. It should work with Helios, WebListener (native),
2+
and the managed implementation of WebSockets in this project (running on WebListener, Kestrel, etc.). The tests only require that the server implement
3+
a basic WebSocket accept and then echo any content received.
4+
5+
See http://autobahn.ws/ to download and install the test framework.
6+
7+
Usage:
8+
Configure and start the server of your choice.
9+
Run the test client:
10+
"C:\Program Files\Python\2.7.6\Scripts\wstest.exe" -d -m fuzzingclient -s fuzzingclient.json
11+
Where fussingclient.json contains:
12+
{
13+
"options": {"failByDrop": false},
14+
"outdir": "./reports/servers",
15+
16+
"servers": [
17+
{"agent": "NameOfImplementationBeingTested",
18+
"url": "ws://localhost:12345",
19+
"options": {"version": 18}}
20+
],
21+
22+
"cases": ["*"],
23+
"exclude-cases": [],
24+
"exclude-agent-cases": {}
25+
}

test/AutobahnTestServer/Startup.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Net.WebSockets;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.AspNet.Builder;
9+
using Microsoft.AspNet.Http;
10+
using Microsoft.AspNet.WebSockets.Server;
11+
12+
namespace AutobahnTestServer
13+
{
14+
public class Startup
15+
{
16+
public void Configure(IApplicationBuilder app)
17+
{
18+
// Comment this out to test native server implementations
19+
app.UseWebSockets(new WebSocketOptions()
20+
{
21+
ReplaceFeature = true,
22+
});
23+
24+
app.Use(async (context, next) =>
25+
{
26+
if (context.IsWebSocketRequest)
27+
{
28+
Console.WriteLine("Echo: " + context.Request.Path);
29+
var webSocket = await context.AcceptWebSocketAsync();
30+
await Echo(webSocket);
31+
return;
32+
}
33+
await next();
34+
});
35+
36+
app.Run(context =>
37+
{
38+
Console.WriteLine("Hello World");
39+
return context.Response.WriteAsync("Hello World");
40+
});
41+
}
42+
43+
private async Task Echo(WebSocket webSocket)
44+
{
45+
byte[] buffer = new byte[1024 * 4];
46+
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
47+
while (!result.CloseStatus.HasValue)
48+
{
49+
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
50+
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
51+
}
52+
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
53+
}
54+
}
55+
}

0 commit comments

Comments
 (0)