json-rpc-test-server: fix some outstanding issues
This commit is contained in:
		
							parent
							
								
									df38bcf775
								
							
						
					
					
						commit
						1840ac795e
					
				| @ -128,8 +128,8 @@ struct fcgi_muxer | ||||
| 
 | ||||
| 	// Virtual method callbacks:
 | ||||
| 
 | ||||
| 	/// Write data to the underlying transport
 | ||||
| 	void (*write_cb) (struct fcgi_muxer *, const void *data, size_t len); | ||||
| 	/// Write data to the underlying transport.  Assumes ownership of data.
 | ||||
| 	void (*write_cb) (struct fcgi_muxer *, void *data, size_t len); | ||||
| 
 | ||||
| 	/// Close the underlying transport.  You are allowed to destroy the muxer
 | ||||
| 	/// directly from within the callback.
 | ||||
| @ -171,9 +171,7 @@ fcgi_muxer_send (struct fcgi_muxer *self, | ||||
| 	str_append_data (&message, data, len); | ||||
| 	str_append_data (&message, zeroes, padding); | ||||
| 
 | ||||
| 	// XXX: we should probably have another write_cb that assumes ownership
 | ||||
| 	self->write_cb (self, message.str, message.len); | ||||
| 	str_free (&message); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -250,14 +248,15 @@ fcgi_request_write (struct fcgi_request *self, const void *data, size_t len) | ||||
| /// Mark the request as done.  Returns false if the underlying transport
 | ||||
| /// should be closed, this being the last request.
 | ||||
| static bool | ||||
| fcgi_request_finish (struct fcgi_request *self) | ||||
| fcgi_request_finish (struct fcgi_request *self, int32_t status_code) | ||||
| { | ||||
| 	fcgi_request_flush (self); | ||||
| 	fcgi_muxer_send (self->muxer, FCGI_STDOUT, self->request_id, NULL, 0); | ||||
| 
 | ||||
| 	// The appStatus is mostly ignored by web servers and it's not even clear
 | ||||
| 	// whether it should be a signed value like it is on Unix, or not
 | ||||
| 	fcgi_muxer_send_end_request (self->muxer, self->request_id, | ||||
| 		0 /* TODO app_status, although ignored */, | ||||
| 		FCGI_REQUEST_COMPLETE /* TODO protocol_status, may be different */); | ||||
| 		status_code, FCGI_REQUEST_COMPLETE); | ||||
| 
 | ||||
| 	bool should_close = !(self->flags & FCGI_KEEP_CONN); | ||||
| 
 | ||||
| @ -288,7 +287,7 @@ fcgi_request_push_params | ||||
| 
 | ||||
| 		self->state = FCGI_REQUEST_STDIN; | ||||
| 		if (!self->muxer->request_start_cb (self)) | ||||
| 			return fcgi_request_finish (self); | ||||
| 			return fcgi_request_finish (self, EXIT_SUCCESS); | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
| @ -424,7 +423,7 @@ fcgi_muxer_on_abort_request | ||||
| 		return true;  // We might have just rejected it
 | ||||
| 	} | ||||
| 
 | ||||
| 	return fcgi_request_finish (request); | ||||
| 	return fcgi_request_finish (request, EXIT_FAILURE); | ||||
| } | ||||
| 
 | ||||
| static bool | ||||
| @ -730,13 +729,19 @@ ws_handler_on_control_close | ||||
| 		reason = xstrdup (""); | ||||
| 
 | ||||
| 	if (close_code < 1000 || close_code > 4999) | ||||
| 		// XXX: invalid close code: maybe we should fail the connection instead
 | ||||
| 		// XXX: invalid close code: maybe we should fail the connection instead,
 | ||||
| 		//   although the specification doesn't say anything about this case
 | ||||
| 		close_code = WS_STATUS_PROTOCOL_ERROR; | ||||
| 
 | ||||
| 	// Update the now potentially different close_code (lol const)
 | ||||
| 	if (parser->payload_len >= 2) | ||||
| 	{ | ||||
| 		parser->input.str[0] = close_code >> 8; | ||||
| 		parser->input.str[1] = close_code; | ||||
| 	} | ||||
| 
 | ||||
| 	if (self->state == WS_HANDLER_OPEN) | ||||
| 	{ | ||||
| 		// Close initiated by the client
 | ||||
| 		// FIXME: not sending the potentially different close_code
 | ||||
| 		ws_handler_send_control (self, WS_OPCODE_CLOSE, | ||||
| 			parser->input.str, parser->payload_len); | ||||
| 
 | ||||
| @ -745,6 +750,7 @@ ws_handler_on_control_close | ||||
| 			self->on_close (self, close_code, reason); | ||||
| 	} | ||||
| 	else | ||||
| 		// Close initiated by us, flush the write queue and close the transport
 | ||||
| 		self->state = WS_HANDLER_FLUSHING; | ||||
| 
 | ||||
| 	free (reason); | ||||
| @ -817,7 +823,7 @@ ws_handler_on_ping_timer (EV_P_ ev_timer *watcher, int revents) | ||||
| 
 | ||||
| 	struct ws_handler *self = watcher->data; | ||||
| 	if (!self->received_pong) | ||||
| 		ws_handler_fail_connection (self, 4000); | ||||
| 		ws_handler_fail_connection (self, 4000 /* private use code */); | ||||
| 	else | ||||
| 	{ | ||||
| 		// TODO: be an annoying server and send a nonce in the data
 | ||||
| @ -1437,10 +1443,6 @@ json_rpc_handler_info_cmp (const void *first, const void *second) | ||||
| 		((struct json_rpc_handler_info *) second)->method_name); | ||||
| } | ||||
| 
 | ||||
| // TODO: a method that sends a response after a certain number of seconds.
 | ||||
| //   This has to be owned by the server context as a background job that
 | ||||
| //   removes itself upon completion.
 | ||||
| 
 | ||||
| static json_t * | ||||
| json_rpc_ping (struct server_context *ctx, json_t *params) | ||||
| { | ||||
| @ -1574,7 +1576,7 @@ struct request | ||||
| 
 | ||||
| 	/// Callback to close the CGI response, simulates end of program execution.
 | ||||
| 	/// CALLING THIS MAY CAUSE THE REQUEST TO BE DESTROYED.
 | ||||
| 	void (*close_cb) (struct request *); | ||||
| 	void (*finish_cb) (struct request *); | ||||
| }; | ||||
| 
 | ||||
| /// An interface to detect and handle specific kinds of CGI requests.
 | ||||
| @ -1627,7 +1629,7 @@ request_write (struct request *self, const void *data, size_t len) | ||||
| static void | ||||
| request_finish (struct request *self) | ||||
| { | ||||
| 	self->close_cb (self); | ||||
| 	self->finish_cb (self); | ||||
| } | ||||
| 
 | ||||
| /// Starts processing a request.  Returns false if no further action is to be
 | ||||
| @ -1746,16 +1748,15 @@ struct request_handler g_request_handler_json_rpc = | ||||
| 
 | ||||
| // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | ||||
| 
 | ||||
| /// Make a URL path canonical.  The resulting path always begins with a slash,
 | ||||
| /// and any trailing slashes are lost.
 | ||||
| static char * | ||||
| canonicalize_url_path (const char *path) | ||||
| { | ||||
| 	// XXX: this strips any slashes at the end
 | ||||
| 	struct strv v = strv_make (); | ||||
| 	cstr_split (path, "/", true, &v); | ||||
| 
 | ||||
| 	struct strv canonical = strv_make (); | ||||
| 
 | ||||
| 	// So that the joined path always begins with a slash
 | ||||
| 	strv_append (&canonical, ""); | ||||
| 
 | ||||
| 	for (size_t i = 0; i < v.len; i++) | ||||
| @ -1896,9 +1897,14 @@ request_handler_static_push | ||||
| 	(void) request; | ||||
| 	(void) data; | ||||
| 
 | ||||
| 	// Aborting on content; we shouldn't receive any (GET)
 | ||||
| 	// FIXME: there should at least be some indication of this happening
 | ||||
| 	return len == 0; | ||||
| 	if (len == 0) | ||||
| 		return true; | ||||
| 
 | ||||
| 	// Aborting on content; we shouldn't receive any (GET).
 | ||||
| 	// In fact, we will only get here once try_handle stops dumping everything
 | ||||
| 	// into the write queue at once.
 | ||||
| 	print_debug ("the static file handler received data but shouldn't have"); | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -1977,19 +1983,32 @@ client_destroy (struct client *self) | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| client_write (struct client *self, const void *data, size_t len) | ||||
| client_write_unsafe (struct client *self, void *data, size_t len) | ||||
| { | ||||
| 	if (!soft_assert (!self->flushing) || len == 0) | ||||
| 		return; | ||||
| 
 | ||||
| 	struct write_req *req = xcalloc (1, sizeof *req); | ||||
| 	req->data.iov_base = memcpy (xmalloc (len), data, len); | ||||
| 	req->data.iov_base = data; | ||||
| 	req->data.iov_len = len; | ||||
| 
 | ||||
| 	write_queue_add (&self->write_queue, req); | ||||
| 	ev_io_start (EV_DEFAULT_ &self->write_watcher); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| client_write_owned (struct client *self, void *data, size_t len) | ||||
| { | ||||
| 	if (soft_assert (!self->flushing) && len != 0) | ||||
| 		client_write_unsafe (self, data, len); | ||||
| 	else | ||||
| 		free (data); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| client_write (struct client *self, const void *data, size_t len) | ||||
| { | ||||
| 	if (soft_assert (!self->flushing) && len != 0) | ||||
| 		client_write_unsafe (self, memcpy (xmalloc (len), data, len), len); | ||||
| } | ||||
| 
 | ||||
| /// Half-close the connection from our side once the write_queue is flushed.
 | ||||
| /// It is the caller's responsibility to destroy the connection upon EOF.
 | ||||
| // XXX: or we might change on_client_readable to do it anyway, seems safe
 | ||||
| @ -2152,14 +2171,16 @@ client_fcgi_request_write_cb (struct request *req, const void *data, size_t len) | ||||
| 	fcgi_request_write (self->fcgi_request, data, len); | ||||
| } | ||||
| 
 | ||||
| // XXX: it should be possible to pass a specific status code but we'd have to
 | ||||
| //   allow it in multiple places over this code base, notably request_push()
 | ||||
| static void | ||||
| client_fcgi_request_close_cb (struct request *req) | ||||
| client_fcgi_request_finish_cb (struct request *req) | ||||
| { | ||||
| 	FIND_CONTAINER (self, req, struct client_fcgi_request, request); | ||||
| 	struct fcgi_muxer *muxer = self->fcgi_request->muxer; | ||||
| 	// No more data to send, terminate the substream/request,
 | ||||
| 	// and also the transport if the client didn't specifically ask to keep it
 | ||||
| 	if (!fcgi_request_finish (self->fcgi_request)) | ||||
| 	if (!fcgi_request_finish (self->fcgi_request, EXIT_SUCCESS)) | ||||
| 		muxer->close_cb (muxer); | ||||
| } | ||||
| 
 | ||||
| @ -2172,9 +2193,9 @@ client_fcgi_request_start (struct fcgi_request *fcgi_request) | ||||
| 		fcgi_request->handler_data = xcalloc (1, sizeof *request); | ||||
| 	request->fcgi_request = fcgi_request; | ||||
| 	request_init (&request->request); | ||||
| 	request->request.ctx = ev_userdata (EV_DEFAULT); | ||||
| 	request->request.write_cb = client_fcgi_request_write_cb; | ||||
| 	request->request.close_cb = client_fcgi_request_close_cb; | ||||
| 	request->request.ctx       = ev_userdata (EV_DEFAULT); | ||||
| 	request->request.write_cb  = client_fcgi_request_write_cb; | ||||
| 	request->request.finish_cb = client_fcgi_request_finish_cb; | ||||
| 
 | ||||
| 	return request_start (&request->request, &fcgi_request->headers); | ||||
| } | ||||
| @ -2185,7 +2206,7 @@ client_fcgi_request_push | ||||
| { | ||||
| 	struct client_fcgi_request *request = req->handler_data; | ||||
| 	return request_push (&request->request, data, len) | ||||
| 		|| fcgi_request_finish (req); | ||||
| 		|| fcgi_request_finish (req, EXIT_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -2199,10 +2220,10 @@ client_fcgi_request_finalize (struct fcgi_request *req) | ||||
| // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | ||||
| 
 | ||||
| static void | ||||
| client_fcgi_write_cb (struct fcgi_muxer *mux, const void *data, size_t len) | ||||
| client_fcgi_write_cb (struct fcgi_muxer *mux, void *data, size_t len) | ||||
| { | ||||
| 	FIND_CONTAINER (self, mux, struct client_fcgi, muxer); | ||||
| 	client_write (&self->client, data, len); | ||||
| 	client_write_owned (&self->client, data, len); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -2278,10 +2299,9 @@ client_scgi_write_cb (struct request *req, const void *data, size_t len) | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| client_scgi_close_cb (struct request *req) | ||||
| client_scgi_finish_cb (struct request *req) | ||||
| { | ||||
| 	FIND_CONTAINER (self, req, struct client_scgi, request); | ||||
| 	// NOTE: this rather really means "close me [the request]"
 | ||||
| 	client_close (&self->client); | ||||
| } | ||||
| 
 | ||||
| @ -2358,7 +2378,7 @@ client_scgi_create (EV_P_ int sock_fd) | ||||
| 	request_init (&self->request); | ||||
| 	self->request.ctx            = ev_userdata (EV_DEFAULT); | ||||
| 	self->request.write_cb       = client_scgi_write_cb; | ||||
| 	self->request.close_cb       = client_scgi_close_cb; | ||||
| 	self->request.finish_cb      = client_scgi_finish_cb; | ||||
| 
 | ||||
| 	self->parser = scgi_parser_make (); | ||||
| 	self->parser.on_headers_read = client_scgi_on_headers_read; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user