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:
parent
4293e75082
commit
b5b6ed8ba5
@ -5,6 +5,7 @@ var gSocketHandlers = [];
|
|||||||
var gBadRequests = {};
|
var gBadRequests = {};
|
||||||
|
|
||||||
const kRequestTimeout = 15000;
|
const kRequestTimeout = 15000;
|
||||||
|
const kStallTimeout = 60000;
|
||||||
|
|
||||||
function logError(error) {
|
function logError(error) {
|
||||||
print("ERROR " + error);
|
print("ERROR " + error);
|
||||||
@ -388,10 +389,12 @@ function allowRequest(client) {
|
|||||||
function handleConnection(client) {
|
function handleConnection(client) {
|
||||||
if (!allowRequest(client)) {
|
if (!allowRequest(client)) {
|
||||||
print('Rejecting client for too many bad requests: ', client.peerName, gBadRequests[client.peerName].reason);
|
print('Rejecting client for too many bad requests: ', client.peerName, gBadRequests[client.peerName].reason);
|
||||||
|
client.info = 'rejected';
|
||||||
client.close();
|
client.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client.info = 'accepted';
|
||||||
var inputBuffer = new Uint8Array(0);
|
var inputBuffer = new Uint8Array(0);
|
||||||
var request;
|
var request;
|
||||||
var headers = {};
|
var headers = {};
|
||||||
@ -399,17 +402,37 @@ function handleConnection(client) {
|
|||||||
var bodyToRead = -1;
|
var bodyToRead = -1;
|
||||||
var body;
|
var body;
|
||||||
var requestCount = -1;
|
var requestCount = -1;
|
||||||
|
var readCount = 0;
|
||||||
|
var isWebsocket = false;
|
||||||
|
|
||||||
function resetTimeout(requestIndex) {
|
function resetTimeout(requestIndex) {
|
||||||
setTimeout(function() {
|
if (isWebsocket) {
|
||||||
if (bodyToRead == -1 && requestCount == requestIndex) {
|
return;
|
||||||
if (requestCount == 0) {
|
}
|
||||||
badRequest(client, 'Timed out waiting for request.');
|
if (bodyToRead == -1) {
|
||||||
} else {
|
setTimeout(function() {
|
||||||
client.close();
|
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);
|
resetTimeout(++requestCount);
|
||||||
@ -421,10 +444,12 @@ function handleConnection(client) {
|
|||||||
lineByLine = true;
|
lineByLine = true;
|
||||||
bodyToRead = -1;
|
bodyToRead = -1;
|
||||||
body = undefined;
|
body = undefined;
|
||||||
|
client.info = 'reset';
|
||||||
resetTimeout(++requestCount);
|
resetTimeout(++requestCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
function finish() {
|
function finish() {
|
||||||
|
client.info = 'finishing';
|
||||||
var requestObject = new Request(request[0], request[1], request[2], headers, body, client);
|
var requestObject = new Request(request[0], request[1], request[2], headers, body, client);
|
||||||
var response = new Response(requestObject, client);
|
var response = new Response(requestObject, client);
|
||||||
try {
|
try {
|
||||||
@ -468,11 +493,14 @@ function handleConnection(client) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
body = new Uint8Array(bodyToRead);
|
body = new Uint8Array(bodyToRead);
|
||||||
|
client.info = 'waiting for body';
|
||||||
return true;
|
return true;
|
||||||
} else if (headers["connection"]
|
} else if (headers["connection"]
|
||||||
&& headers["connection"].toLowerCase().split(",").map(x => x.trim()).indexOf("upgrade") != -1
|
&& headers["connection"].toLowerCase().split(",").map(x => x.trim()).indexOf("upgrade") != -1
|
||||||
&& headers["upgrade"]
|
&& headers["upgrade"]
|
||||||
&& headers["upgrade"].toLowerCase() == "websocket") {
|
&& headers["upgrade"].toLowerCase() == "websocket") {
|
||||||
|
isWebsocket = true;
|
||||||
|
client.info = 'websocket';
|
||||||
var requestObject = new Request(request[0], request[1], request[2], headers, body, client);
|
var requestObject = new Request(request[0], request[1], request[2], headers, body, client);
|
||||||
var response = new Response(requestObject, client);
|
var response = new Response(requestObject, client);
|
||||||
handleWebSocketRequest(requestObject, response, client);
|
handleWebSocketRequest(requestObject, response, client);
|
||||||
@ -504,7 +532,11 @@ function handleConnection(client) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
client.read(function(data) {
|
client.read(function(data) {
|
||||||
|
readCount++;
|
||||||
if (data) {
|
if (data) {
|
||||||
|
if (bodyToRead != -1 && !isWebsocket) {
|
||||||
|
resetTimeout(requestCount);
|
||||||
|
}
|
||||||
const kMaxLineLength = 4096;
|
const kMaxLineLength = 4096;
|
||||||
var newBuffer = new Uint8Array(inputBuffer.length + data.length);
|
var newBuffer = new Uint8Array(inputBuffer.length + data.length);
|
||||||
newBuffer.set(inputBuffer, 0);
|
newBuffer.set(inputBuffer, 0);
|
||||||
@ -537,6 +569,9 @@ function handleConnection(client) {
|
|||||||
inputBuffer = new Uint8Array(0);
|
inputBuffer = new Uint8Array(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
client.info = 'EOF';
|
||||||
|
client.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ typedef struct _socket_t {
|
|||||||
JSValue _onConnect;
|
JSValue _onConnect;
|
||||||
JSValue _onRead;
|
JSValue _onRead;
|
||||||
JSValue _onError;
|
JSValue _onError;
|
||||||
|
JSValue _info;
|
||||||
uint64_t created_ms;
|
uint64_t created_ms;
|
||||||
} socket_t;
|
} 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_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_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_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 JSValue _sockets_get(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
|
||||||
|
|
||||||
static void _socket_onClose(uv_handle_t* handle);
|
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->_onConnect, mark_func);
|
||||||
JS_MarkValue(runtime, socket->_onRead, mark_func);
|
JS_MarkValue(runtime, socket->_onRead, mark_func);
|
||||||
JS_MarkValue(runtime, socket->_onError, 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_DefinePropertyGetSet(context, object, atom, get_no_delay, set_no_delay, 0);
|
||||||
JS_FreeAtom(context, atom);
|
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;
|
++_open_count;
|
||||||
uv_tcp_init(tf_task_get_loop(socket->_task), &socket->_socket);
|
uv_tcp_init(tf_task_get_loop(socket->_task), &socket->_socket);
|
||||||
socket->_socket.data = socket;
|
socket->_socket.data = socket;
|
||||||
@ -1065,6 +1073,15 @@ JSValue _socket_setNoDelay(JSContext* context, JSValueConst this_val, int argc,
|
|||||||
return JS_UNDEFINED;
|
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 _sockets_get(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||||
{
|
{
|
||||||
JSValue array = JS_NewArray(context);
|
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, "connected", JS_NewBool(context, s->_connected));
|
||||||
JS_SetPropertyStr(context, entry, "tls", JS_NewBool(context, s->_tls != NULL));
|
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, "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);
|
JS_SetPropertyUint32(context, array, i, entry);
|
||||||
}
|
}
|
||||||
return array;
|
return array;
|
||||||
|
Loading…
Reference in New Issue
Block a user