|
@@ -9,11 +9,13 @@ namespace Astralis {
|
|
|
private RequestHandler handler;
|
|
private RequestHandler handler;
|
|
|
private int port;
|
|
private int port;
|
|
|
private HashSet<RequestContext> request_contexts;
|
|
private HashSet<RequestContext> request_contexts;
|
|
|
|
|
+ private HashSet<ResponseContext> response_contexts;
|
|
|
|
|
|
|
|
public Server(int port, RequestHandler handler) {
|
|
public Server(int port, RequestHandler handler) {
|
|
|
this.port = port;
|
|
this.port = port;
|
|
|
this.handler = handler;
|
|
this.handler = handler;
|
|
|
this.request_contexts = new HashSet<RequestContext>();
|
|
this.request_contexts = new HashSet<RequestContext>();
|
|
|
|
|
+ this.response_contexts = new HashSet<ResponseContext>();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private int access_handler (Connection connection, string? url, string? method, string? version, string? upload_data, size_t* upload_data_size, void** con_cls) {
|
|
private int access_handler (Connection connection, string? url, string? method, string? version, string? upload_data, size_t* upload_data_size, void** con_cls) {
|
|
@@ -128,30 +130,40 @@ namespace Astralis {
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
private Result send_result(Connection connection, HttpResult result) {
|
|
private Result send_result(Connection connection, HttpResult result) {
|
|
|
- Response response;
|
|
|
|
|
-
|
|
|
|
|
- if(result.get_type().is_a(typeof(BufferedHttpResult))) {
|
|
|
|
|
- var buffered = (BufferedHttpResult)result;
|
|
|
|
|
- response = new Response.from_buffer(
|
|
|
|
|
- buffered.buffer.length,
|
|
|
|
|
- buffered.buffer,
|
|
|
|
|
- ResponseMemoryMode.RESPMEM_MUST_COPY
|
|
|
|
|
- );
|
|
|
|
|
- }
|
|
|
|
|
- else {
|
|
|
|
|
- response = new Response.from_buffer(
|
|
|
|
|
- 0,
|
|
|
|
|
- new uint8[0],
|
|
|
|
|
- ResponseMemoryMode.RESPMEM_PERSISTENT
|
|
|
|
|
- );
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ uint64 size = result.content_length ?? -1;
|
|
|
|
|
+ var response_context = new ResponseContext(connection, result);
|
|
|
|
|
+ response_contexts.add(response_context);
|
|
|
|
|
+
|
|
|
|
|
+ var response = new Response.from_callback(
|
|
|
|
|
+ size,
|
|
|
|
|
+ 1048576,
|
|
|
|
|
+ (cls, pos, buf, max) => {
|
|
|
|
|
+ var context = (ResponseContext) ((Object*) cls[0]);
|
|
|
|
|
+ var bytes_read = context.body_output.read_chunk(buf, max);
|
|
|
|
|
+ if(bytes_read == 0) {
|
|
|
|
|
+ if(!context.send_body_finished) {
|
|
|
|
|
+ context.suspend_connection();
|
|
|
|
|
+ }
|
|
|
|
|
+ else if(context.send_body_error == null) {
|
|
|
|
|
+ response_contexts.remove(context);
|
|
|
|
|
+ return CONTENT_READER_END_OF_STREAM;
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ printerr(@"Astralis Internal Server Error: Unhandled Error Sending HttpResult: $(context.send_body_error.message)\n");
|
|
|
|
|
+ response_contexts.remove(context);
|
|
|
|
|
+ return CONTENT_READER_END_WITH_ERROR;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return (ssize_t)bytes_read;
|
|
|
|
|
+ },
|
|
|
|
|
+ &response_context,
|
|
|
|
|
+ null);
|
|
|
|
|
|
|
|
|
|
|
|
|
- result.headers.to_immutable_buffer().iterate((grouping) => {
|
|
|
|
|
- grouping.iterate((value) => {
|
|
|
|
|
- response.add_header(grouping.key, value);
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ result.headers.iterate((kv) => {
|
|
|
|
|
+ response.add_header(kv.key, kv.value);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
var res = MHD.queue_response(connection, result.status, response);
|
|
var res = MHD.queue_response(connection, result.status, response);
|
|
@@ -163,7 +175,7 @@ namespace Astralis {
|
|
|
|
|
|
|
|
private Result handle_error(Error error, Connection connection) {
|
|
private Result handle_error(Error error, Connection connection) {
|
|
|
printerr(@"Astralis Internal Server Error: Unhandled Error: $(error.message)\n");
|
|
printerr(@"Astralis Internal Server Error: Unhandled Error: $(error.message)\n");
|
|
|
- return send_result(connection, new BufferedHttpResult.from_string("Internal Server Error", StatusCode.INTERNAL_SERVER_ERROR));
|
|
|
|
|
|
|
+ return send_result(connection, new HttpStringResult("Internal Server Error", StatusCode.INTERNAL_SERVER_ERROR));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Simple memory-based InputStream for request body
|
|
// Simple memory-based InputStream for request body
|