forked from cory/tildefriends
Some quick http refactors to make websockets less magic.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4705 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
105
src/httpd.js.c
105
src/httpd.js.c
@ -162,44 +162,8 @@ static void _httpd_message_callback(tf_http_request_t* request, int op_code, con
|
||||
JS_FreeValue(context, on_message);
|
||||
}
|
||||
|
||||
static void _httpd_callback(tf_http_request_t* request)
|
||||
static void _httpd_callback_internal(tf_http_request_t* request, bool is_websocket)
|
||||
{
|
||||
if (request->flags & k_tf_http_handler_flag_websocket)
|
||||
{
|
||||
const char* header_connection = tf_http_request_get_header(request, "connection");
|
||||
const char* header_upgrade = tf_http_request_get_header(request, "upgrade");
|
||||
const char* header_sec_websocket_key = tf_http_request_get_header(request, "sec-websocket-key");
|
||||
if (header_connection &&
|
||||
header_upgrade &&
|
||||
header_sec_websocket_key &&
|
||||
strstr(header_connection, "Upgrade") &&
|
||||
strcasecmp(header_upgrade, "websocket") == 0)
|
||||
{
|
||||
static const char* k_magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||
size_t key_length = strlen(header_sec_websocket_key);
|
||||
size_t size = key_length + 36;
|
||||
uint8_t* key_magic = alloca(size);
|
||||
memcpy(key_magic, header_sec_websocket_key, key_length);
|
||||
memcpy(key_magic + key_length, k_magic, 36);
|
||||
uint8_t digest[20];
|
||||
SHA1(key_magic, size, digest);
|
||||
char key[41] = { 0 };
|
||||
tf_base64_encode(digest, sizeof(digest), key, sizeof(key));
|
||||
enum { k_headers_count = 4 };
|
||||
const char* headers[k_headers_count * 2] =
|
||||
{
|
||||
"Upgrade", "websocket",
|
||||
"Connection", "Upgrade",
|
||||
"Sec-WebSocket-Accept", key,
|
||||
"Sec-WebSocket-Version", "13",
|
||||
};
|
||||
bool send_version =
|
||||
!tf_http_request_get_header(request, "sec-websocket-version") ||
|
||||
strcmp(tf_http_request_get_header(request, "sec-websocket-version"), "13") != 0;
|
||||
tf_http_respond(request, 101, headers, send_version ? k_headers_count : (k_headers_count - 1), NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
http_handler_data_t* data = request->user_data;
|
||||
JSContext* context = data->context;
|
||||
JSValue request_object = JS_NewObject(context);
|
||||
@ -238,11 +202,66 @@ static void _httpd_callback(tf_http_request_t* request)
|
||||
JSValue response = JS_Call(context, data->callback, JS_UNDEFINED, 2, args);
|
||||
tf_util_report_error(context, response);
|
||||
JS_FreeValue(context, request_object);
|
||||
//JS_FreeValue(context, response_object);
|
||||
JS_FreeValue(context, response);
|
||||
request->on_message = _httpd_message_callback;
|
||||
request->context = context;
|
||||
request->user_data = JS_VALUE_GET_PTR(response_object);
|
||||
|
||||
if (is_websocket)
|
||||
{
|
||||
request->on_message = _httpd_message_callback;
|
||||
request->context = context;
|
||||
request->user_data = JS_VALUE_GET_PTR(response_object);
|
||||
}
|
||||
else
|
||||
{
|
||||
JS_FreeValue(context, response_object);
|
||||
}
|
||||
}
|
||||
|
||||
static void _httpd_callback(tf_http_request_t* request)
|
||||
{
|
||||
_httpd_callback_internal(request, false);
|
||||
}
|
||||
|
||||
static void _httpd_websocket_callback(tf_http_request_t* request)
|
||||
{
|
||||
const char* header_connection = tf_http_request_get_header(request, "connection");
|
||||
const char* header_upgrade = tf_http_request_get_header(request, "upgrade");
|
||||
const char* header_sec_websocket_key = tf_http_request_get_header(request, "sec-websocket-key");
|
||||
if (header_connection &&
|
||||
header_upgrade &&
|
||||
header_sec_websocket_key &&
|
||||
strstr(header_connection, "Upgrade") &&
|
||||
strcasecmp(header_upgrade, "websocket") == 0)
|
||||
{
|
||||
static const char* k_magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||
size_t key_length = strlen(header_sec_websocket_key);
|
||||
size_t size = key_length + 36;
|
||||
uint8_t* key_magic = alloca(size);
|
||||
memcpy(key_magic, header_sec_websocket_key, key_length);
|
||||
memcpy(key_magic + key_length, k_magic, 36);
|
||||
uint8_t digest[20];
|
||||
SHA1(key_magic, size, digest);
|
||||
char key[41] = { 0 };
|
||||
tf_base64_encode(digest, sizeof(digest), key, sizeof(key));
|
||||
enum { k_headers_count = 4 };
|
||||
const char* headers[k_headers_count * 2] =
|
||||
{
|
||||
"Upgrade", "websocket",
|
||||
"Connection", "Upgrade",
|
||||
"Sec-WebSocket-Accept", key,
|
||||
"Sec-WebSocket-Version", "13",
|
||||
};
|
||||
bool send_version =
|
||||
!tf_http_request_get_header(request, "sec-websocket-version") ||
|
||||
strcmp(tf_http_request_get_header(request, "sec-websocket-version"), "13") != 0;
|
||||
tf_http_request_websocket_upgrade(request);
|
||||
tf_http_respond(request, 101, headers, send_version ? k_headers_count : (k_headers_count - 1), NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tf_http_respond(request, 400, NULL, 0, NULL, 0);
|
||||
}
|
||||
|
||||
_httpd_callback_internal(request, true);
|
||||
}
|
||||
|
||||
static JSValue _httpd_all(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||
@ -251,7 +270,7 @@ static JSValue _httpd_all(JSContext* context, JSValueConst this_val, int argc, J
|
||||
const char* pattern = JS_ToCString(context, argv[0]);
|
||||
http_handler_data_t* data = tf_malloc(sizeof(http_handler_data_t));
|
||||
*data = (http_handler_data_t) { .context = context, .callback = JS_DupValue(context, argv[1]) };
|
||||
tf_http_add_handler(http, pattern, k_tf_http_handler_flag_none, _httpd_callback, data);
|
||||
tf_http_add_handler(http, pattern, _httpd_callback, data);
|
||||
JS_FreeCString(context, pattern);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
@ -262,7 +281,7 @@ static JSValue _httpd_register_socket_handler(JSContext* context, JSValueConst t
|
||||
const char* pattern = JS_ToCString(context, argv[0]);
|
||||
http_handler_data_t* data = tf_malloc(sizeof(http_handler_data_t));
|
||||
*data = (http_handler_data_t) { .context = context, .callback = JS_DupValue(context, argv[1]) };
|
||||
tf_http_add_handler(http, pattern, k_tf_http_handler_flag_websocket, _httpd_callback, data);
|
||||
tf_http_add_handler(http, pattern, _httpd_websocket_callback, data);
|
||||
JS_FreeCString(context, pattern);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
Reference in New Issue
Block a user