Hi,
Let's say the access handler callback passed to MHD_start_daemon() is
answer_to_connection(). According to the comment in microhttpd.h, the
parameter upload_data_size shall be updated to the number of bytes not
processed. However, it seems that it only works perfectly if the
*upload_data_size is updated to zero. If its value is set to non-zero,
answer_to_connection() won't be called again, which leaves the HTTP
client waiting forever. To be more exact, unless the client sends
another (unrelated) request, MHD calls answer_to_connection() for the
suspending request again. Don't know if this is a bug, or I'm misusing
MHD. Having tried this on both Linux (Debian) and Windows, and both
don't work. The attached file demonstrates the problem.
Thanks. Have a nice day.
Nicholas Cooper.
// BUILD: g++ a.cpp -Wall $(pkg-config --cflags --libs libmicrohttpd)
#include <cstdio>
#include <ctime>
#include <microhttpd.h>
#include <string>
int answer_to_connection(
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
) {
time_t now = std::time(NULL);
const size_t cchNow = 9u;
char szNow[cchNow];
std::strftime(szNow, cchNow, "%H:%M:%S", std::localtime(&now));
// stage 1
if (*con_cls == NULL) {
std::printf("[%s] connection 0x%08X, stage 1: %s %s %s\n", szNow, (size_t)connection, url, method, version);
*con_cls = (void *)0xDEADBEEF;
return MHD_YES;
}
// stage 2
if (*upload_data_size != 0u) {
std::printf("[%s] connection 0x%08X, stage 2: 0x%08X, %u\n", szNow, (size_t)connection, (size_t)upload_data, *upload_data_size);
*upload_data_size = static_cast<size_t>(std::max(static_cast<int>(*upload_data_size) - 100, 0));
return MHD_YES;
}
// stage 3
std::printf("[%s] connection 0x%08X, stage 3\n", szNow, (size_t)connection);
static const std::string s_strDoc("Hello MHD!");
MHD_Response *res = ::MHD_create_response_from_buffer(s_strDoc.length(), (void *)s_strDoc.data(), MHD_RESPMEM_PERSISTENT);
::MHD_add_response_header(res, "Content-Type", "text/plain");
::MHD_queue_response(connection, MHD_HTTP_OK, res);
::MHD_destroy_response(res);
return MHD_YES;
}
int main(int argc, char *argv[])
{
MHD_Daemon *daemon = ::MHD_start_daemon(
MHD_USE_SELECT_INTERNALLY,
UINT16_C(12345u), // port number
NULL, NULL,
&answer_to_connection, NULL,
MHD_OPTION_END
);
::MHD_run(daemon);
std::getchar();
::MHD_stop_daemon(daemon);
return 0;
}