Wed, 31 Dec 2014 06:55:46 +0100
Added tag TORBROWSER_REPLICA for changeset 6474c204b198
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 var spdy = require('../node-spdy/lib/spdy.js');
6 var fs = require('fs');
7 var url = require('url');
8 var crypto = require('crypto');
10 function getHttpContent(path) {
11 var content = '<!doctype html>' +
12 '<html>' +
13 '<head><title>HOORAY!</title></head>' +
14 '<body>You Win! (by requesting' + path + ')</body>' +
15 '</html>';
16 return content;
17 }
19 function getHugeContent(size) {
20 var content = '';
22 for (var i = 0; i < size; i++) {
23 content += '0';
24 }
26 return content;
27 }
29 /* This takes care of responding to the multiplexed request for us */
30 var Multiplex = function() {};
32 Multiplex.prototype = {
33 mp1res: null,
34 mp2res: null,
35 buf: null,
36 mp1start: 0,
37 mp2start: 0,
39 checkReady: function() {
40 if (this.mp1res != null && this.mp2res != null) {
41 this.buf = getHugeContent(30*1024);
42 this.mp1start = 0;
43 this.mp2start = 0;
44 this.send(this.mp1res, 0);
45 setTimeout(function() { this.send(this.mp2res, 0); }.bind(this), 5);
46 }
47 },
49 send: function(res, start) {
50 var end = start + 1024;
51 if (end > this.buf.length)
52 end = this.buf.length;
53 var content = this.buf.substring(start, end);
54 if (end < this.buf.length) {
55 res.write(content);
56 setTimeout(function() { this.send(res, end); }.bind(this), 10);
57 } else {
58 res.end(content);
59 }
60 },
61 };
63 var m = new Multiplex();
65 var post_hash = null;
66 function receivePostData(chunk) {
67 post_hash.update(chunk.toString());
68 }
70 function finishPost(res, content) {
71 var md5 = post_hash.digest('hex');
72 res.setHeader('X-Calculated-MD5', md5);
73 res.writeHead(200);
74 res.end(content);
75 }
77 function handleRequest(req, res) {
78 var u = url.parse(req.url);
79 var content = getHttpContent(u.pathname);
81 if (req.streamID) {
82 res.setHeader('X-Connection-Spdy', 'yes');
83 res.setHeader('X-Spdy-StreamId', '' + req.streamID);
84 } else {
85 res.setHeader('X-Connection-Spdy', 'no');
86 }
88 if (u.pathname == '/exit') {
89 res.setHeader('Content-Type', 'text/plain');
90 res.writeHead(200);
91 res.end('ok');
92 process.exit();
93 } else if (u.pathname == '/multiplex1' && req.streamID) {
94 res.setHeader('Content-Type', 'text/plain');
95 res.writeHead(200);
96 m.mp1res = res;
97 m.checkReady();
98 return;
99 } else if (u.pathname == '/multiplex2' && req.streamID) {
100 res.setHeader('Content-Type', 'text/plain');
101 res.writeHead(200);
102 m.mp2res = res;
103 m.checkReady();
104 return;
105 } else if (u.pathname == "/header") {
106 m = new Multiplex();
107 var val = req.headers["x-test-header"];
108 if (val) {
109 res.setHeader("X-Received-Test-Header", val);
110 }
111 } else if (u.pathname == "/push") {
112 res.push('/push.js',
113 { 'content-type': 'application/javascript',
114 'pushed' : 'yes',
115 'content-length' : 11,
116 'X-Connection-Spdy': 'yes'},
117 function(err, stream) {
118 if (err) return;
119 stream.end('// comments');
120 });
121 content = '<head> <script src="push.js"/></head>body text';
122 } else if (u.pathname == "/push2") {
123 res.push('/push2.js',
124 { 'content-type': 'application/javascript',
125 'pushed' : 'yes',
126 // no content-length
127 'X-Connection-Spdy': 'yes'},
128 function(err, stream) {
129 if (err) return;
130 stream.end('// comments');
131 });
132 content = '<head> <script src="push2.js"/></head>body text';
133 } else if (u.pathname == "/big") {
134 content = getHugeContent(128 * 1024);
135 var hash = crypto.createHash('md5');
136 hash.update(content);
137 var md5 = hash.digest('hex');
138 res.setHeader("X-Expected-MD5", md5);
139 } else if (u.pathname == "/post") {
140 if (req.method != "POST") {
141 res.writeHead(405);
142 res.end('Unexpected method: ' + req.method);
143 return;
144 }
146 post_hash = crypto.createHash('md5');
147 req.on('data', receivePostData);
148 req.on('end', function () { finishPost(res, content); });
150 return;
151 }
153 res.setHeader('Content-Type', 'text/html');
154 res.writeHead(200);
155 res.end(content);
156 }
158 // Set up the SSL certs for our server
159 var options = {
160 key: fs.readFileSync(__dirname + '/spdy-key.pem'),
161 cert: fs.readFileSync(__dirname + '/spdy-cert.pem'),
162 ca: fs.readFileSync(__dirname + '/spdy-ca.pem'),
163 windowSize: 16000000,
164 };
166 spdy.createServer(options, handleRequest).listen(4443);
167 console.log('SPDY server listening on port 4443');
169 // Set up to exit when the user finishes our stdin
170 process.stdin.resume();
171 process.stdin.on('end', function () {
172 process.exit();
173 });