port,
nullptr, nullptr,
&answer_to_connection_thunk, this,
- MHD_OPTION_NOTIFY_COMPLETED, nullptr, this,
MHD_OPTION_END);
if (mhd == nullptr) {
fprintf(stderr, "Warning: Could not open HTTP server. (Port already in use?)\n");
}
}
-int HTTPD::answer_to_connection_thunk(void *cls, MHD_Connection *connection,
- const char *url, const char *method,
- const char *version, const char *upload_data,
- size_t *upload_data_size, void **con_cls)
+HTTPD::MHD_Result HTTPD::answer_to_connection_thunk(void *cls, MHD_Connection *connection,
+ const char *url, const char *method,
+ const char *version, const char *upload_data,
+ size_t *upload_data_size, void **con_cls)
{
HTTPD *httpd = (HTTPD *)cls;
return httpd->answer_to_connection(connection, url, method, version, upload_data, upload_data_size, con_cls);
}
-int HTTPD::answer_to_connection(MHD_Connection *connection,
- const char *url, const char *method,
- const char *version, const char *upload_data,
- size_t *upload_data_size, void **con_cls)
+HTTPD::MHD_Result HTTPD::answer_to_connection(MHD_Connection *connection,
+ const char *url, const char *method,
+ const char *version, const char *upload_data,
+ size_t *upload_data_size, void **con_cls)
{
// See if the URL ends in “.metacube”.
HTTPD::Stream::Framing framing;
MHD_Response *response = MHD_create_response_from_buffer(
contents.size(), &contents[0], MHD_RESPMEM_MUST_COPY);
MHD_add_response_header(response, "Content-type", "text/plain");
- int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
+ MHD_Result ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response); // Only decreases the refcount; actual free is after the request is done.
return ret;
}
if (endpoints[url].cors_policy == ALLOW_ALL_ORIGINS) {
MHD_add_response_header(response, "Access-Control-Allow-Origin", "*");
}
- int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
+ MHD_Result ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response); // Only decreases the refcount; actual free is after the request is done.
return ret;
}
MHD_Response *response = MHD_create_response_from_buffer(
contents.size(), &contents[0], MHD_RESPMEM_MUST_COPY);
MHD_add_response_header(response, "Content-type", "text/plain");
- int ret = MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
+ MHD_Result ret = MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
MHD_destroy_response(response); // Only decreases the refcount; actual free is after the request is done.
return ret;
}
MHD_add_response_header(response, "Content-encoding", "metacube");
}
- int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
+ MHD_Result ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response); // Only decreases the refcount; actual free is after the request is done.
return ret;
ssize_t HTTPD::Stream::reader_callback(uint64_t pos, char *buf, size_t max)
{
unique_lock<mutex> lock(buffer_mutex);
- has_buffered_data.wait(lock, [this] { return should_quit || !buffered_data.empty(); });
+ bool has_data = has_buffered_data.wait_for(lock, std::chrono::seconds(60), [this] { return should_quit || !buffered_data.empty(); });
if (should_quit) {
return -1;
}
+ if (!has_data) {
+ // The wait timed out, so tell microhttpd to clean out the socket;
+ // it's not unlikely that the client has given up anyway.
+ // This is seemingly the only way to actually reap sockets if we
+ // do not get any data; returning 0 does nothing, and
+ // MHD_OPTION_NOTIFY_CONNECTION does not trigger for these cases.
+ // If not, an instance that has no data to send (typically an instance
+ // of kaeru connected to a nonfunctional backend) would get a steadily
+ // increasing amount of sockets in CLOSE_WAIT (ie., the other end has
+ // hung up, but we haven't called close() yet, as our thread is stuck
+ // in this callback).
+ return -1;
+ }
ssize_t ret = 0;
while (max > 0 && !buffered_data.empty()) {