forked from cory/tildefriends
		
	Delete httpd.js.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4709 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		
							
								
								
									
										22
									
								
								core/core.js
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								core/core.js
									
									
									
									
									
								
							@@ -2,7 +2,6 @@ import * as app from './app.js';
 | 
				
			|||||||
import * as auth from './auth.js';
 | 
					import * as auth from './auth.js';
 | 
				
			||||||
import * as form from './form.js';
 | 
					import * as form from './form.js';
 | 
				
			||||||
import * as http from './http.js';
 | 
					import * as http from './http.js';
 | 
				
			||||||
import * as httpd from './httpd.js';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
let gProcessIndex = 0;
 | 
					let gProcessIndex = 0;
 | 
				
			||||||
let gProcesses = {};
 | 
					let gProcesses = {};
 | 
				
			||||||
@@ -952,10 +951,9 @@ function stringResponse(response, data) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
loadSettings().then(function() {
 | 
					loadSettings().then(function() {
 | 
				
			||||||
	let httpd_impl = (tildefriends.args.httpdc ? httpdc : httpd);
 | 
						httpd.all("/login", auth.handler);
 | 
				
			||||||
	httpd_impl.all("/login", auth.handler);
 | 
						httpd.registerSocketHandler("/app/socket", app.socket);
 | 
				
			||||||
	httpd_impl.registerSocketHandler("/app/socket", app.socket);
 | 
						httpd.all("", function(request, response) {
 | 
				
			||||||
	httpd_impl.all("", function(request, response) {
 | 
					 | 
				
			||||||
		let match;
 | 
							let match;
 | 
				
			||||||
		if (request.uri === "/" || request.uri === "") {
 | 
							if (request.uri === "/" || request.uri === "") {
 | 
				
			||||||
			try {
 | 
								try {
 | 
				
			||||||
@@ -1005,9 +1003,17 @@ loadSettings().then(function() {
 | 
				
			|||||||
			return response.end(data);
 | 
								return response.end(data);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	httpd_impl.start(tildefriends.http_port);
 | 
						let port = httpd.start(tildefriends.http_port);
 | 
				
			||||||
 | 
						if (tildefriends.args.out_http_port_file) {
 | 
				
			||||||
 | 
							print("Writing the port file.");
 | 
				
			||||||
 | 
							File.writeFile(tildefriends.args.out_http_port_file, port.toString() + '\n').then(function(r) {
 | 
				
			||||||
 | 
								print("Wrote the port file:", tildefriends.args.out_http_port_file, r);
 | 
				
			||||||
 | 
							}).catch(function() {
 | 
				
			||||||
 | 
								print("Failed to write the port file.");
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (tildefriends.args.httpdc && tildefriends.https_port) {
 | 
						if (tildefriends.https_port) {
 | 
				
			||||||
		async function start_tls() {
 | 
							async function start_tls() {
 | 
				
			||||||
			const kCertificatePath = "data/httpd/certificate.pem";
 | 
								const kCertificatePath = "data/httpd/certificate.pem";
 | 
				
			||||||
			const kPrivateKeyPath = "data/httpd/privatekey.pem";
 | 
								const kPrivateKeyPath = "data/httpd/privatekey.pem";
 | 
				
			||||||
@@ -1016,7 +1022,7 @@ loadSettings().then(function() {
 | 
				
			|||||||
			let context = new TlsContext();
 | 
								let context = new TlsContext();
 | 
				
			||||||
			context.setPrivateKey(privateKey);
 | 
								context.setPrivateKey(privateKey);
 | 
				
			||||||
			context.setCertificate(certificate);
 | 
								context.setCertificate(certificate);
 | 
				
			||||||
			httpd_impl.start(tildefriends.https_port, context);
 | 
								httpd.start(tildefriends.https_port, context);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		start_tls();
 | 
							start_tls();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										598
									
								
								core/httpd.js
									
									
									
									
									
								
							
							
						
						
									
										598
									
								
								core/httpd.js
									
									
									
									
									
								
							@@ -1,598 +0,0 @@
 | 
				
			|||||||
import * as core from './core.js';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let gHandlers = [];
 | 
					 | 
				
			||||||
let gSocketHandlers = [];
 | 
					 | 
				
			||||||
let gBadRequests = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const kRequestTimeout = 5000;
 | 
					 | 
				
			||||||
const kStallTimeout = 60000;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function logError(error) {
 | 
					 | 
				
			||||||
	print("ERROR " + error);
 | 
					 | 
				
			||||||
	if (error.stackTrace) {
 | 
					 | 
				
			||||||
		print(error.stackTrace);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function addHandler(handler) {
 | 
					 | 
				
			||||||
	let added = false;
 | 
					 | 
				
			||||||
	for (let 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,
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function registerSocketHandler(prefix, handler) {
 | 
					 | 
				
			||||||
	gSocketHandlers.push({
 | 
					 | 
				
			||||||
		owner: this,
 | 
					 | 
				
			||||||
		path: prefix,
 | 
					 | 
				
			||||||
		invoke: handler,
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function Request(method, uri, version, headers, body, client) {
 | 
					 | 
				
			||||||
	this.method = method;
 | 
					 | 
				
			||||||
	let 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;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	this.version = version || '';
 | 
					 | 
				
			||||||
	this.headers = headers;
 | 
					 | 
				
			||||||
	this.client = {peerName: client.peerName, tls: client.tls};
 | 
					 | 
				
			||||||
	this.body = body;
 | 
					 | 
				
			||||||
	return this;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function findHandler(request) {
 | 
					 | 
				
			||||||
	let matchedHandler = null;
 | 
					 | 
				
			||||||
	for (let name in gHandlers) {
 | 
					 | 
				
			||||||
		let handler = gHandlers[name];
 | 
					 | 
				
			||||||
		if (request.uri == handler.path || request.uri.slice(0, handler.path.length + 1) == handler.path + '/') {
 | 
					 | 
				
			||||||
			matchedHandler = handler;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return matchedHandler;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function findSocketHandler(request) {
 | 
					 | 
				
			||||||
	let matchedHandler = null;
 | 
					 | 
				
			||||||
	for (let name in gSocketHandlers) {
 | 
					 | 
				
			||||||
		let handler = gSocketHandlers[name];
 | 
					 | 
				
			||||||
		if (request.uri == handler.path || request.uri.slice(0, handler.path.length + 1) == handler.path + '/') {
 | 
					 | 
				
			||||||
			matchedHandler = handler;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return matchedHandler;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function Response(request, client) {
 | 
					 | 
				
			||||||
	let kStatusText = {
 | 
					 | 
				
			||||||
		101: "Switching Protocols",
 | 
					 | 
				
			||||||
		200: 'OK',
 | 
					 | 
				
			||||||
		303: 'See other',
 | 
					 | 
				
			||||||
		304: 'Not Modified',
 | 
					 | 
				
			||||||
		400: 'Bad Request',
 | 
					 | 
				
			||||||
		401: 'Unauthorized',
 | 
					 | 
				
			||||||
		403: 'Forbidden',
 | 
					 | 
				
			||||||
		404: 'File not found',
 | 
					 | 
				
			||||||
		500: 'Internal server error',
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	let _started = false;
 | 
					 | 
				
			||||||
	let _finished = false;
 | 
					 | 
				
			||||||
	let _keepAlive = false;
 | 
					 | 
				
			||||||
	let _chunked = false;
 | 
					 | 
				
			||||||
	return {
 | 
					 | 
				
			||||||
		writeHead: function(status) {
 | 
					 | 
				
			||||||
			if (_started) {
 | 
					 | 
				
			||||||
				throw new Error("Response.writeHead called multiple times.");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			let reason;
 | 
					 | 
				
			||||||
			let headers;
 | 
					 | 
				
			||||||
			if (arguments.length == 3) {
 | 
					 | 
				
			||||||
				reason = arguments[1];
 | 
					 | 
				
			||||||
				headers = arguments[2];
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				reason = kStatusText[status];
 | 
					 | 
				
			||||||
				headers = arguments[1];
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			let lowerHeaders = {};
 | 
					 | 
				
			||||||
			let requestVersion = request.version.split("/")[1].split(".");
 | 
					 | 
				
			||||||
			let responseVersion = (requestVersion[0] >= 1 && requestVersion[0] >= 1) ? "1.1" : "1.0";
 | 
					 | 
				
			||||||
			let headerString = "HTTP/" + responseVersion + " " + status + " " + reason + "\r\n";
 | 
					 | 
				
			||||||
			headers['Server'] = `Tilde Friends/${version().number}`;
 | 
					 | 
				
			||||||
			for (let 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;
 | 
					 | 
				
			||||||
			client.write(headerString).catch(function() {});
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		end: function(data) {
 | 
					 | 
				
			||||||
			if (_finished) {
 | 
					 | 
				
			||||||
				throw new Error("Response.end called multiple times.");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (data) {
 | 
					 | 
				
			||||||
				if (_chunked) {
 | 
					 | 
				
			||||||
					client.write(data.length.toString(16) + "\r\n" + data + "\r\n" + "0\r\n\r\n").catch(function() {});
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					client.write(data).catch(function() {});
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else if (_chunked) {
 | 
					 | 
				
			||||||
				client.write("0\r\n\r\n").catch(function() {});
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			_finished = true;
 | 
					 | 
				
			||||||
			if (!_keepAlive) {
 | 
					 | 
				
			||||||
				client.shutdown().catch(function() {});
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		reportError: function(error) {
 | 
					 | 
				
			||||||
			if (!_started) {
 | 
					 | 
				
			||||||
				client.write("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n").catch(function() {});
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (!_finished) {
 | 
					 | 
				
			||||||
				client.write("500 Internal Server Error\r\n\r\n" + error?.stackTrace).catch(function() {});
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			logError(client.peerName + " - - [" + new Date() + "] " + error);
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		isConnected: function() { return client.isConnected; },
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function handleRequest(request, response) {
 | 
					 | 
				
			||||||
	let handler = findHandler(request);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	print(request.client.peerName + " - - [" + new Date() + "] " + request.method + " " + request.uri + " " + request.version + " \"" + request.headers["user-agent"] + "\"");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (handler) {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			Promise.resolve(handler.invoke(request, response)).catch(function(error) {
 | 
					 | 
				
			||||||
				response.reportError(error);
 | 
					 | 
				
			||||||
				request.client.close();
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			response.reportError(error);
 | 
					 | 
				
			||||||
			request.client.close();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		response.writeHead(200, {"Content-Type": "text/plain; charset=utf-8"});
 | 
					 | 
				
			||||||
		response.end("No handler found for request: " + request.uri);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function handleWebSocketRequest(request, response, client) {
 | 
					 | 
				
			||||||
	let buffer = new Uint8Array(0);
 | 
					 | 
				
			||||||
	let frame;
 | 
					 | 
				
			||||||
	let frameOpCode = 0x0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let handler = findSocketHandler(request);
 | 
					 | 
				
			||||||
	if (!handler) {
 | 
					 | 
				
			||||||
		client.close();
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (client) {
 | 
					 | 
				
			||||||
		response.send = function(message, opCode) {
 | 
					 | 
				
			||||||
			if (opCode === undefined) {
 | 
					 | 
				
			||||||
				opCode = 0x2;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (opCode == 0x1 && (typeof message == "string" || message instanceof String)) {
 | 
					 | 
				
			||||||
				message = utf8Encode(message);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			let fin = true;
 | 
					 | 
				
			||||||
			let packet = [(fin ? (1 << 7) : 0) | (opCode & 0xf)];
 | 
					 | 
				
			||||||
			let mask = false;
 | 
					 | 
				
			||||||
			if (message.length < 126) {
 | 
					 | 
				
			||||||
				packet.push((mask ? (1 << 7) : 0) | message.length);
 | 
					 | 
				
			||||||
			} else if (message.length < (1 << 16)) {
 | 
					 | 
				
			||||||
				packet.push((mask ? (1 << 7) : 0) | 126);
 | 
					 | 
				
			||||||
				packet.push((message.length >> 8) & 0xff);
 | 
					 | 
				
			||||||
				packet.push(message.length & 0xff);
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				let high = 0; //(message.length / (1 ** 32)) & 0xffffffff;
 | 
					 | 
				
			||||||
				let low = message.length & 0xffffffff;
 | 
					 | 
				
			||||||
				packet.push((mask ? (1 << 7) : 0) | 127);
 | 
					 | 
				
			||||||
				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);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			let array = new Uint8Array(packet.length + message.length);
 | 
					 | 
				
			||||||
			array.set(packet, 0);
 | 
					 | 
				
			||||||
			array.set(message, packet.length);
 | 
					 | 
				
			||||||
			try {
 | 
					 | 
				
			||||||
				return client.write(array);
 | 
					 | 
				
			||||||
			} catch (error) {
 | 
					 | 
				
			||||||
				client.close();
 | 
					 | 
				
			||||||
				throw error;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	response.onMessage = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let extra_headers = handler.invoke(request, response);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (client) {
 | 
					 | 
				
			||||||
		client.read(function(data) {
 | 
					 | 
				
			||||||
			if (data) {
 | 
					 | 
				
			||||||
				let newBuffer = new Uint8Array(buffer.length + data.length);
 | 
					 | 
				
			||||||
				newBuffer.set(buffer, 0);
 | 
					 | 
				
			||||||
				newBuffer.set(data, buffer.length);
 | 
					 | 
				
			||||||
				buffer = newBuffer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				while (buffer.length >= 2) {
 | 
					 | 
				
			||||||
					let bits0 = buffer[0];
 | 
					 | 
				
			||||||
					let bits1 = buffer[1];
 | 
					 | 
				
			||||||
					if (bits1 & (1 << 7) == 0) {
 | 
					 | 
				
			||||||
						// Unmasked message.
 | 
					 | 
				
			||||||
						client.close();
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					let opCode = bits0 & 0xf;
 | 
					 | 
				
			||||||
					let fin = bits0 & (1 << 7);
 | 
					 | 
				
			||||||
					let payloadLength = bits1 & 0x7f;
 | 
					 | 
				
			||||||
					let maskStart = 2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					if (payloadLength == 126) {
 | 
					 | 
				
			||||||
						payloadLength = 0;
 | 
					 | 
				
			||||||
						for (let i = 0; i < 2; i++) {
 | 
					 | 
				
			||||||
							payloadLength <<= 8;
 | 
					 | 
				
			||||||
							payloadLength |= buffer[2 + i];
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
						maskStart = 4;
 | 
					 | 
				
			||||||
					} else if (payloadLength == 127) {
 | 
					 | 
				
			||||||
						payloadLength = 0;
 | 
					 | 
				
			||||||
						for (let i = 0; i < 8; i++) {
 | 
					 | 
				
			||||||
							payloadLength <<= 8;
 | 
					 | 
				
			||||||
							payloadLength |= buffer[2 + i];
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
						maskStart = 10;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					let havePayload = buffer.length >= payloadLength + 2 + 4;
 | 
					 | 
				
			||||||
					if (havePayload) {
 | 
					 | 
				
			||||||
						let mask =
 | 
					 | 
				
			||||||
							buffer[maskStart + 0] |
 | 
					 | 
				
			||||||
							buffer[maskStart + 1] << 8 |
 | 
					 | 
				
			||||||
							buffer[maskStart + 2] << 16 |
 | 
					 | 
				
			||||||
							buffer[maskStart + 3] << 24;
 | 
					 | 
				
			||||||
						let dataStart = maskStart + 4;
 | 
					 | 
				
			||||||
						let payload = buffer.slice(dataStart, dataStart + payloadLength);
 | 
					 | 
				
			||||||
						let decoded = maskBytes(payload, mask);
 | 
					 | 
				
			||||||
						buffer = buffer.slice(dataStart + payloadLength);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						if (frame) {
 | 
					 | 
				
			||||||
							let newBuffer = new Uint8Array(frame.length + decoded.length);
 | 
					 | 
				
			||||||
							newBuffer.set(frame, 0);
 | 
					 | 
				
			||||||
							newBuffer.set(decoded, frame.length);
 | 
					 | 
				
			||||||
							frame = newBuffer;
 | 
					 | 
				
			||||||
						} else {
 | 
					 | 
				
			||||||
							frame = decoded;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						if (opCode) {
 | 
					 | 
				
			||||||
							frameOpCode = opCode;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						if (fin) {
 | 
					 | 
				
			||||||
							if (response.onMessage) {
 | 
					 | 
				
			||||||
								response.onMessage({
 | 
					 | 
				
			||||||
									data: frameOpCode == 0x1 ? utf8Decode(frame) : frame,
 | 
					 | 
				
			||||||
									opCode: frameOpCode,
 | 
					 | 
				
			||||||
								});
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
							frame = undefined;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					} else {
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				response.onClose();
 | 
					 | 
				
			||||||
				client.close();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
		client.onError(function(error) {
 | 
					 | 
				
			||||||
			logError(client.peerName + " - - [" + new Date() + "] " + error);
 | 
					 | 
				
			||||||
			response.onError(error);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let headers = {
 | 
					 | 
				
			||||||
		"Upgrade": "websocket",
 | 
					 | 
				
			||||||
		"Connection": "Upgrade",
 | 
					 | 
				
			||||||
		"Sec-WebSocket-Accept": webSocketAcceptResponse(request.headers["sec-websocket-key"]),
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	if (request.headers["sec-websocket-version"] != "13") {
 | 
					 | 
				
			||||||
		headers["Sec-WebSocket-Version"] = "13";
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	response.writeHead(101, Object.assign({}, headers, extra_headers));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function webSocketAcceptResponse(key) {
 | 
					 | 
				
			||||||
	let kMagic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
 | 
					 | 
				
			||||||
	return base64Encode(sha1Digest(key + kMagic));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function badRequest(client, reason) {
 | 
					 | 
				
			||||||
	let now = new Date();
 | 
					 | 
				
			||||||
	let count = 0;
 | 
					 | 
				
			||||||
	let old = gBadRequests[client.peerName];
 | 
					 | 
				
			||||||
	if (!old) {
 | 
					 | 
				
			||||||
		gBadRequests[client.peerName] = {
 | 
					 | 
				
			||||||
			expire: new Date(now.getTime() + 1 * 60 * 1000),
 | 
					 | 
				
			||||||
			count: 1,
 | 
					 | 
				
			||||||
			reason: reason,
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
		count = 1;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		old.count++;
 | 
					 | 
				
			||||||
		old.reason = reason;
 | 
					 | 
				
			||||||
		count = old.count;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	new Response({version: '1.0'}, client).reportError(reason + ': ' + count);
 | 
					 | 
				
			||||||
	client.close();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function allowRequest(client) {
 | 
					 | 
				
			||||||
	let old = gBadRequests[client.peerName];
 | 
					 | 
				
			||||||
	if (old) {
 | 
					 | 
				
			||||||
		let now = new Date();
 | 
					 | 
				
			||||||
		if (old.expire < now) {
 | 
					 | 
				
			||||||
			delete gBadRequests[client.peerName];
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return old.count < 3;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return true;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function handleConnection(client) {
 | 
					 | 
				
			||||||
	if (!allowRequest(client)) {
 | 
					 | 
				
			||||||
		print('Rejecting client for too many bad requests: ', client.peerName, gBadRequests[client.peerName].reason);
 | 
					 | 
				
			||||||
		client.info = 'rejected';
 | 
					 | 
				
			||||||
		client.close();
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	client.info = 'accepted';
 | 
					 | 
				
			||||||
	let inputBuffer = new Uint8Array(0);
 | 
					 | 
				
			||||||
	let request;
 | 
					 | 
				
			||||||
	let headers = {};
 | 
					 | 
				
			||||||
	let parsing_header = true;
 | 
					 | 
				
			||||||
	let bodyToRead = -1;
 | 
					 | 
				
			||||||
	let body;
 | 
					 | 
				
			||||||
	let readCount = 0;
 | 
					 | 
				
			||||||
	let isWebsocket = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	client.setActivityTimeout(kRequestTimeout);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function reset() {
 | 
					 | 
				
			||||||
		request = undefined;
 | 
					 | 
				
			||||||
		headers = {};
 | 
					 | 
				
			||||||
		parsing_header = true;
 | 
					 | 
				
			||||||
		bodyToRead = -1;
 | 
					 | 
				
			||||||
		body = undefined;
 | 
					 | 
				
			||||||
		client.info = 'reset';
 | 
					 | 
				
			||||||
		client.setActivityTimeout(kRequestTimeout);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function finish() {
 | 
					 | 
				
			||||||
		client.info = 'finishing';
 | 
					 | 
				
			||||||
		let requestObject = new Request(request[0], request[1], request[2], headers, body, client);
 | 
					 | 
				
			||||||
		let response = new Response(requestObject, client);
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			handleRequest(requestObject, response)
 | 
					 | 
				
			||||||
			if (client.isConnected) {
 | 
					 | 
				
			||||||
				reset();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			response.reportError(error);
 | 
					 | 
				
			||||||
			client.close();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	client.onError(function(error) {
 | 
					 | 
				
			||||||
		logError(client.peerName + " - - [" + new Date() + "] " + error);
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	client.read(function(data) {
 | 
					 | 
				
			||||||
		readCount++;
 | 
					 | 
				
			||||||
		if (data) {
 | 
					 | 
				
			||||||
			let newBuffer = new Uint8Array(inputBuffer.length + data.length);
 | 
					 | 
				
			||||||
			newBuffer.set(inputBuffer, 0);
 | 
					 | 
				
			||||||
			newBuffer.set(data, inputBuffer.length);
 | 
					 | 
				
			||||||
			inputBuffer = newBuffer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (parsing_header)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				let result = parseHttpRequest(inputBuffer, inputBuffer.length - data.length);
 | 
					 | 
				
			||||||
				if (result) {
 | 
					 | 
				
			||||||
					if (typeof result === 'number') {
 | 
					 | 
				
			||||||
						if (result == -2) {
 | 
					 | 
				
			||||||
							/* More. */
 | 
					 | 
				
			||||||
						} else {
 | 
					 | 
				
			||||||
							badRequest(client, `Bad request(parse=${result}, length=${inputBuffer.length - data.length}).`);
 | 
					 | 
				
			||||||
							return;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					} else if (typeof result === 'object')  {
 | 
					 | 
				
			||||||
						client.setActivityTimeout(kStallTimeout);
 | 
					 | 
				
			||||||
						request = [
 | 
					 | 
				
			||||||
							result.method,
 | 
					 | 
				
			||||||
							result.path,
 | 
					 | 
				
			||||||
							`HTTP/1.${result.minor_version}`,
 | 
					 | 
				
			||||||
						];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						headers = Object.fromEntries(Object.entries(result.headers).map(x => [x[0].toLowerCase(), x[1]]));
 | 
					 | 
				
			||||||
						parsing_header = false;
 | 
					 | 
				
			||||||
						inputBuffer = inputBuffer.slice(result.bytes_parsed);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						if (!client.tls && tildefriends.https_port && core.globalSettings.http_redirect && !result.path.startsWith('/.well-known/')) {
 | 
					 | 
				
			||||||
							let requestObject = new Request(request[0], request[1], request[2], headers, body, client);
 | 
					 | 
				
			||||||
							let response = new Response(requestObject, client);
 | 
					 | 
				
			||||||
							response.writeHead(303, {"Location": `${core.globalSettings.http_redirect}${result.path}`, "Content-Length": "0"});
 | 
					 | 
				
			||||||
							response.end();
 | 
					 | 
				
			||||||
							return;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						if (headers["content-length"] != undefined) {
 | 
					 | 
				
			||||||
							bodyToRead = parseInt(headers["content-length"]);
 | 
					 | 
				
			||||||
							if (bodyToRead > 16 * 1024 * 1024) {
 | 
					 | 
				
			||||||
								badRequest(client, 'Request too large: ' + bodyToRead + '.');
 | 
					 | 
				
			||||||
								return;
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
							body = new Uint8Array(bodyToRead);
 | 
					 | 
				
			||||||
							client.info = 'waiting for body';
 | 
					 | 
				
			||||||
						} else if (headers["connection"]
 | 
					 | 
				
			||||||
							&& headers["connection"].toLowerCase().split(",").map(x => x.trim()).indexOf("upgrade") != -1
 | 
					 | 
				
			||||||
							&& headers["upgrade"]
 | 
					 | 
				
			||||||
							&& headers["upgrade"].toLowerCase() == "websocket") {
 | 
					 | 
				
			||||||
							isWebsocket = true;
 | 
					 | 
				
			||||||
							client.info = 'websocket';
 | 
					 | 
				
			||||||
							let requestObject = new Request(request[0], request[1], request[2], headers, body, client);
 | 
					 | 
				
			||||||
							let response = new Response(requestObject, client);
 | 
					 | 
				
			||||||
							handleWebSocketRequest(requestObject, response, client);
 | 
					 | 
				
			||||||
							/* Prevent the timeout from disconnecting us. */
 | 
					 | 
				
			||||||
							client.setActivityTimeout();
 | 
					 | 
				
			||||||
						} else {
 | 
					 | 
				
			||||||
							finish();
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (!parsing_header && inputBuffer.length)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				let offset = body.length - bodyToRead;
 | 
					 | 
				
			||||||
				let length = Math.min(inputBuffer.length, body.length - offset);
 | 
					 | 
				
			||||||
				if (inputBuffer.length > body.length - offset) {
 | 
					 | 
				
			||||||
					body.set(inputBuffer.slice(0, length), offset);
 | 
					 | 
				
			||||||
					inputBuffer = inputBuffer.slice(length);
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					body.set(inputBuffer, offset);
 | 
					 | 
				
			||||||
					inputBuffer = inputBuffer.slice(inputBuffer.length);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				bodyToRead -= length;
 | 
					 | 
				
			||||||
				if (bodyToRead <= 0) {
 | 
					 | 
				
			||||||
					finish();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			client.info = 'EOF';
 | 
					 | 
				
			||||||
			client.close();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let kBacklog = 8;
 | 
					 | 
				
			||||||
let kHost = platform() == 'haiku' ? 'localhost' : '::';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function start() {
 | 
					 | 
				
			||||||
	let socket = new Socket();
 | 
					 | 
				
			||||||
	socket.bind(kHost, tildefriends.http_port).then(function(port) {
 | 
					 | 
				
			||||||
		print("bound to", port);
 | 
					 | 
				
			||||||
		print("checking", tildefriends.args.out_http_port_file);
 | 
					 | 
				
			||||||
		if (tildefriends.args.out_http_port_file) {
 | 
					 | 
				
			||||||
			print("going to write the file");
 | 
					 | 
				
			||||||
			File.writeFile(tildefriends.args.out_http_port_file, port.toString() + '\n').then(function(r) {
 | 
					 | 
				
			||||||
				print("wrote port file", tildefriends.args.out_http_port_file, r);
 | 
					 | 
				
			||||||
			}).catch(function() {
 | 
					 | 
				
			||||||
				print("failed to write port file");
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		let listenResult = socket.listen(kBacklog, async function() {
 | 
					 | 
				
			||||||
			try {
 | 
					 | 
				
			||||||
				let client = await socket.accept();
 | 
					 | 
				
			||||||
				client.noDelay = true;
 | 
					 | 
				
			||||||
				handleConnection(client);
 | 
					 | 
				
			||||||
			} catch (error) {
 | 
					 | 
				
			||||||
				logError("[" + new Date() + "] accept error " + error);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}).catch(function(error) {
 | 
					 | 
				
			||||||
		logError("[" + new Date() + "] bind error " + error);
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (tildefriends.https_port) {
 | 
					 | 
				
			||||||
		let tls = {};
 | 
					 | 
				
			||||||
		let secureSocket = new Socket();
 | 
					 | 
				
			||||||
		secureSocket.bind(kHost, tildefriends.https_port).then(function() {
 | 
					 | 
				
			||||||
			return secureSocket.listen(kBacklog, async function() {
 | 
					 | 
				
			||||||
				try {
 | 
					 | 
				
			||||||
					let client = await secureSocket.accept();
 | 
					 | 
				
			||||||
					client.noDelay = true;
 | 
					 | 
				
			||||||
					client.tls = true;
 | 
					 | 
				
			||||||
					const kCertificatePath = "data/httpd/certificate.pem";
 | 
					 | 
				
			||||||
					const kPrivateKeyPath = "data/httpd/privatekey.pem";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					let 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);
 | 
					 | 
				
			||||||
						let privateKey = utf8Decode(await File.readFile(kPrivateKeyPath));
 | 
					 | 
				
			||||||
						let certificate = utf8Decode(await File.readFile(kCertificatePath));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						tls.context = new TlsContext();
 | 
					 | 
				
			||||||
						tls.context.setPrivateKey(privateKey);
 | 
					 | 
				
			||||||
						tls.context.setCertificate(certificate);
 | 
					 | 
				
			||||||
						tls.certStat = stat[0];
 | 
					 | 
				
			||||||
						tls.keyStat = stat[1];
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					let result = client.startTls(tls.context);
 | 
					 | 
				
			||||||
					handleConnection(client);
 | 
					 | 
				
			||||||
					return result;
 | 
					 | 
				
			||||||
				} catch (error) {
 | 
					 | 
				
			||||||
					logError("[" + new Date() + "] " + error);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		}).catch(function(error) {
 | 
					 | 
				
			||||||
			logError("[" + new Date() + "] bind error " + error);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export { all, start, registerSocketHandler };
 | 
					 | 
				
			||||||
							
								
								
									
										12
									
								
								src/http.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								src/http.c
									
									
									
									
									
								
							@@ -544,7 +544,7 @@ static void _http_on_connection(uv_stream_t* stream, int status)
 | 
				
			|||||||
	http->connections[http->connections_count++] = connection;
 | 
						http->connections[http->connections_count++] = connection;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void tf_http_listen(tf_http_t* http, int port, tf_tls_context_t* tls)
 | 
					int tf_http_listen(tf_http_t* http, int port, tf_tls_context_t* tls)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	tf_http_listener_t* listener = tf_malloc(sizeof(tf_http_listener_t));
 | 
						tf_http_listener_t* listener = tf_malloc(sizeof(tf_http_listener_t));
 | 
				
			||||||
	*listener = (tf_http_listener_t) { .http = http, .tls = tls, .tcp = { .data = listener } };
 | 
						*listener = (tf_http_listener_t) { .http = http, .tls = tls, .tcp = { .data = listener } };
 | 
				
			||||||
@@ -569,6 +569,15 @@ void tf_http_listen(tf_http_t* http, int port, tf_tls_context_t* tls)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int assigned_port = 0;
 | 
				
			||||||
 | 
						if (r == 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							struct sockaddr_storage name = { 0 };
 | 
				
			||||||
 | 
							int size = (int)sizeof(name);
 | 
				
			||||||
 | 
							r = uv_tcp_getsockname(&listener->tcp, (struct sockaddr*)&name, &size);
 | 
				
			||||||
 | 
							assigned_port = ntohs(((struct sockaddr_in*)&name)->sin_port);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (r == 0)
 | 
						if (r == 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		r = uv_listen((uv_stream_t*)&listener->tcp, 16, _http_on_connection);
 | 
							r = uv_listen((uv_stream_t*)&listener->tcp, 16, _http_on_connection);
 | 
				
			||||||
@@ -583,6 +592,7 @@ void tf_http_listen(tf_http_t* http, int port, tf_tls_context_t* tls)
 | 
				
			|||||||
		http->listeners = tf_realloc(http->listeners, sizeof(tf_http_listener_t*) * (http->listeners_count + 1));
 | 
							http->listeners = tf_realloc(http->listeners, sizeof(tf_http_listener_t*) * (http->listeners_count + 1));
 | 
				
			||||||
		http->listeners[http->listeners_count++] = listener;
 | 
							http->listeners[http->listeners_count++] = listener;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return assigned_port;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void tf_http_add_handler(tf_http_t* http, const char* pattern, tf_http_callback_t* callback, void* user_data)
 | 
					void tf_http_add_handler(tf_http_t* http, const char* pattern, tf_http_callback_t* callback, void* user_data)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,7 +36,7 @@ typedef struct _tf_http_request_t
 | 
				
			|||||||
typedef void (tf_http_callback_t)(tf_http_request_t* request);
 | 
					typedef void (tf_http_callback_t)(tf_http_request_t* request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tf_http_t* tf_http_create(uv_loop_t* loop);
 | 
					tf_http_t* tf_http_create(uv_loop_t* loop);
 | 
				
			||||||
void tf_http_listen(tf_http_t* http, int port, tf_tls_context_t* tls);
 | 
					int tf_http_listen(tf_http_t* http, int port, tf_tls_context_t* tls);
 | 
				
			||||||
void tf_http_add_handler(tf_http_t* http, const char* pattern, tf_http_callback_t* callback, void* user_data);
 | 
					void tf_http_add_handler(tf_http_t* http, const char* pattern, tf_http_callback_t* callback, void* user_data);
 | 
				
			||||||
void tf_http_respond(tf_http_request_t* request, int status, const char** headers, int headers_count, const void* body, size_t content_length);
 | 
					void tf_http_respond(tf_http_request_t* request, int status, const char** headers, int headers_count, const void* body, size_t content_length);
 | 
				
			||||||
size_t tf_http_get_body(const tf_http_request_t* request, const void** out_data);
 | 
					size_t tf_http_get_body(const tf_http_request_t* request, const void** out_data);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -293,8 +293,8 @@ static JSValue _httpd_start(JSContext* context, JSValueConst this_val, int argc,
 | 
				
			|||||||
	int port = 0;
 | 
						int port = 0;
 | 
				
			||||||
	JS_ToInt32(context, &port, argv[0]);
 | 
						JS_ToInt32(context, &port, argv[0]);
 | 
				
			||||||
	tf_tls_context_t* tls = tf_tls_context_get(JS_DupValue(context, argv[1]));
 | 
						tf_tls_context_t* tls = tf_tls_context_get(JS_DupValue(context, argv[1]));
 | 
				
			||||||
	tf_http_listen(http, port, tls);
 | 
						int assigned_port = tf_http_listen(http, port, tls);
 | 
				
			||||||
	return JS_UNDEFINED;
 | 
						return JS_NewInt32(context, assigned_port);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void _httpd_finalizer(JSRuntime* runtime, JSValue value)
 | 
					void _httpd_finalizer(JSRuntime* runtime, JSValue value)
 | 
				
			||||||
@@ -343,6 +343,6 @@ void tf_httpd_register(JSContext* context)
 | 
				
			|||||||
	JS_SetPropertyStr(context, httpd, "all", JS_NewCFunction(context, _httpd_all, "all", 2));
 | 
						JS_SetPropertyStr(context, httpd, "all", JS_NewCFunction(context, _httpd_all, "all", 2));
 | 
				
			||||||
	JS_SetPropertyStr(context, httpd, "registerSocketHandler", JS_NewCFunction(context, _httpd_register_socket_handler, "register_socket_handler", 2));
 | 
						JS_SetPropertyStr(context, httpd, "registerSocketHandler", JS_NewCFunction(context, _httpd_register_socket_handler, "register_socket_handler", 2));
 | 
				
			||||||
	JS_SetPropertyStr(context, httpd, "start", JS_NewCFunction(context, _httpd_start, "start", 2));
 | 
						JS_SetPropertyStr(context, httpd, "start", JS_NewCFunction(context, _httpd_start, "start", 2));
 | 
				
			||||||
	JS_SetPropertyStr(context, global, "httpdc", httpd);
 | 
						JS_SetPropertyStr(context, global, "httpd", httpd);
 | 
				
			||||||
	JS_FreeValue(context, global);
 | 
						JS_FreeValue(context, global);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user