forked from cory/tildefriends
		
	Trying harder still to curb stale connections.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3900 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		@@ -5,6 +5,7 @@ var gSocketHandlers = [];
 | 
			
		||||
var gBadRequests = {};
 | 
			
		||||
 | 
			
		||||
const kRequestTimeout = 15000;
 | 
			
		||||
const kStallTimeout = 60000;
 | 
			
		||||
 | 
			
		||||
function logError(error) {
 | 
			
		||||
	print("ERROR " + error);
 | 
			
		||||
@@ -388,10 +389,12 @@ function allowRequest(client) {
 | 
			
		||||
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';
 | 
			
		||||
	var inputBuffer = new Uint8Array(0);
 | 
			
		||||
	var request;
 | 
			
		||||
	var headers = {};
 | 
			
		||||
@@ -399,17 +402,37 @@ function handleConnection(client) {
 | 
			
		||||
	var bodyToRead = -1;
 | 
			
		||||
	var body;
 | 
			
		||||
	var requestCount = -1;
 | 
			
		||||
	var readCount = 0;
 | 
			
		||||
	var isWebsocket = false;
 | 
			
		||||
 | 
			
		||||
	function resetTimeout(requestIndex) {
 | 
			
		||||
		setTimeout(function() {
 | 
			
		||||
			if (bodyToRead == -1 && requestCount == requestIndex) {
 | 
			
		||||
				if (requestCount == 0) {
 | 
			
		||||
					badRequest(client, 'Timed out waiting for request.');
 | 
			
		||||
				} else {
 | 
			
		||||
					client.close();
 | 
			
		||||
		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();
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}, kRequestTimeout);
 | 
			
		||||
			}, kRequestTimeout);
 | 
			
		||||
		} else {
 | 
			
		||||
			var lastReadCount = readCount;
 | 
			
		||||
			setTimeout(function() {
 | 
			
		||||
				if (readCount == lastReadCount) {
 | 
			
		||||
					client.info = 'stalled';
 | 
			
		||||
					if (requestCount == 0) {
 | 
			
		||||
						badRequest(client, 'Request stalled.');
 | 
			
		||||
					} else {
 | 
			
		||||
						client.close();
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}, kStallTimeout);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resetTimeout(++requestCount);
 | 
			
		||||
@@ -421,10 +444,12 @@ function handleConnection(client) {
 | 
			
		||||
		lineByLine = true;
 | 
			
		||||
		bodyToRead = -1;
 | 
			
		||||
		body = undefined;
 | 
			
		||||
		client.info = 'reset';
 | 
			
		||||
		resetTimeout(++requestCount);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function finish() {
 | 
			
		||||
		client.info = 'finishing';
 | 
			
		||||
		var requestObject = new Request(request[0], request[1], request[2], headers, body, client);
 | 
			
		||||
		var response = new Response(requestObject, client);
 | 
			
		||||
		try {
 | 
			
		||||
@@ -468,11 +493,14 @@ function handleConnection(client) {
 | 
			
		||||
						return false;
 | 
			
		||||
					}
 | 
			
		||||
					body = new Uint8Array(bodyToRead);
 | 
			
		||||
					client.info = 'waiting for body';
 | 
			
		||||
					return true;
 | 
			
		||||
				} 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';
 | 
			
		||||
					var requestObject = new Request(request[0], request[1], request[2], headers, body, client);
 | 
			
		||||
					var response = new Response(requestObject, client);
 | 
			
		||||
					handleWebSocketRequest(requestObject, response, client);
 | 
			
		||||
@@ -504,7 +532,11 @@ function handleConnection(client) {
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	client.read(function(data) {
 | 
			
		||||
		readCount++;
 | 
			
		||||
		if (data) {
 | 
			
		||||
			if (bodyToRead != -1 && !isWebsocket) {
 | 
			
		||||
				resetTimeout(requestCount);
 | 
			
		||||
			}
 | 
			
		||||
			const kMaxLineLength = 4096;
 | 
			
		||||
			var newBuffer = new Uint8Array(inputBuffer.length + data.length);
 | 
			
		||||
			newBuffer.set(inputBuffer, 0);
 | 
			
		||||
@@ -537,6 +569,9 @@ function handleConnection(client) {
 | 
			
		||||
					inputBuffer = new Uint8Array(0);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			client.info = 'EOF';
 | 
			
		||||
			client.close();
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,7 @@ typedef struct _socket_t {
 | 
			
		||||
	JSValue _onConnect;
 | 
			
		||||
	JSValue _onRead;
 | 
			
		||||
	JSValue _onError;
 | 
			
		||||
	JSValue _info;
 | 
			
		||||
	uint64_t created_ms;
 | 
			
		||||
} socket_t;
 | 
			
		||||
 | 
			
		||||
@@ -67,6 +68,7 @@ static JSValue _socket_getPeerName(JSContext* context, JSValueConst this_val, in
 | 
			
		||||
static JSValue _socket_getPeerCertificate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
 | 
			
		||||
static JSValue _socket_getNoDelay(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
 | 
			
		||||
static JSValue _socket_setNoDelay(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
 | 
			
		||||
static JSValue _socket_setInfo(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
 | 
			
		||||
static JSValue _sockets_get(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
 | 
			
		||||
 | 
			
		||||
static void _socket_onClose(uv_handle_t* handle);
 | 
			
		||||
@@ -122,6 +124,7 @@ static void _socket_gc_mark(JSRuntime* runtime, JSValueConst value, JS_MarkFunc
 | 
			
		||||
		JS_MarkValue(runtime, socket->_onConnect, mark_func);
 | 
			
		||||
		JS_MarkValue(runtime, socket->_onRead, mark_func);
 | 
			
		||||
		JS_MarkValue(runtime, socket->_onError, mark_func);
 | 
			
		||||
		JS_MarkValue(runtime, socket->_info, mark_func);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -212,6 +215,11 @@ socket_t* _socket_create_internal(JSContext* context)
 | 
			
		||||
	JS_DefinePropertyGetSet(context, object, atom, get_no_delay, set_no_delay, 0);
 | 
			
		||||
	JS_FreeAtom(context, atom);
 | 
			
		||||
 | 
			
		||||
	atom = JS_NewAtom(context, "info");
 | 
			
		||||
	JSValue set_info = JS_NewCFunction(context, _socket_setInfo, "setInfo", 1);
 | 
			
		||||
	JS_DefinePropertyGetSet(context, object, atom, JS_UNDEFINED, set_info, 0);
 | 
			
		||||
	JS_FreeAtom(context, atom);
 | 
			
		||||
 | 
			
		||||
	++_open_count;
 | 
			
		||||
	uv_tcp_init(tf_task_get_loop(socket->_task), &socket->_socket);
 | 
			
		||||
	socket->_socket.data = socket;
 | 
			
		||||
@@ -1065,6 +1073,15 @@ JSValue _socket_setNoDelay(JSContext* context, JSValueConst this_val, int argc,
 | 
			
		||||
	return JS_UNDEFINED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
JSValue _socket_setInfo(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
 | 
			
		||||
{
 | 
			
		||||
	socket_t* socket = JS_GetOpaque(this_val, _classId);
 | 
			
		||||
	JSValue old = socket->_info;
 | 
			
		||||
	socket->_info = JS_DupValue(context, argv[0]);
 | 
			
		||||
	JS_FreeValue(context, old);
 | 
			
		||||
	return JS_UNDEFINED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
JSValue _sockets_get(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
 | 
			
		||||
{
 | 
			
		||||
	JSValue array = JS_NewArray(context);
 | 
			
		||||
@@ -1077,6 +1094,7 @@ JSValue _sockets_get(JSContext* context, JSValueConst this_val, int argc, JSValu
 | 
			
		||||
		JS_SetPropertyStr(context, entry, "connected", JS_NewBool(context, s->_connected));
 | 
			
		||||
		JS_SetPropertyStr(context, entry, "tls", JS_NewBool(context, s->_tls != NULL));
 | 
			
		||||
		JS_SetPropertyStr(context, entry, "age_seconds", JS_NewFloat64(context, (uv_now(tf_task_get_loop(s->_task)) - s->created_ms) / 1000.f));
 | 
			
		||||
		JS_SetPropertyStr(context, entry, "info", JS_DupValue(context, s->_info));
 | 
			
		||||
		JS_SetPropertyUint32(context, array, i, entry);
 | 
			
		||||
	}
 | 
			
		||||
	return array;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user