Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 832da2a

Browse filesBrowse files
Split out 'socket' hosting model into a separate optional NuGet package, since most developers won't need it
1 parent ebf5a18 commit 832da2a
Copy full SHA for 832da2a
Expand file treeCollapse file tree

24 files changed

+244
-135
lines changed
Open diff view settings
Collapse file

‎pack-local.sh‎

Copy file name to clipboardExpand all lines: pack-local.sh
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ versionSuffix=$1
22
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
33
projects=(
44
./src/Microsoft.AspNetCore.NodeServices
5+
./src/Microsoft.AspNetCore.NodeServices.Sockets
56
./src/Microsoft.AspNetCore.SpaServices
67
./src/Microsoft.AspNetCore.AngularServices
78
./src/Microsoft.AspNetCore.ReactServices
Collapse file

‎samples/misc/LatencyTest/Program.cs‎

Copy file name to clipboardExpand all lines: samples/misc/LatencyTest/Program.cs
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.IO;
44
using System.Threading.Tasks;
55
using Microsoft.AspNetCore.NodeServices;
6+
using Microsoft.AspNetCore.NodeServices.Sockets;
67
using Microsoft.Extensions.DependencyInjection;
78

89
namespace ConsoleApplication
@@ -16,6 +17,10 @@ public static void Main(string[] args) {
1617
// Set up the DI system
1718
var services = new ServiceCollection();
1819
services.AddNodeServices(options => {
20+
// To compare with Socket hosting, uncomment the following line
21+
// Since .NET Core 1.1, the HTTP hosting model has become basically as fast as the Socket hosting model
22+
//options.UseSocketHosting();
23+
1924
options.ProjectPath = Directory.GetCurrentDirectory();
2025
options.WatchFileExtensions = new string[] {}; // Don't watch anything
2126
});
Collapse file

‎samples/misc/LatencyTest/project.json‎

Copy file name to clipboardExpand all lines: samples/misc/LatencyTest/project.json
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"type": "platform"
1010
},
1111
"Microsoft.AspNetCore.NodeServices": "1.1.0-*",
12+
"Microsoft.AspNetCore.NodeServices.Sockets": "1.1.0-*",
1213
"Microsoft.Extensions.DependencyInjection": "1.1.0"
1314
},
1415
"frameworks": {
Collapse file
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/bin/
2+
/node_modules/
3+
yarn.lock
Collapse file

‎…rvices/Content/Node/entrypoint-socket.js‎ ‎…ockets/Content/Node/entrypoint-socket.js‎src/Microsoft.AspNetCore.NodeServices/Content/Node/entrypoint-socket.js renamed to src/Microsoft.AspNetCore.NodeServices.Sockets/Content/Node/entrypoint-socket.js src/Microsoft.AspNetCore.NodeServices/Content/Node/entrypoint-socket.js renamed to src/Microsoft.AspNetCore.NodeServices.Sockets/Content/Node/entrypoint-socket.js

Copy file name to clipboardExpand all lines: src/Microsoft.AspNetCore.NodeServices.Sockets/Content/Node/entrypoint-socket.js
+96-97Lines changed: 96 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,81 @@
4444
/* 0 */
4545
/***/ function(module, exports, __webpack_require__) {
4646

47-
module.exports = __webpack_require__(7);
47+
module.exports = __webpack_require__(1);
48+
49+
50+
/***/ },
51+
/* 1 */
52+
/***/ function(module, exports, __webpack_require__) {
53+
54+
"use strict";
55+
// Limit dependencies to core Node modules. This means the code in this file has to be very low-level and unattractive,
56+
// but simplifies things for the consumer of this module.
57+
__webpack_require__(2);
58+
var net = __webpack_require__(3);
59+
var path = __webpack_require__(4);
60+
var readline = __webpack_require__(5);
61+
var ArgsUtil_1 = __webpack_require__(6);
62+
var ExitWhenParentExits_1 = __webpack_require__(7);
63+
var virtualConnectionServer = __webpack_require__(8);
64+
// Webpack doesn't support dynamic requires for files not present at compile time, so grab a direct
65+
// reference to Node's runtime 'require' function.
66+
var dynamicRequire = eval('require');
67+
// Signal to the .NET side when we're ready to accept invocations
68+
var server = net.createServer().on('listening', function () {
69+
console.log('[Microsoft.AspNetCore.NodeServices:Listening]');
70+
});
71+
// Each virtual connection represents a separate invocation
72+
virtualConnectionServer.createInterface(server).on('connection', function (connection) {
73+
readline.createInterface(connection, null).on('line', function (line) {
74+
try {
75+
// Get a reference to the function to invoke
76+
var invocation = JSON.parse(line);
77+
var invokedModule = dynamicRequire(path.resolve(process.cwd(), invocation.moduleName));
78+
var invokedFunction = invocation.exportedFunctionName ? invokedModule[invocation.exportedFunctionName] : invokedModule;
79+
// Prepare a callback for accepting non-streamed JSON responses
80+
var hasInvokedCallback_1 = false;
81+
var invocationCallback = function (errorValue, successValue) {
82+
if (hasInvokedCallback_1) {
83+
throw new Error('Cannot supply more than one result. The callback has already been invoked,'
84+
+ ' or the result stream has already been accessed');
85+
}
86+
hasInvokedCallback_1 = true;
87+
connection.end(JSON.stringify({
88+
result: successValue,
89+
errorMessage: errorValue && (errorValue.message || errorValue),
90+
errorDetails: errorValue && (errorValue.stack || null)
91+
}));
92+
};
93+
// Also support streamed binary responses
94+
Object.defineProperty(invocationCallback, 'stream', {
95+
enumerable: true,
96+
get: function () {
97+
hasInvokedCallback_1 = true;
98+
return connection;
99+
}
100+
});
101+
// Actually invoke it, passing through any supplied args
102+
invokedFunction.apply(null, [invocationCallback].concat(invocation.args));
103+
}
104+
catch (ex) {
105+
connection.end(JSON.stringify({
106+
errorMessage: ex.message,
107+
errorDetails: ex.stack
108+
}));
109+
}
110+
});
111+
});
112+
// Begin listening now. The underlying transport varies according to the runtime platform.
113+
// On Windows it's Named Pipes; on Linux/OSX it's Domain Sockets.
114+
var useWindowsNamedPipes = /^win/.test(process.platform);
115+
var parsedArgs = ArgsUtil_1.parseArgs(process.argv);
116+
var listenAddress = (useWindowsNamedPipes ? '\\\\.\\pipe\\' : '/tmp/') + parsedArgs.listenAddress;
117+
server.listen(listenAddress);
118+
ExitWhenParentExits_1.exitWhenParentExits(parseInt(parsedArgs.parentPid));
48119

49120

50121
/***/ },
51-
/* 1 */,
52122
/* 2 */
53123
/***/ function(module, exports) {
54124

@@ -90,14 +160,25 @@
90160

91161

92162
/***/ },
93-
/* 3 */,
163+
/* 3 */
164+
/***/ function(module, exports) {
165+
166+
module.exports = require("net");
167+
168+
/***/ },
94169
/* 4 */
95170
/***/ function(module, exports) {
96171

97172
module.exports = require("path");
98173

99174
/***/ },
100175
/* 5 */
176+
/***/ function(module, exports) {
177+
178+
module.exports = require("readline");
179+
180+
/***/ },
181+
/* 6 */
101182
/***/ function(module, exports) {
102183

103184
"use strict";
@@ -123,7 +204,7 @@
123204

124205

125206
/***/ },
126-
/* 6 */
207+
/* 7 */
127208
/***/ function(module, exports) {
128209

129210
/*
@@ -189,96 +270,13 @@
189270
}
190271

191272

192-
/***/ },
193-
/* 7 */
194-
/***/ function(module, exports, __webpack_require__) {
195-
196-
"use strict";
197-
// Limit dependencies to core Node modules. This means the code in this file has to be very low-level and unattractive,
198-
// but simplifies things for the consumer of this module.
199-
__webpack_require__(2);
200-
var net = __webpack_require__(8);
201-
var path = __webpack_require__(4);
202-
var readline = __webpack_require__(9);
203-
var ArgsUtil_1 = __webpack_require__(5);
204-
var ExitWhenParentExits_1 = __webpack_require__(6);
205-
var virtualConnectionServer = __webpack_require__(10);
206-
// Webpack doesn't support dynamic requires for files not present at compile time, so grab a direct
207-
// reference to Node's runtime 'require' function.
208-
var dynamicRequire = eval('require');
209-
// Signal to the .NET side when we're ready to accept invocations
210-
var server = net.createServer().on('listening', function () {
211-
console.log('[Microsoft.AspNetCore.NodeServices:Listening]');
212-
});
213-
// Each virtual connection represents a separate invocation
214-
virtualConnectionServer.createInterface(server).on('connection', function (connection) {
215-
readline.createInterface(connection, null).on('line', function (line) {
216-
try {
217-
// Get a reference to the function to invoke
218-
var invocation = JSON.parse(line);
219-
var invokedModule = dynamicRequire(path.resolve(process.cwd(), invocation.moduleName));
220-
var invokedFunction = invocation.exportedFunctionName ? invokedModule[invocation.exportedFunctionName] : invokedModule;
221-
// Prepare a callback for accepting non-streamed JSON responses
222-
var hasInvokedCallback_1 = false;
223-
var invocationCallback = function (errorValue, successValue) {
224-
if (hasInvokedCallback_1) {
225-
throw new Error('Cannot supply more than one result. The callback has already been invoked,'
226-
+ ' or the result stream has already been accessed');
227-
}
228-
hasInvokedCallback_1 = true;
229-
connection.end(JSON.stringify({
230-
result: successValue,
231-
errorMessage: errorValue && (errorValue.message || errorValue),
232-
errorDetails: errorValue && (errorValue.stack || null)
233-
}));
234-
};
235-
// Also support streamed binary responses
236-
Object.defineProperty(invocationCallback, 'stream', {
237-
enumerable: true,
238-
get: function () {
239-
hasInvokedCallback_1 = true;
240-
return connection;
241-
}
242-
});
243-
// Actually invoke it, passing through any supplied args
244-
invokedFunction.apply(null, [invocationCallback].concat(invocation.args));
245-
}
246-
catch (ex) {
247-
connection.end(JSON.stringify({
248-
errorMessage: ex.message,
249-
errorDetails: ex.stack
250-
}));
251-
}
252-
});
253-
});
254-
// Begin listening now. The underlying transport varies according to the runtime platform.
255-
// On Windows it's Named Pipes; on Linux/OSX it's Domain Sockets.
256-
var useWindowsNamedPipes = /^win/.test(process.platform);
257-
var parsedArgs = ArgsUtil_1.parseArgs(process.argv);
258-
var listenAddress = (useWindowsNamedPipes ? '\\\\.\\pipe\\' : '/tmp/') + parsedArgs.listenAddress;
259-
server.listen(listenAddress);
260-
ExitWhenParentExits_1.exitWhenParentExits(parseInt(parsedArgs.parentPid));
261-
262-
263273
/***/ },
264274
/* 8 */
265-
/***/ function(module, exports) {
266-
267-
module.exports = require("net");
268-
269-
/***/ },
270-
/* 9 */
271-
/***/ function(module, exports) {
272-
273-
module.exports = require("readline");
274-
275-
/***/ },
276-
/* 10 */
277275
/***/ function(module, exports, __webpack_require__) {
278276

279277
"use strict";
280-
var events_1 = __webpack_require__(11);
281-
var VirtualConnection_1 = __webpack_require__(12);
278+
var events_1 = __webpack_require__(9);
279+
var VirtualConnection_1 = __webpack_require__(10);
282280
// Keep this in sync with the equivalent constant in the .NET code. Both sides split up their transmissions into frames with this max length,
283281
// and both will reject longer frames.
284282
var MaxFrameBodyLength = 16 * 1024;
@@ -460,13 +458,13 @@
460458

461459

462460
/***/ },
463-
/* 11 */
461+
/* 9 */
464462
/***/ function(module, exports) {
465463

466464
module.exports = require("events");
467465

468466
/***/ },
469-
/* 12 */
467+
/* 10 */
470468
/***/ function(module, exports, __webpack_require__) {
471469

472470
"use strict";
@@ -475,17 +473,18 @@
475473
function __() { this.constructor = d; }
476474
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
477475
};
478-
var stream_1 = __webpack_require__(13);
476+
var stream_1 = __webpack_require__(11);
479477
/**
480478
* Represents a virtual connection. Multiple virtual connections may be multiplexed over a single physical socket connection.
481479
*/
482480
var VirtualConnection = (function (_super) {
483481
__extends(VirtualConnection, _super);
484482
function VirtualConnection(_beginWriteCallback) {
485-
_super.call(this);
486-
this._beginWriteCallback = _beginWriteCallback;
487-
this._flowing = false;
488-
this._receivedDataQueue = [];
483+
var _this = _super.call(this) || this;
484+
_this._beginWriteCallback = _beginWriteCallback;
485+
_this._flowing = false;
486+
_this._receivedDataQueue = [];
487+
return _this;
489488
}
490489
VirtualConnection.prototype._read = function () {
491490
this._flowing = true;
@@ -516,7 +515,7 @@
516515

517516

518517
/***/ },
519-
/* 13 */
518+
/* 11 */
520519
/***/ function(module, exports) {
521520

522521
module.exports = require("stream");
Collapse file

‎…ysicalConnections/NamedPipeConnection.cs‎ ‎…ysicalConnections/NamedPipeConnection.cs‎src/Microsoft.AspNetCore.NodeServices/HostingModels/PhysicalConnections/NamedPipeConnection.cs renamed to src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/NamedPipeConnection.cs src/Microsoft.AspNetCore.NodeServices/HostingModels/PhysicalConnections/NamedPipeConnection.cs renamed to src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/NamedPipeConnection.cs

Copy file name to clipboardExpand all lines: src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/NamedPipeConnection.cs
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using System.IO.Pipes;
33
using System.Threading.Tasks;
44

5-
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
5+
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
66
{
77
internal class NamedPipeConnection : StreamConnection
88
{
Collapse file

‎…/PhysicalConnections/StreamConnection.cs‎ ‎…/PhysicalConnections/StreamConnection.cs‎src/Microsoft.AspNetCore.NodeServices/HostingModels/PhysicalConnections/StreamConnection.cs renamed to src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/StreamConnection.cs src/Microsoft.AspNetCore.NodeServices/HostingModels/PhysicalConnections/StreamConnection.cs renamed to src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/StreamConnection.cs

Copy file name to clipboardExpand all lines: src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/StreamConnection.cs
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using System.IO;
33
using System.Threading.Tasks;
44

5-
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
5+
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
66
{
77
internal abstract class StreamConnection : IDisposable
88
{
Collapse file

‎…onnections/UnixDomainSocketConnection.cs‎ ‎…onnections/UnixDomainSocketConnection.cs‎src/Microsoft.AspNetCore.NodeServices/HostingModels/PhysicalConnections/UnixDomainSocketConnection.cs renamed to src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/UnixDomainSocketConnection.cs src/Microsoft.AspNetCore.NodeServices/HostingModels/PhysicalConnections/UnixDomainSocketConnection.cs renamed to src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/UnixDomainSocketConnection.cs

Copy file name to clipboardExpand all lines: src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/UnixDomainSocketConnection.cs
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using System.Net.Sockets;
33
using System.Threading.Tasks;
44

5-
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
5+
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
66
{
77
internal class UnixDomainSocketConnection : StreamConnection
88
{
Collapse file

‎…lConnections/UnixDomainSocketEndPoint.cs‎ ‎…lConnections/UnixDomainSocketEndPoint.cs‎src/Microsoft.AspNetCore.NodeServices/HostingModels/PhysicalConnections/UnixDomainSocketEndPoint.cs renamed to src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/UnixDomainSocketEndPoint.cs src/Microsoft.AspNetCore.NodeServices/HostingModels/PhysicalConnections/UnixDomainSocketEndPoint.cs renamed to src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/UnixDomainSocketEndPoint.cs

Copy file name to clipboardExpand all lines: src/Microsoft.AspNetCore.NodeServices.Sockets/PhysicalConnections/UnixDomainSocketEndPoint.cs
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using System.Net.Sockets;
44
using System.Text;
55

6-
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
6+
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
77
{
88
// From System.IO.Pipes/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs (an internal class in System.IO.Pipes)
99
internal sealed class UnixDomainSocketEndPoint : EndPoint
Collapse file

‎…ices/HostingModels/SocketNodeInstance.cs‎ ‎…deServices.Sockets/SocketNodeInstance.cs‎src/Microsoft.AspNetCore.NodeServices/HostingModels/SocketNodeInstance.cs renamed to src/Microsoft.AspNetCore.NodeServices.Sockets/SocketNodeInstance.cs src/Microsoft.AspNetCore.NodeServices/HostingModels/SocketNodeInstance.cs renamed to src/Microsoft.AspNetCore.NodeServices.Sockets/SocketNodeInstance.cs

Copy file name to clipboardExpand all lines: src/Microsoft.AspNetCore.NodeServices.Sockets/SocketNodeInstance.cs
+16-6Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
using System;
2-
using System.Collections.Generic;
31
using System.IO;
42
using System.Text;
53
using System.Threading;
64
using System.Threading.Tasks;
7-
using Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections;
8-
using Microsoft.AspNetCore.NodeServices.HostingModels.VirtualConnections;
5+
using Microsoft.AspNetCore.NodeServices.HostingModels;
6+
using Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections;
7+
using Microsoft.AspNetCore.NodeServices.Sockets.VirtualConnections;
98
using Microsoft.Extensions.Logging;
109
using Newtonsoft.Json;
1110
using Newtonsoft.Json.Serialization;
1211

13-
namespace Microsoft.AspNetCore.NodeServices.HostingModels
12+
namespace Microsoft.AspNetCore.NodeServices.Sockets
1413
{
1514
/// <summary>
1615
/// A specialisation of the OutOfProcessNodeInstance base class that uses a lightweight binary streaming protocol
@@ -77,7 +76,7 @@ protected override async Task<T> InvokeExportAsync<T>(NodeInvocationInfo invocat
7776
// wait for the same connection task. There's no reason why the first caller should have the
7877
// special ability to cancel the connection process in a way that would affect subsequent
7978
// callers. So, each caller just independently stops awaiting connection if that call is cancelled.
80-
await EnsureVirtualConnectionClientCreated().OrThrowOnCancellation(cancellationToken);
79+
await ThrowOnCancellation(EnsureVirtualConnectionClientCreated(), cancellationToken);
8180
}
8281

8382
// For each invocation, we open a new virtual connection. This gives an API equivalent to opening a new
@@ -213,6 +212,17 @@ private static string MakeNewCommandLineOptions(string listenAddress)
213212
return $"--listenAddress {listenAddress}";
214213
}
215214

215+
private static Task ThrowOnCancellation(Task task, CancellationToken cancellationToken)
216+
{
217+
return task.IsCompleted
218+
? task // If the task is already completed, no need to wrap it in a further layer of task
219+
: task.ContinueWith(
220+
_ => {}, // If the task completes, allow execution to continue
221+
cancellationToken,
222+
TaskContinuationOptions.ExecuteSynchronously,
223+
TaskScheduler.Default);
224+
}
225+
216226
#pragma warning disable 649 // These properties are populated via JSON deserialization
217227
private class RpcJsonResponse<TResult>
218228
{

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.