forked from cory/tildefriends
		
	A bit closer to websockets.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4696 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		@@ -203,6 +203,7 @@ function handleWebSocketRequest(request, response, client) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (client) {
 | 
			
		||||
		response.send = function(message, opCode) {
 | 
			
		||||
			if (opCode === undefined) {
 | 
			
		||||
				opCode = 0x2;
 | 
			
		||||
@@ -243,10 +244,12 @@ function handleWebSocketRequest(request, response, client) {
 | 
			
		||||
				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);
 | 
			
		||||
@@ -328,6 +331,7 @@ function handleWebSocketRequest(request, response, client) {
 | 
			
		||||
			logError(client.peerName + " - - [" + new Date() + "] " + error);
 | 
			
		||||
			response.onError(error);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let headers = {
 | 
			
		||||
		"Upgrade": "websocket",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								src/http.c
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/http.c
									
									
									
									
									
								
							@@ -521,6 +521,23 @@ static void _http_on_shutdown(uv_shutdown_t* request, int status)
 | 
			
		||||
	request->data = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _http_write(tf_http_connection_t* connection, const void* data, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	uv_write_t* write = tf_malloc(sizeof(uv_write_t) + size);
 | 
			
		||||
	*write = (uv_write_t) { .data = connection };
 | 
			
		||||
	memcpy(write + 1, data, size);
 | 
			
		||||
	int r = uv_write(write, (uv_stream_t*)&connection->tcp, &(uv_buf_t) { .base = (void*)(write + 1), .len = size }, 1, _http_on_write);
 | 
			
		||||
	if (r)
 | 
			
		||||
	{
 | 
			
		||||
		tf_printf("uv_write: %s\n", uv_strerror(r));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tf_http_request_send(tf_http_request_t* request, const void* data, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	_http_write(request->connection, data, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tf_http_respond(tf_http_request_t* request, int status, const char** headers, int headers_count, const void* body, size_t content_length)
 | 
			
		||||
{
 | 
			
		||||
	const char* status_text = _http_status_text(status);
 | 
			
		||||
 
 | 
			
		||||
@@ -46,3 +46,4 @@ void tf_http_destroy(tf_http_t* http);
 | 
			
		||||
void tf_http_request_ref(tf_http_request_t* request);
 | 
			
		||||
void tf_http_request_release(tf_http_request_t* request);
 | 
			
		||||
const char* tf_http_request_get_header(tf_http_request_t* request, const char* name);
 | 
			
		||||
void tf_http_request_send(tf_http_request_t* request, const void* data, size_t size);
 | 
			
		||||
 
 | 
			
		||||
@@ -100,14 +100,62 @@ static JSValue _httpd_response_end(JSContext* context, JSValueConst this_val, in
 | 
			
		||||
	return JS_UNDEFINED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static JSValue _httpd_response_send(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
 | 
			
		||||
{
 | 
			
		||||
	tf_http_request_t* request = JS_GetOpaque(this_val, _httpd_request_class_id);
 | 
			
		||||
	int opcode = 0x1;
 | 
			
		||||
	JS_ToInt32(context, &opcode, argv[1]);
 | 
			
		||||
	uint64_t length = 0;
 | 
			
		||||
	size_t length_size = 0;
 | 
			
		||||
	const char* message = JS_ToCStringLen(context, &length_size, argv[0]);
 | 
			
		||||
	length = length_size;
 | 
			
		||||
	uint8_t* copy = tf_malloc(length + 16);
 | 
			
		||||
	bool fin = true;
 | 
			
		||||
	size_t header = 1;
 | 
			
		||||
	copy[0] = (fin ? (1 << 7) : 0) | (opcode & 0xf);
 | 
			
		||||
	if (length < 126)
 | 
			
		||||
	{
 | 
			
		||||
		copy[1] = length;
 | 
			
		||||
		header += 2;
 | 
			
		||||
	}
 | 
			
		||||
	else if (length < (1 << 16))
 | 
			
		||||
	{
 | 
			
		||||
		copy[1] = 126;
 | 
			
		||||
		copy[2] = (length >> 8) & 0xff;
 | 
			
		||||
		copy[3] = (length >> 0) & 0xff;
 | 
			
		||||
		header += 4;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		uint32_t high = (length >> 32) & 0xffffffff;
 | 
			
		||||
		uint32_t low = (length >> 0) & 0xffffffff;
 | 
			
		||||
		copy[1] = 127;
 | 
			
		||||
		copy[2] = (high >> 24) & 0xff;
 | 
			
		||||
		copy[3] = (high >> 16) & 0xff;
 | 
			
		||||
		copy[4] = (high >> 8) & 0xff;
 | 
			
		||||
		copy[5] = (high >> 0) & 0xff;
 | 
			
		||||
		copy[6] = (low >> 24) & 0xff;
 | 
			
		||||
		copy[7] = (low >> 16) & 0xff;
 | 
			
		||||
		copy[8] = (low >> 8) & 0xff;
 | 
			
		||||
		copy[9] = (low >> 0) & 0xff;
 | 
			
		||||
		header += 10;
 | 
			
		||||
	}
 | 
			
		||||
	memcpy(copy + header, message, length);
 | 
			
		||||
	tf_printf("SEND [%.*s]\n", (int)length, message);
 | 
			
		||||
	tf_http_request_send(request, copy, header + length);
 | 
			
		||||
	tf_free(copy);
 | 
			
		||||
	JS_FreeCString(context, message);
 | 
			
		||||
	return JS_UNDEFINED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _httpd_callback(tf_http_request_t* request)
 | 
			
		||||
{
 | 
			
		||||
#if 0
 | 
			
		||||
	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");
 | 
			
		||||
		tf_printf("\n%s\n%s\n%s\n\n", header_connection, header_upgrade, header_sec_websocket_key);
 | 
			
		||||
		if (header_connection &&
 | 
			
		||||
			header_upgrade &&
 | 
			
		||||
			header_sec_websocket_key &&
 | 
			
		||||
@@ -136,9 +184,9 @@ static void _httpd_callback(tf_http_request_t* request)
 | 
			
		||||
				!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);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	http_handler_data_t* data = request->user_data;
 | 
			
		||||
	JSContext* context = data->context;
 | 
			
		||||
@@ -169,6 +217,7 @@ static void _httpd_callback(tf_http_request_t* request)
 | 
			
		||||
	JS_SetOpaque(response_object, request);
 | 
			
		||||
	JS_SetPropertyStr(context, response_object, "writeHead", JS_NewCFunction(context, _httpd_response_write_head, "writeHead", 2));
 | 
			
		||||
	JS_SetPropertyStr(context, response_object, "end", JS_NewCFunction(context, _httpd_response_end, "end", 1));
 | 
			
		||||
	JS_SetPropertyStr(context, response_object, "send", JS_NewCFunction(context, _httpd_response_send, "send", 2));
 | 
			
		||||
	JSValue args[] =
 | 
			
		||||
	{
 | 
			
		||||
		request_object,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user