forked from sandstorm-io/sandstorm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
meteor-bundle-main.js
90 lines (77 loc) · 3.18 KB
/
meteor-bundle-main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Typically, Meteor binds to one port and speaks HTTP.
//
// For Sandstorm, `run-bundle` has already bound a number of TCP ports
// for us and passed them in as file descriptors starting at #3. So
// this file runs before Meteor starts, monkey-patching the node world
// so that, along with pre-meteor.js, we create the the right
// HTTP+HTTPS services.
var http = require('http');
var net = require('net');
var isDevShellMode = process.argv.length > 2;
var firstInheritedFd = isDevShellMode ? 65 : 3;
function sandstormMain() {
process.env.SANDSTORM_SMTP_LISTEN_HANDLE = (firstInheritedFd + 2).toString();
process.env.SANDSTORM_BACKEND_HANDLE = (firstInheritedFd + 1).toString();
monkeypatchHttpForGateway();
if (isDevShellMode) {
// Cut ourselves out of argv.
process.argv = [process.argv[0]].concat(process.argv.slice(2));
// Change to the shell directory, which Meteor expects.
process.chdir("shell");
// Delegate to Meteor dev tool.
require(process.argv[1]);
} else {
// Delegate to Meteor runtime.
require("./main.js");
}
}
function monkeypatchHttpForGateway() {
// Monkey-patch the HTTP server module to receive connections over a unix socket on FD 3 instead
// of listening the usual way.
if (process.env.HTTP_GATEWAY === "local") {
// Node.js has no public API for receiving file descriptors via SCM_RIGHTS on a unix pipe.
// However, it does have a *private* API for this, which it uses to implement child_process.
// We use the private API here. This could break when we update Node. If so, that's our fault.
// But we pin our Node version, so this should be easy to control. Also, this interface hasn't
// changed in forever.
const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap');
global.sandstormListenCapabilityStream = function (fd, cb) {
var pipe = new Pipe(PipeConstants.IPC);
pipe.open(fd);
pipe.onread = function (buf) {
let handle = pipe.pendingHandle;
if (handle) {
pipe.pendingHandle = null;
cb(new net.Socket({ handle: handle, readable: true, writable: true }));
}
};
pipe.readStart();
}
}
var oldListen = http.Server.prototype.listen;
var alreadyListened = false;
http.Server.prototype.listen = function (port, host, cb) {
if (port.toString() === process.env.PORT ||
(typeof port === "object" && port.port && port.port.toString() === process.env.PORT)) {
// Attempt to listen on the HTTP port. Override.
if (alreadyListened) {
throw new Error("can only listen on primary HTTP port once");
}
alreadyListened = true;
if (process.env.HTTP_GATEWAY === "local") {
// Gateway running locally, connecting over unix socketpair via SCM_RIGHTS transfer.
global.sandstormListenCapabilityStream(firstInheritedFd, socket => {
this.emit("connection", socket);
});
(cb || host)();
} else {
// Gateway running remotely, connecting over a regular socket.
oldListen.call(this, { fd: firstInheritedFd }, cb || host);
}
} else {
// Don't override.
return oldListen.call(this, port, host, cb);
}
}
}
sandstormMain();