Skip to content

Commit

Permalink
Fixed issues that prevented SignalR from working correctly.
Browse files Browse the repository at this point in the history
Still somewhat unstable though.
Release pre2.
  • Loading branch information
ashmind committed May 18, 2013
1 parent 638aa72 commit 4bb98ee
Show file tree
Hide file tree
Showing 23 changed files with 2,382 additions and 117 deletions.
7 changes: 7 additions & 0 deletions IntegrationTests/IntegrationTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,18 @@
<Reference Include="Gate">
<HintPath>..\#packages\Gate.0.27\lib\net40\Gate.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNet.SignalR.Client">
<HintPath>..\#packages\Microsoft.AspNet.SignalR.Client.1.1.0\lib\net45\Microsoft.AspNet.SignalR.Client.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Host.HttpListener">
<HintPath>..\#packages\Microsoft.Owin.Host.HttpListener.0.21.0-pre\lib\net45\Microsoft.Owin.Host.HttpListener.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Hosting">
<HintPath>..\#packages\Microsoft.Owin.Hosting.0.21.0-pre\lib\net40\Microsoft.Owin.Hosting.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\#packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Owin">
<HintPath>..\#packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
Expand All @@ -67,6 +73,7 @@
<Compile Include="Internal\TestStringProvider.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Internal\TestHostStartup.cs" />
<Compile Include="SignalRTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
Expand Down
30 changes: 30 additions & 0 deletions IntegrationTests/SignalRTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Gate.Adapters.AspNet.IntegrationTests.Internal;
using Microsoft.AspNet.SignalR.Client.Hubs;
using Xunit;

namespace Gate.Adapters.AspNet.IntegrationTests {
public class SignalRTests : IDisposable {
private readonly HubConnection _connection;
private readonly IHubProxy _hub;

public SignalRTests() {
_connection = new HubConnection(TestHost.Url.ToString());
_hub = _connection.CreateHubProxy("TestHub");
_connection.Start().Wait();
}

[Fact]
public async Task String_Roundtrip() {
var result = await _hub.Invoke<string>("Roundtrip", "ABCDEF");
Assert.Equal("ABCDEF", result);
}

public void Dispose() {
this._connection.Stop();
}
}
}
2 changes: 2 additions & 0 deletions IntegrationTests/packages.config
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Gate" version="0.27" targetFramework="net45" />
<package id="Microsoft.AspNet.SignalR.Client" version="1.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Host.HttpListener" version="0.21.0-pre" targetFramework="net45" />
<package id="Microsoft.Owin.Hosting" version="0.21.0-pre" targetFramework="net45" />
<package id="Newtonsoft.Json" version="4.5.11" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
<package id="xunit" version="1.9.1" targetFramework="net45" />
<package id="xunit.extensions" version="1.9.1" targetFramework="net45" />
Expand Down
44 changes: 8 additions & 36 deletions Main/AspNetAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ namespace Gate.Adapters.AspNet {
public class AspNetAdapter {
private readonly Func<IDictionary<string, object>, Task> _next;
private readonly AspNetRemote _remote;
private readonly CrossAppDomainDataConverter _converter;

public AspNetAdapter(Func<IDictionary<string, object>, Task> next, AspNetAdapterArguments arguments) {
this._next = next;
this._remote = this.CreateAspNetRemote(Argument.NotNull("arguments", arguments));
_next = next;
_remote = this.CreateAspNetRemote(Argument.NotNull("arguments", arguments));
_converter = new CrossAppDomainDataConverter();
}

private AspNetRemote CreateAspNetRemote(AspNetAdapterArguments arguments) {
Expand All @@ -30,7 +32,7 @@ private AspNetRemote CreateAspNetRemote(AspNetAdapterArguments arguments) {

public Task Invoke(IDictionary<string, object> environment) {
var parent = new TaskCompletionSource<object>();
Task.Factory.StartNew(() => this._remote.ProcessRequest(this.CreateRequestData(environment)))
Task.Factory.StartNew(() => _remote.ProcessRequest(_converter.CreateRequestData(environment)))
.ContinueWith(t => {
if (t.Exception != null) {
parent.SetException(t.Exception);
Expand All @@ -43,25 +45,9 @@ public Task Invoke(IDictionary<string, object> environment) {
return parent.Task;
}

private CrossDomainRequestData CreateRequestData(IDictionary<string, object> environment) {
var request = new Request(environment);
var rawUrl = request.Path + "?" + request.QueryString;
var headers = request.Headers.ToDictionary(h => h.Key, h => string.Join(",", h.Value));
var body = new MemoryStream();
request.Body.CopyTo(body);

return new CrossDomainRequestData(request.Version,
request.Method,
rawUrl,
request.Path,
request.QueryString,
headers,
body.ToArray());
}

private void ProcessResponse(IDictionary<string, object> environment, CrossDomainResponseData responseData, TaskCompletionSource<object> parent) {
private void ProcessResponse(IDictionary<string, object> environment, CrossAppDomainResponseData responseData, TaskCompletionSource<object> parent) {
if (responseData.StatusCode == 404) {
this._next(environment).ContinueWith(t => {
_next(environment).ContinueWith(t => {
if (t.Exception != null) {
parent.SetException(t.Exception);
return;
Expand All @@ -73,7 +59,7 @@ private void ProcessResponse(IDictionary<string, object> environment, CrossDomai
}

try {
this.UpdateResponseData(responseData, environment);
_converter.UpdateWithResponseData(environment, responseData);
}
catch (Exception ex) {
parent.SetException(ex);
Expand All @@ -82,19 +68,5 @@ private void ProcessResponse(IDictionary<string, object> environment, CrossDomai

parent.SetResult(null);
}

private void UpdateResponseData(CrossDomainResponseData responseData, IDictionary<string, object> environment) {
var response = new Response(environment);
response.StatusCode = responseData.StatusCode;
response.ReasonPhrase = responseData.StatusDescription;

foreach (var pair in responseData.Headers) {
response.Headers.Add(pair.Key, new[] { pair.Value });
}

foreach (var data in responseData.Body) {
response.Write(data.Item1, 0, data.Item2);
}
}
}
}
10 changes: 7 additions & 3 deletions Main/AspNetRemote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@

namespace Gate.Adapters.AspNet {
public class AspNetRemote : MarshalByRefObject {
public CrossDomainResponseData ProcessRequest(CrossDomainRequestData requestData) {
var responseData = new CrossDomainResponseData();
HttpRuntime.ProcessRequest(new GateWorkerRequest(requestData, responseData));
public CrossAppDomainResponseData ProcessRequest(CrossAppDomainRequestData requestData) {
var responseData = new CrossAppDomainResponseData();
// can be rewritten to support true async later on (beginrequest/endrequest)
using (var request = new GateWorkerRequest(requestData, responseData)) {
HttpRuntime.ProcessRequest(request);
request.WaitForEnd();
}
return responseData;
}

Expand Down
16 changes: 16 additions & 0 deletions Main/Integration/CrossAppDomainAddressAndPort.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace Gate.Adapters.AspNet.Integration {
[Serializable]
public class CrossAppDomainAddressAndPort {
public CrossAppDomainAddressAndPort(string address, int port) {
Address = address;
Port = port;
}

public string Address { get; private set; }
public int Port { get; private set; }
}
}
48 changes: 48 additions & 0 deletions Main/Integration/CrossAppDomainDataConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Gate.Adapters.AspNet.Integration {
public class CrossAppDomainDataConverter {
public CrossAppDomainRequestData CreateRequestData(IDictionary<string, object> environment) {
var request = new Request(environment);

var rawUrl = request.Path + "?" + request.QueryString;
var headers = request.Headers.ToDictionary(h => h.Key, h => string.Join(",", h.Value));
var body = new MemoryStream();
request.Body.CopyTo(body);

return new CrossAppDomainRequestData(request.Version,
request.Method,
new CrossAppDomainAddressAndPort(request.Host, request.Port),
GetRemoteAddressAndPort(request),
rawUrl,
request.Path,
request.QueryString,
headers,
body.ToArray());
}

private static CrossAppDomainAddressAndPort GetRemoteAddressAndPort(Request request) {
var address = request.Get<string>("server.RemoteIpAddress") ?? "0.0.0.0";
var portString = request.Get<string>("server.RemotePort");
var port = !string.IsNullOrEmpty(portString) ? int.Parse(portString) : 0;
return new CrossAppDomainAddressAndPort(address, port);
}

public void UpdateWithResponseData(IDictionary<string, object> environment, CrossAppDomainResponseData responseData) {
var response = new Response(environment);
response.StatusCode = responseData.StatusCode;
response.ReasonPhrase = responseData.StatusDescription;

foreach (var pair in responseData.Headers) {
response.Headers.Add(pair.Key, new[] { pair.Value });
}

foreach (var data in responseData.Body) {
response.Write(data.Item1, 0, data.Item2);
}
}
}
}
39 changes: 39 additions & 0 deletions Main/Integration/CrossAppDomainRequestData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace Gate.Adapters.AspNet.Integration {
[Serializable]
public class CrossAppDomainRequestData {
public CrossAppDomainRequestData(string httpVersion,
string httpVerbName,
CrossAppDomainAddressAndPort local,
CrossAppDomainAddressAndPort remote,
string rawUrl,
string uriPath,
string queryString,
IDictionary<string, string> headers,
byte[] body)
{
HttpVersion = httpVersion;
HttpVerbName = httpVerbName;
Local = Argument.NotNull("local", local);
Remote = Argument.NotNull("remote", remote);
RawUrl = rawUrl;
UriPath = uriPath;
QueryString = queryString;
Headers = new ReadOnlyDictionary<string, string>(Argument.NotNull("headers", headers));
Body = body;
}
public string RawUrl { get; private set; }
public string UriPath { get; private set; }
public string QueryString { get; private set; }
public string HttpVerbName { get; private set; }
public CrossAppDomainAddressAndPort Local { get; private set; }
public CrossAppDomainAddressAndPort Remote { get; private set; }
public string HttpVersion { get; private set; }
public IReadOnlyDictionary<string, string> Headers { get; private set; }
public byte[] Body { get; private set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

namespace Gate.Adapters.AspNet.Integration {
[Serializable]
public class CrossDomainResponseData {
public CrossDomainResponseData() {
this.Body = new List<Tuple<byte[], int>>();
this.Headers = new Dictionary<string, string>();
public class CrossAppDomainResponseData {
public CrossAppDomainResponseData() {
Body = new List<Tuple<byte[], int>>();
Headers = new Dictionary<string, string>();
}

public int StatusCode { get; set; }
Expand Down
34 changes: 0 additions & 34 deletions Main/Integration/CrossDomainRequestData.cs

This file was deleted.

Loading

0 comments on commit 4bb98ee

Please sign in to comment.