| 
									
										
										
										
											2022-06-18 17:39:08 +00:00
										 |  |  | import * as sha1 from './sha1.js'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | var gHandlers = []; | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | var gSocketHandlers = []; | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | var gBadRequests = {}; | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-07 01:00:50 +00:00
										 |  |  | const kRequestTimeout = 15000; | 
					
						
							| 
									
										
										
										
											2022-06-17 18:51:24 +00:00
										 |  |  | const kStallTimeout = 60000; | 
					
						
							| 
									
										
										
										
											2022-06-07 01:00:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | function logError(error) { | 
					
						
							|  |  |  | 	print("ERROR " + error); | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 	if (error.stackTrace) { | 
					
						
							|  |  |  | 		print(error.stackTrace); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function addHandler(handler) { | 
					
						
							|  |  |  | 	var added = false; | 
					
						
							|  |  |  | 	for (var i in gHandlers) { | 
					
						
							|  |  |  | 		if (gHandlers[i].path == handler.path) { | 
					
						
							|  |  |  | 			gHandlers[i] = handler; | 
					
						
							|  |  |  | 			added = true; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (!added) { | 
					
						
							|  |  |  | 		gHandlers.push(handler); | 
					
						
							|  |  |  | 		added = true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function all(prefix, handler) { | 
					
						
							|  |  |  | 	addHandler({ | 
					
						
							|  |  |  | 		owner: this, | 
					
						
							|  |  |  | 		path: prefix, | 
					
						
							|  |  |  | 		invoke: handler, | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | function registerSocketHandler(prefix, handler) { | 
					
						
							|  |  |  | 	gSocketHandlers.push({ | 
					
						
							|  |  |  | 		owner: this, | 
					
						
							|  |  |  | 		path: prefix, | 
					
						
							|  |  |  | 		invoke: handler, | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | function Request(method, uri, version, headers, body, client) { | 
					
						
							|  |  |  | 	this.method = method; | 
					
						
							|  |  |  | 	var index = uri.indexOf("?"); | 
					
						
							|  |  |  | 	if (index != -1) { | 
					
						
							|  |  |  | 		this.uri = uri.slice(0, index); | 
					
						
							|  |  |  | 		this.query = uri.slice(index + 1); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		this.uri = uri; | 
					
						
							|  |  |  | 		this.query = undefined; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 	this.version = version || ''; | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 	this.headers = headers; | 
					
						
							| 
									
										
										
										
											2022-01-09 01:36:29 +00:00
										 |  |  | 	this.client = {peerName: client.peerName, tls: client.tls}; | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 	this.body = body; | 
					
						
							|  |  |  | 	return this; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function findHandler(request) { | 
					
						
							|  |  |  | 	var matchedHandler = null; | 
					
						
							|  |  |  | 	for (var name in gHandlers) { | 
					
						
							|  |  |  | 		var handler = gHandlers[name]; | 
					
						
							|  |  |  | 		if (request.uri == handler.path || request.uri.slice(0, handler.path.length + 1) == handler.path + '/') { | 
					
						
							|  |  |  | 			matchedHandler = handler; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return matchedHandler; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | function findSocketHandler(request) { | 
					
						
							|  |  |  | 	var matchedHandler = null; | 
					
						
							|  |  |  | 	for (var name in gSocketHandlers) { | 
					
						
							|  |  |  | 		var handler = gSocketHandlers[name]; | 
					
						
							|  |  |  | 		if (request.uri == handler.path || request.uri.slice(0, handler.path.length + 1) == handler.path + '/') { | 
					
						
							|  |  |  | 			matchedHandler = handler; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return matchedHandler; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | function Response(request, client) { | 
					
						
							|  |  |  | 	var kStatusText = { | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 		101: "Switching Protocols", | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 		200: 'OK', | 
					
						
							|  |  |  | 		303: 'See other', | 
					
						
							| 
									
										
										
										
											2016-03-17 00:51:08 +00:00
										 |  |  | 		403: 'Forbidden', | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 		404: 'File not found', | 
					
						
							|  |  |  | 		500: 'Internal server error', | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 	var _started = false; | 
					
						
							|  |  |  | 	var _finished = false; | 
					
						
							|  |  |  | 	var _keepAlive = false; | 
					
						
							|  |  |  | 	var _chunked = false; | 
					
						
							|  |  |  | 	return { | 
					
						
							|  |  |  | 		writeHead: function(status) { | 
					
						
							|  |  |  | 			if (_started) { | 
					
						
							|  |  |  | 				throw new Error("Response.writeHead called multiple times."); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			var reason; | 
					
						
							|  |  |  | 			var headers; | 
					
						
							|  |  |  | 			if (arguments.length == 3) { | 
					
						
							|  |  |  | 				reason = arguments[1]; | 
					
						
							|  |  |  | 				headers = arguments[2]; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				reason = kStatusText[status]; | 
					
						
							|  |  |  | 				headers = arguments[1]; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			var lowerHeaders = {}; | 
					
						
							|  |  |  | 			var requestVersion = request.version.split("/")[1].split("."); | 
					
						
							|  |  |  | 			var responseVersion = (requestVersion[0] >= 1 && requestVersion[0] >= 1) ? "1.1" : "1.0"; | 
					
						
							|  |  |  | 			var headerString = "HTTP/" + responseVersion + " " + status + " " + reason + "\r\n"; | 
					
						
							|  |  |  | 			for (var i in headers) { | 
					
						
							|  |  |  | 				headerString += i + ": " + headers[i] + "\r\n"; | 
					
						
							|  |  |  | 				lowerHeaders[i.toLowerCase()] = headers[i]; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if ("connection" in lowerHeaders) { | 
					
						
							|  |  |  | 				_keepAlive = lowerHeaders["connection"].toLowerCase() == "keep-alive"; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				_keepAlive = ((request.version == "HTTP/1.0" && ("connection" in lowerHeaders && lowerHeaders["connection"].toLowerCase() == "keep-alive")) || | 
					
						
							|  |  |  | 					(request.version == "HTTP/1.1" && (!("connection" in lowerHeaders) || lowerHeaders["connection"].toLowerCase() != "close"))); | 
					
						
							|  |  |  | 				headerString += "Connection: " + (_keepAlive ? "keep-alive" : "close") + "\r\n"; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			_chunked = _keepAlive && !("content-length" in lowerHeaders); | 
					
						
							|  |  |  | 			if (_chunked) { | 
					
						
							|  |  |  | 				headerString += "Transfer-Encoding: chunked\r\n"; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			headerString += "\r\n"; | 
					
						
							|  |  |  | 			_started = true; | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 			client.write(headerString).catch(function() {}); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		end: function(data) { | 
					
						
							|  |  |  | 			if (_finished) { | 
					
						
							|  |  |  | 				throw new Error("Response.end called multiple times."); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (data) { | 
					
						
							|  |  |  | 				if (_chunked) { | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 					client.write(data.length.toString(16) + "\r\n" + data + "\r\n" + "0\r\n\r\n").catch(function() {}); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 					client.write(data).catch(function() {}); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} else if (_chunked) { | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 				client.write("0\r\n\r\n").catch(function() {}); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			_finished = true; | 
					
						
							|  |  |  | 			if (!_keepAlive) { | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 				client.shutdown().catch(function() {}); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		reportError: function(error) { | 
					
						
							|  |  |  | 			if (!_started) { | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 				client.write("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n").catch(function() {}); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			if (!_finished) { | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 				client.write("500 Internal Server Error\r\n\r\n" + error?.stackTrace).catch(function() {}); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			logError(client.peerName + " - - [" + new Date() + "] " + error); | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		isConnected: function() { return client.isConnected; }, | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function handleRequest(request, response) { | 
					
						
							|  |  |  | 	var handler = findHandler(request); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	print(request.client.peerName + " - - [" + new Date() + "] " + request.method + " " + request.uri + " " + request.version + " \"" + request.headers["user-agent"] + "\""); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (handler) { | 
					
						
							|  |  |  | 		try { | 
					
						
							| 
									
										
										
										
											2016-03-17 00:51:08 +00:00
										 |  |  | 			var promise = handler.invoke(request, response); | 
					
						
							|  |  |  | 			if (promise) { | 
					
						
							|  |  |  | 				promise.catch(function(error) { | 
					
						
							|  |  |  | 					response.reportError(error); | 
					
						
							| 
									
										
										
										
											2022-06-02 10:58:22 +00:00
										 |  |  | 					request.client.close(); | 
					
						
							| 
									
										
										
										
											2016-03-17 00:51:08 +00:00
										 |  |  | 				}); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 		} catch (error) { | 
					
						
							|  |  |  | 			response.reportError(error); | 
					
						
							| 
									
										
										
										
											2022-06-02 10:58:22 +00:00
										 |  |  | 			request.client.close(); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		response.writeHead(200, {"Content-Type": "text/plain; charset=utf-8"}); | 
					
						
							|  |  |  | 		response.end("No handler found for request: " + request.uri); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | function handleWebSocketRequest(request, response, client) { | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 	var buffer = new Uint8Array(0); | 
					
						
							| 
									
										
										
										
											2016-12-22 17:38:21 +00:00
										 |  |  | 	var frame = new Uint8Array(0); | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 	var frameOpCode = 0x0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var handler = findSocketHandler(request); | 
					
						
							|  |  |  | 	if (!handler) { | 
					
						
							|  |  |  | 		client.close(); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	response.send = function(message, opCode) { | 
					
						
							|  |  |  | 		if (opCode === undefined) { | 
					
						
							|  |  |  | 			opCode = 0x2; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 		if (opCode == 0x1 && (typeof message == "string" || message instanceof String)) { | 
					
						
							| 
									
										
										
										
											2022-01-27 01:15:54 +00:00
										 |  |  | 			message = utf8Encode(message); | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 		var fin = true; | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 		var packet = [(fin ? (1 << 7) : 0) | (opCode & 0xf)]; | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 		var mask = false; | 
					
						
							|  |  |  | 		if (message.length < 126) { | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 			packet.push((mask ? (1 << 7) : 0) | message.length); | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 		} else if (message.length < (1 << 16)) { | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 			packet.push((mask ? (1 << 7) : 0) | 126); | 
					
						
							|  |  |  | 			packet.push((message.length >> 8) & 0xff); | 
					
						
							|  |  |  | 			packet.push(message.length & 0xff); | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2021-01-02 18:10:00 +00:00
										 |  |  | 			var high = 0; //(message.length / (1 ** 32)) & 0xffffffff;
 | 
					
						
							|  |  |  | 			var low = message.length & 0xffffffff; | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 			packet.push((mask ? (1 << 7) : 0) | 127); | 
					
						
							| 
									
										
										
										
											2021-01-02 18:10:00 +00:00
										 |  |  | 			packet.push((high >> 24) & 0xff); | 
					
						
							|  |  |  | 			packet.push((high >> 16) & 0xff); | 
					
						
							|  |  |  | 			packet.push((high >> 8) & 0xff); | 
					
						
							|  |  |  | 			packet.push((high >> 0) & 0xff); | 
					
						
							|  |  |  | 			packet.push((low >> 24) & 0xff); | 
					
						
							|  |  |  | 			packet.push((low >> 16) & 0xff); | 
					
						
							|  |  |  | 			packet.push((low >> 8) & 0xff); | 
					
						
							|  |  |  | 			packet.push(low & 0xff); | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		var array = new Uint8Array(packet.length + message.length); | 
					
						
							|  |  |  | 		array.set(packet, 0); | 
					
						
							|  |  |  | 		array.set(message, packet.length); | 
					
						
							| 
									
										
										
										
											2022-06-20 14:30:00 +00:00
										 |  |  | 		try { | 
					
						
							|  |  |  | 			return client.write(array); | 
					
						
							|  |  |  | 		} catch (error) { | 
					
						
							|  |  |  | 			client.close(); | 
					
						
							|  |  |  | 			throw error; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	response.onMessage = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	handler.invoke(request, response); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	client.read(function(data) { | 
					
						
							|  |  |  | 		if (data) { | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 			var newBuffer = new Uint8Array(buffer.length + data.length); | 
					
						
							|  |  |  | 			newBuffer.set(buffer, 0); | 
					
						
							|  |  |  | 			newBuffer.set(data, buffer.length); | 
					
						
							|  |  |  | 			buffer = newBuffer; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-02 18:10:00 +00:00
										 |  |  | 			while (buffer.length >= 2) { | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 				var bits0 = buffer[0]; | 
					
						
							|  |  |  | 				var bits1 = buffer[1]; | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 				if (bits1 & (1 << 7) == 0) { | 
					
						
							|  |  |  | 					// Unmasked message.
 | 
					
						
							|  |  |  | 					client.close(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				var opCode = bits0 & 0xf; | 
					
						
							|  |  |  | 				var fin = bits0 & (1 << 7); | 
					
						
							|  |  |  | 				var payloadLength = bits1 & 0x7f; | 
					
						
							|  |  |  | 				var maskStart = 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (payloadLength == 126) { | 
					
						
							|  |  |  | 					payloadLength = 0; | 
					
						
							|  |  |  | 					for (var i = 0; i < 2; i++) { | 
					
						
							|  |  |  | 						payloadLength <<= 8; | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 						payloadLength |= buffer[2 + i]; | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					maskStart = 4; | 
					
						
							|  |  |  | 				} else if (payloadLength == 127) { | 
					
						
							|  |  |  | 					payloadLength = 0; | 
					
						
							|  |  |  | 					for (var i = 0; i < 8; i++) { | 
					
						
							|  |  |  | 						payloadLength <<= 8; | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 						payloadLength |= buffer[2 + i]; | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					maskStart = 10; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				var havePayload = buffer.length >= payloadLength + 2 + 4; | 
					
						
							|  |  |  | 				if (havePayload) { | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 					var mask = buffer.slice(maskStart, maskStart + 4); | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 					var dataStart = maskStart + 4; | 
					
						
							| 
									
										
										
										
											2016-12-22 17:38:21 +00:00
										 |  |  | 					var decoded = new Array(payloadLength); | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 					var payload = buffer.slice(dataStart, dataStart + payloadLength); | 
					
						
							|  |  |  | 					buffer = buffer.slice(dataStart + payloadLength); | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 					for (var i = 0; i < payloadLength; i++) { | 
					
						
							| 
									
										
										
										
											2016-12-22 17:38:21 +00:00
										 |  |  | 						decoded[i] = payload[i] ^ mask[i % 4]; | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-22 17:38:21 +00:00
										 |  |  | 					var newBuffer = new Uint8Array(frame.length + decoded.length); | 
					
						
							|  |  |  | 					newBuffer.set(frame, 0); | 
					
						
							|  |  |  | 					newBuffer.set(decoded, frame.length); | 
					
						
							|  |  |  | 					frame = newBuffer; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 					if (opCode) { | 
					
						
							|  |  |  | 						frameOpCode = opCode; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if (fin) { | 
					
						
							|  |  |  | 						if (response.onMessage) { | 
					
						
							|  |  |  | 							response.onMessage({ | 
					
						
							| 
									
										
										
										
											2022-01-27 01:15:54 +00:00
										 |  |  | 								data: frameOpCode == 0x1 ? utf8Decode(frame) : frame, | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 								opCode: frameOpCode, | 
					
						
							|  |  |  | 							}); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2016-12-22 17:38:21 +00:00
										 |  |  | 						frame = new Uint8Array(0); | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2021-01-02 18:10:00 +00:00
										 |  |  | 				} else { | 
					
						
							|  |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-01-21 00:49:03 +00:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			response.onClose(); | 
					
						
							|  |  |  | 			client.close(); | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | 	client.onError(function(error) { | 
					
						
							|  |  |  | 		logError(client.peerName + " - - [" + new Date() + "] " + error); | 
					
						
							| 
									
										
										
										
											2022-01-21 00:49:03 +00:00
										 |  |  | 		response.onError(error); | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 	}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-23 18:17:55 +00:00
										 |  |  | 	let headers = { | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 		"Upgrade": "websocket", | 
					
						
							|  |  |  | 		"Connection": "Upgrade", | 
					
						
							|  |  |  | 		"Sec-WebSocket-Accept": webSocketAcceptResponse(request.headers["sec-websocket-key"]), | 
					
						
							| 
									
										
										
										
											2016-04-23 18:17:55 +00:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 	if (request.headers["sec-websocket-version"] != "13") { | 
					
						
							|  |  |  | 		headers["Sec-WebSocket-Version"] = "13"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	response.writeHead(101, headers); | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function webSocketAcceptResponse(key) { | 
					
						
							|  |  |  | 	var kMagic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; | 
					
						
							|  |  |  | 	var kAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; | 
					
						
							| 
									
										
										
										
											2022-06-18 17:39:08 +00:00
										 |  |  | 	var hex = sha1.hash(key + kMagic) | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 	var binary = ""; | 
					
						
							|  |  |  | 	for (var i = 0; i < hex.length; i += 6) { | 
					
						
							|  |  |  | 		var characters = hex.substring(i, i + 6); | 
					
						
							|  |  |  | 		if (characters.length < 6) { | 
					
						
							|  |  |  | 			characters += "0".repeat(6 - characters.length); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		var value = parseInt(characters, 16); | 
					
						
							|  |  |  | 		for (var bit = 0; bit < 8 * 3; bit += 6) { | 
					
						
							|  |  |  | 			if (i * 8 / 2 + bit >= 8 * hex.length / 2) { | 
					
						
							|  |  |  | 				binary += kAlphabet.charAt(64); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				binary += kAlphabet.charAt((value >> (18 - bit)) & 63); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return binary; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | function badRequest(client, reason) { | 
					
						
							|  |  |  | 	var now = new Date(); | 
					
						
							|  |  |  | 	var count = 0; | 
					
						
							|  |  |  | 	var old = gBadRequests[client.peerName]; | 
					
						
							|  |  |  | 	if (!old) { | 
					
						
							|  |  |  | 		gBadRequests[client.peerName] = { | 
					
						
							| 
									
										
										
										
											2022-06-20 19:50:03 +00:00
										 |  |  | 			expire: new Date(now.getTime() + 1 * 60 * 1000), | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 			count: 1, | 
					
						
							| 
									
										
										
										
											2022-06-07 02:08:06 +00:00
										 |  |  | 			reason: reason, | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 		}; | 
					
						
							|  |  |  | 		count = 1; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		old.count++; | 
					
						
							| 
									
										
										
										
											2022-06-07 02:08:06 +00:00
										 |  |  | 		old.reason = reason; | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 		count = old.count; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	new Response({version: '1.0'}, client).reportError(reason + ': ' + count); | 
					
						
							|  |  |  | 	client.close(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function allowRequest(client) { | 
					
						
							|  |  |  | 	var old = gBadRequests[client.peerName]; | 
					
						
							|  |  |  | 	if (old) { | 
					
						
							|  |  |  | 		var now = new Date(); | 
					
						
							|  |  |  | 		if (old.expire < now) { | 
					
						
							|  |  |  | 			delete gBadRequests[client.peerName]; | 
					
						
							|  |  |  | 			return true; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			return old.count < 3; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | function handleConnection(client) { | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 	if (!allowRequest(client)) { | 
					
						
							| 
									
										
										
										
											2022-06-07 02:08:06 +00:00
										 |  |  | 		print('Rejecting client for too many bad requests: ', client.peerName, gBadRequests[client.peerName].reason); | 
					
						
							| 
									
										
										
										
											2022-06-17 18:51:24 +00:00
										 |  |  | 		client.info = 'rejected'; | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 		client.close(); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-17 18:51:24 +00:00
										 |  |  | 	client.info = 'accepted'; | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 	var inputBuffer = new Uint8Array(0); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 	var request; | 
					
						
							|  |  |  | 	var headers = {}; | 
					
						
							|  |  |  | 	var lineByLine = true; | 
					
						
							|  |  |  | 	var bodyToRead = -1; | 
					
						
							|  |  |  | 	var body; | 
					
						
							| 
									
										
										
										
											2022-06-07 01:00:50 +00:00
										 |  |  | 	var requestCount = -1; | 
					
						
							| 
									
										
										
										
											2022-06-17 18:51:24 +00:00
										 |  |  | 	var readCount = 0; | 
					
						
							|  |  |  | 	var isWebsocket = false; | 
					
						
							| 
									
										
										
										
											2022-06-07 01:00:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	function resetTimeout(requestIndex) { | 
					
						
							| 
									
										
										
										
											2022-06-17 18:51:24 +00:00
										 |  |  | 		if (isWebsocket) { | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (bodyToRead == -1) { | 
					
						
							|  |  |  | 			setTimeout(function() { | 
					
						
							|  |  |  | 				if (requestCount == requestIndex) { | 
					
						
							|  |  |  | 					client.info = 'timed out'; | 
					
						
							|  |  |  | 					if (requestCount == 0) { | 
					
						
							|  |  |  | 						badRequest(client, 'Timed out waiting for request.'); | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						client.close(); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2022-06-07 02:08:06 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2022-06-17 18:51:24 +00:00
										 |  |  | 			}, kRequestTimeout); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			var lastReadCount = readCount; | 
					
						
							|  |  |  | 			setTimeout(function() { | 
					
						
							|  |  |  | 				if (readCount == lastReadCount) { | 
					
						
							|  |  |  | 					client.info = 'stalled'; | 
					
						
							|  |  |  | 					if (requestCount == 0) { | 
					
						
							|  |  |  | 						badRequest(client, 'Request stalled.'); | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						client.close(); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}, kStallTimeout); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-06-07 01:00:50 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	resetTimeout(++requestCount); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	function reset() { | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 		inputBuffer = new Uint8Array(0); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 		request = undefined; | 
					
						
							|  |  |  | 		headers = {}; | 
					
						
							|  |  |  | 		lineByLine = true; | 
					
						
							|  |  |  | 		bodyToRead = -1; | 
					
						
							|  |  |  | 		body = undefined; | 
					
						
							| 
									
										
										
										
											2022-06-17 18:51:24 +00:00
										 |  |  | 		client.info = 'reset'; | 
					
						
							| 
									
										
										
										
											2022-06-07 01:00:50 +00:00
										 |  |  | 		resetTimeout(++requestCount); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function finish() { | 
					
						
							| 
									
										
										
										
											2022-06-17 18:51:24 +00:00
										 |  |  | 		client.info = 'finishing'; | 
					
						
							| 
									
										
										
										
											2016-04-14 23:37:23 +00:00
										 |  |  | 		var requestObject = new Request(request[0], request[1], request[2], headers, body, client); | 
					
						
							|  |  |  | 		var response = new Response(requestObject, client); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 		try { | 
					
						
							|  |  |  | 			handleRequest(requestObject, response) | 
					
						
							|  |  |  | 			if (client.isConnected) { | 
					
						
							|  |  |  | 				reset(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} catch (error) { | 
					
						
							|  |  |  | 			response.reportError(error); | 
					
						
							| 
									
										
										
										
											2022-06-02 10:58:22 +00:00
										 |  |  | 			client.close(); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function handleLine(line, length) { | 
					
						
							|  |  |  | 		if (bodyToRead == -1) { | 
					
						
							| 
									
										
										
										
											2022-01-27 01:15:54 +00:00
										 |  |  | 			line = utf8Decode(line); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 			if (!request) { | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 				if (!line) { | 
					
						
							|  |  |  | 					badRequest(client, 'Empty request.'); | 
					
						
							|  |  |  | 					return false; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 				request = line.split(' '); | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 				if (request.length != 3 || !request[2].startsWith('HTTP/1.')) { | 
					
						
							|  |  |  | 					badRequest(client, 'Bad request.'); | 
					
						
							|  |  |  | 					request = null; | 
					
						
							|  |  |  | 					return false; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 				return true; | 
					
						
							|  |  |  | 			} else if (line) { | 
					
						
							|  |  |  | 				var colon = line.indexOf(':'); | 
					
						
							|  |  |  | 				var key = line.slice(0, colon).trim(); | 
					
						
							|  |  |  | 				var value = line.slice(colon + 1).trim(); | 
					
						
							|  |  |  | 				headers[key.toLowerCase()] = value; | 
					
						
							|  |  |  | 				return true; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				if (headers["content-length"] != undefined) { | 
					
						
							|  |  |  | 					bodyToRead = parseInt(headers["content-length"]); | 
					
						
							|  |  |  | 					lineByLine = false; | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 					if (bodyToRead > 16 * 1024 * 1024) { | 
					
						
							| 
									
										
										
										
											2022-06-07 02:41:44 +00:00
										 |  |  | 						badRequest(client, 'Request too large: ' + bodyToRead + '.'); | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 						return false; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2022-01-28 03:11:09 +00:00
										 |  |  | 					body = new Uint8Array(bodyToRead); | 
					
						
							| 
									
										
										
										
											2022-06-17 18:51:24 +00:00
										 |  |  | 					client.info = 'waiting for body'; | 
					
						
							| 
									
										
										
										
											2022-06-17 19:58:50 +00:00
										 |  |  | 					resetTimeout(requestCount); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 					return true; | 
					
						
							| 
									
										
										
										
											2016-04-11 15:54:26 +00:00
										 |  |  | 				} else if (headers["connection"] | 
					
						
							|  |  |  | 					&& headers["connection"].toLowerCase().split(",").map(x => x.trim()).indexOf("upgrade") != -1 | 
					
						
							|  |  |  | 					&& headers["upgrade"] | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 					&& headers["upgrade"].toLowerCase() == "websocket") { | 
					
						
							| 
									
										
										
										
											2022-06-17 18:51:24 +00:00
										 |  |  | 					isWebsocket = true; | 
					
						
							|  |  |  | 					client.info = 'websocket'; | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 					var requestObject = new Request(request[0], request[1], request[2], headers, body, client); | 
					
						
							|  |  |  | 					var response = new Response(requestObject, client); | 
					
						
							|  |  |  | 					handleWebSocketRequest(requestObject, response, client); | 
					
						
							| 
									
										
										
										
											2022-06-07 02:08:06 +00:00
										 |  |  | 					/* Prevent the timeout from disconnecting us. */ | 
					
						
							|  |  |  | 					requestCount++; | 
					
						
							| 
									
										
										
										
											2016-04-11 00:09:21 +00:00
										 |  |  | 					return false; | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 				} else { | 
					
						
							|  |  |  | 					finish(); | 
					
						
							|  |  |  | 					return false; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2022-01-28 03:11:09 +00:00
										 |  |  | 			var offset = body.length - bodyToRead; | 
					
						
							|  |  |  | 			if (line.length > body.length - offset) { | 
					
						
							|  |  |  | 				line = line.slice(0, body.length - offset); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			body.set(line, offset); | 
					
						
							|  |  |  | 			bodyToRead -= line.length; | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 			if (bodyToRead <= 0) { | 
					
						
							|  |  |  | 				finish(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-24 13:57:27 +00:00
										 |  |  | 	client.noDelay = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 	client.onError(function(error) { | 
					
						
							|  |  |  | 		logError(client.peerName + " - - [" + new Date() + "] " + error); | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	client.read(function(data) { | 
					
						
							| 
									
										
										
										
											2022-06-17 18:51:24 +00:00
										 |  |  | 		readCount++; | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 		if (data) { | 
					
						
							| 
									
										
										
										
											2022-06-17 18:51:24 +00:00
										 |  |  | 			if (bodyToRead != -1 && !isWebsocket) { | 
					
						
							|  |  |  | 				resetTimeout(requestCount); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 			const kMaxLineLength = 4096; | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 			var newBuffer = new Uint8Array(inputBuffer.length + data.length); | 
					
						
							|  |  |  | 			newBuffer.set(inputBuffer, 0); | 
					
						
							|  |  |  | 			newBuffer.set(data, inputBuffer.length); | 
					
						
							|  |  |  | 			inputBuffer = newBuffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var newLine = '\n'.charCodeAt(0); | 
					
						
							|  |  |  | 			var carriageReturn = '\r'.charCodeAt(0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 			var more = true; | 
					
						
							|  |  |  | 			while (more) { | 
					
						
							|  |  |  | 				if (lineByLine) { | 
					
						
							|  |  |  | 					more = false; | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 					var end = inputBuffer.indexOf(newLine); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 					var realEnd = end; | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 					if (end > 0 && inputBuffer[end - 1] == carriageReturn) { | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 						--end; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2022-04-26 23:05:02 +00:00
										 |  |  | 					if (end > kMaxLineLength || end == -1 && inputBuffer.length > kMaxLineLength) { | 
					
						
							|  |  |  | 						badRequest(client, 'Request too long.'); | 
					
						
							|  |  |  | 						return; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 					if (end != -1) { | 
					
						
							|  |  |  | 						var line = inputBuffer.slice(0, end); | 
					
						
							|  |  |  | 						inputBuffer = inputBuffer.slice(realEnd + 1); | 
					
						
							|  |  |  | 						more = handleLine(line, realEnd + 1); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					more = handleLine(inputBuffer, inputBuffer.length); | 
					
						
							| 
									
										
										
										
											2016-12-21 20:19:23 +00:00
										 |  |  | 					inputBuffer = new Uint8Array(0); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-06-17 18:51:24 +00:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			client.info = 'EOF'; | 
					
						
							|  |  |  | 			client.close(); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var kBacklog = 8; | 
					
						
							|  |  |  | var kHost = "0.0.0.0" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var socket = new Socket(); | 
					
						
							| 
									
										
										
										
											2021-01-02 18:10:00 +00:00
										 |  |  | socket.bind(kHost, tildefriends.http_port).then(function() { | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 	var listenResult = socket.listen(kBacklog, function() { | 
					
						
							|  |  |  | 		socket.accept().then(handleConnection).catch(function(error) { | 
					
						
							| 
									
										
										
										
											2021-01-02 18:10:00 +00:00
										 |  |  | 			logError("[" + new Date() + "] accept error " + error); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 		}); | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | }).catch(function(error) { | 
					
						
							| 
									
										
										
										
											2021-01-02 18:10:00 +00:00
										 |  |  | 	logError("[" + new Date() + "] bind error " + error); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-02 18:10:00 +00:00
										 |  |  | if (tildefriends.https_port) { | 
					
						
							| 
									
										
										
										
											2017-10-12 23:29:33 +00:00
										 |  |  | 	var tls = {}; | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 	var secureSocket = new Socket(); | 
					
						
							| 
									
										
										
										
											2021-01-02 18:10:00 +00:00
										 |  |  | 	secureSocket.bind(kHost, tildefriends.https_port).then(function() { | 
					
						
							| 
									
										
										
										
											2022-01-05 01:58:12 +00:00
										 |  |  | 		return secureSocket.listen(kBacklog, async function() { | 
					
						
							|  |  |  | 			try { | 
					
						
							|  |  |  | 				var client = await secureSocket.accept(); | 
					
						
							| 
									
										
										
										
											2022-01-09 01:36:29 +00:00
										 |  |  | 				client.tls = true; | 
					
						
							| 
									
										
										
										
											2017-10-12 23:29:33 +00:00
										 |  |  | 				const kCertificatePath = "data/httpd/certificate.pem"; | 
					
						
							|  |  |  | 				const kPrivateKeyPath = "data/httpd/privatekey.pem"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 01:58:12 +00:00
										 |  |  | 				var stat = await Promise.all([ | 
					
						
							|  |  |  | 					await File.stat(kCertificatePath), | 
					
						
							|  |  |  | 					await File.stat(kPrivateKeyPath), | 
					
						
							|  |  |  | 				]); | 
					
						
							|  |  |  | 				if (!tls.context || | 
					
						
							|  |  |  | 					tls.certStat.mtime != stat[0].mtime || | 
					
						
							|  |  |  | 					tls.certStat.size != stat[0].size || | 
					
						
							|  |  |  | 					tls.keyStat.mtime != stat[1].mtime || | 
					
						
							|  |  |  | 					tls.keyStat.size != stat[1].size) { | 
					
						
							|  |  |  | 					print("Reloading " + kCertificatePath + " and " + kPrivateKeyPath); | 
					
						
							| 
									
										
										
										
											2022-01-27 01:15:54 +00:00
										 |  |  | 					var privateKey = utf8Decode(await File.readFile(kPrivateKeyPath)); | 
					
						
							|  |  |  | 					var certificate = utf8Decode(await File.readFile(kCertificatePath)); | 
					
						
							| 
									
										
										
										
											2022-01-05 01:58:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					tls.context = new TlsContext(); | 
					
						
							|  |  |  | 					tls.context.setPrivateKey(privateKey); | 
					
						
							|  |  |  | 					tls.context.setCertificate(certificate); | 
					
						
							|  |  |  | 					tls.certStat = stat[0]; | 
					
						
							|  |  |  | 					tls.keyStat = stat[1]; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-10-12 23:29:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-02 10:58:22 +00:00
										 |  |  | 				let result = client.startTls(tls.context); | 
					
						
							| 
									
										
										
										
											2022-01-05 01:58:12 +00:00
										 |  |  | 				handleConnection(client); | 
					
						
							| 
									
										
										
										
											2022-06-02 10:58:22 +00:00
										 |  |  | 				return result; | 
					
						
							| 
									
										
										
										
											2022-01-05 01:58:12 +00:00
										 |  |  | 			} catch (error) { | 
					
						
							|  |  |  | 				logError("[" + new Date() + "] [" + client.peerName + "] " + error); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2017-10-12 23:29:33 +00:00
										 |  |  | 	}).catch(function(error) { | 
					
						
							| 
									
										
										
										
											2021-01-02 18:10:00 +00:00
										 |  |  | 		logError("[" + new Date() + "] bind error " + error); | 
					
						
							| 
									
										
										
										
											2016-03-12 18:50:43 +00:00
										 |  |  | 	}); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 17:39:08 +00:00
										 |  |  | export { all, registerSocketHandler }; |