# HG changeset patch # User Sebastien Jodogne # Date 1409566826 -7200 # Node ID a119f9ae3640c8d433b77d415914bef0f3a4de62 # Parent 929bf8c2123db590cdd30e03a37fc6b66da15c11 upgrade to Mongoose 3.8 diff -r 929bf8c2123d -r a119f9ae3640 CMakeLists.txt --- a/CMakeLists.txt Mon Sep 01 11:23:13 2014 +0200 +++ b/CMakeLists.txt Mon Sep 01 12:20:26 2014 +0200 @@ -44,6 +44,8 @@ # Distribution-specific settings SET(USE_GTEST_DEBIAN_SOURCE_PACKAGE OFF CACHE BOOL "Use the sources of Google Test shipped with libgtest-dev (Debian only)") mark_as_advanced(USE_GTEST_DEBIAN_SOURCE_PACKAGE) +SET(SYSTEM_MONGOOSE_USE_CALLBACKS ON CACHE BOOL "The system version of Mongoose uses callbacks (version >= 3.7)") +mark_as_advanced(SYSTEM_MONGOOSE_USE_CALLBACKS) # Path to the root folder of the Orthanc distribution set(ORTHANC_ROOT ${CMAKE_SOURCE_DIR}) diff -r 929bf8c2123d -r a119f9ae3640 Core/HttpServer/MongooseServer.cpp --- a/Core/HttpServer/MongooseServer.cpp Mon Sep 01 11:23:13 2014 +0200 +++ b/Core/HttpServer/MongooseServer.cpp Mon Sep 01 12:20:26 2014 +0200 @@ -547,191 +547,215 @@ } + static void InternalCallback(struct mg_connection *connection, + const struct mg_request_info *request) + { + MongooseServer* that = reinterpret_cast(request->user_data); + MongooseOutputStream stream(connection); + HttpOutput output(stream); + // Check remote calls + if (!that->IsRemoteAccessAllowed() && + request->remote_ip != LOCALHOST) + { + output.SendUnauthorized(ORTHANC_REALM); + return; + } + + + // Extract the HTTP headers + HttpHandler::Arguments headers; + for (int i = 0; i < request->num_headers; i++) + { + std::string name = request->http_headers[i].name; + std::transform(name.begin(), name.end(), name.begin(), ::tolower); + headers.insert(std::make_pair(name, request->http_headers[i].value)); + } + + + // Extract the GET arguments + HttpHandler::Arguments argumentsGET; + if (!strcmp(request->request_method, "GET")) + { + HttpHandler::ParseGetArguments(argumentsGET, request->query_string); + } + + + // Compute the HTTP method, taking method faking into consideration + HttpMethod method; + if (!ExtractMethod(method, request, headers, argumentsGET)) + { + output.SendHeader(HttpStatus_400_BadRequest); + return; + } + + + // Authenticate this connection + if (that->IsAuthenticationEnabled() && + !Authorize(*that, headers, output)) + { + return; + } + + + // Apply the filter, if it is installed + const IIncomingHttpRequestFilter *filter = that->GetIncomingHttpRequestFilter(); + if (filter != NULL) + { + std::string username = GetAuthenticatedUsername(headers); + + char remoteIp[24]; + sprintf(remoteIp, "%d.%d.%d.%d", + reinterpret_cast(&request->remote_ip) [3], + reinterpret_cast(&request->remote_ip) [2], + reinterpret_cast(&request->remote_ip) [1], + reinterpret_cast(&request->remote_ip) [0]); + + if (!filter->IsAllowed(method, request->uri, remoteIp, username.c_str())) + { + output.SendUnauthorized(ORTHANC_REALM); + return; + } + } + + + // Extract the body of the request for PUT and POST + std::string body; + if (method == HttpMethod_Post || + method == HttpMethod_Put) + { + PostDataStatus status; + + HttpHandler::Arguments::const_iterator ct = headers.find("content-type"); + if (ct == headers.end()) + { + // No content-type specified. Assume no multi-part content occurs at this point. + status = ReadBody(body, connection, headers); + } + else + { + std::string contentType = ct->second; + if (contentType.size() >= multipartLength && + !memcmp(contentType.c_str(), multipart, multipartLength)) + { + status = ParseMultipartPost(body, connection, headers, contentType, that->GetChunkStore()); + } + else + { + status = ReadBody(body, connection, headers); + } + } + + switch (status) + { + case PostDataStatus_NoLength: + output.SendHeader(HttpStatus_411_LengthRequired); + return; + + case PostDataStatus_Failure: + output.SendHeader(HttpStatus_400_BadRequest); + return; + + case PostDataStatus_Pending: + output.AnswerBufferWithContentType(NULL, 0, ""); + return; + + default: + break; + } + } + + + // Decompose the URI into its components + UriComponents uri; + try + { + Toolbox::SplitUriComponents(uri, request->uri); + } + catch (OrthancException) + { + output.SendHeader(HttpStatus_400_BadRequest); + return; + } + + + // Loop over the candidate handlers for this URI + LOG(INFO) << EnumerationToString(method) << " " << Toolbox::FlattenUri(uri); + bool found = false; + + for (MongooseServer::Handlers::const_iterator it = + that->GetHandlers().begin(); it != that->GetHandlers().end() && !found; ++it) + { + try + { + found = (*it)->Handle(output, method, uri, headers, argumentsGET, body); + } + catch (OrthancException& e) + { + // Using this candidate handler results in an exception + LOG(ERROR) << "Exception in the HTTP handler: " << e.What(); + return; + } + catch (boost::bad_lexical_cast&) + { + LOG(ERROR) << "Exception in the HTTP handler: Bad lexical cast"; + return; + } + catch (std::runtime_error&) + { + LOG(ERROR) << "Exception in the HTTP handler: Presumably a bad JSON request"; + return; + } + } + + if (!found) + { + try + { + output.SendHeader(HttpStatus_404_NotFound); + } + catch (OrthancException&) + { + } + } + } + + +#if MONGOOSE_USE_CALLBACKS == 0 static void* Callback(enum mg_event event, struct mg_connection *connection, const struct mg_request_info *request) { if (event == MG_NEW_REQUEST) { - MongooseServer* that = reinterpret_cast(request->user_data); - MongooseOutputStream stream(connection); - HttpOutput output(stream); - - // Check remote calls - if (!that->IsRemoteAccessAllowed() && - request->remote_ip != LOCALHOST) - { - output.SendUnauthorized(ORTHANC_REALM); - return (void*) ""; - } - - - // Extract the HTTP headers - HttpHandler::Arguments headers; - for (int i = 0; i < request->num_headers; i++) - { - std::string name = request->http_headers[i].name; - std::transform(name.begin(), name.end(), name.begin(), ::tolower); - headers.insert(std::make_pair(name, request->http_headers[i].value)); - } - - - // Extract the GET arguments - HttpHandler::Arguments argumentsGET; - if (!strcmp(request->request_method, "GET")) - { - HttpHandler::ParseGetArguments(argumentsGET, request->query_string); - } - - - // Compute the HTTP method, taking method faking into consideration - HttpMethod method; - if (!ExtractMethod(method, request, headers, argumentsGET)) - { - output.SendHeader(HttpStatus_400_BadRequest); - return (void*) ""; - } - - - // Authenticate this connection - if (that->IsAuthenticationEnabled() && - !Authorize(*that, headers, output)) - { - return (void*) ""; - } - - - // Apply the filter, if it is installed - const IIncomingHttpRequestFilter *filter = that->GetIncomingHttpRequestFilter(); - if (filter != NULL) - { - std::string username = GetAuthenticatedUsername(headers); - - char remoteIp[24]; - sprintf(remoteIp, "%d.%d.%d.%d", - reinterpret_cast(&request->remote_ip) [3], - reinterpret_cast(&request->remote_ip) [2], - reinterpret_cast(&request->remote_ip) [1], - reinterpret_cast(&request->remote_ip) [0]); - - if (!filter->IsAllowed(method, request->uri, remoteIp, username.c_str())) - { - output.SendUnauthorized(ORTHANC_REALM); - return (void*) ""; - } - } - - - // Extract the body of the request for PUT and POST - std::string body; - if (method == HttpMethod_Post || - method == HttpMethod_Put) - { - PostDataStatus status; - - HttpHandler::Arguments::const_iterator ct = headers.find("content-type"); - if (ct == headers.end()) - { - // No content-type specified. Assume no multi-part content occurs at this point. - status = ReadBody(body, connection, headers); - } - else - { - std::string contentType = ct->second; - if (contentType.size() >= multipartLength && - !memcmp(contentType.c_str(), multipart, multipartLength)) - { - status = ParseMultipartPost(body, connection, headers, contentType, that->GetChunkStore()); - } - else - { - status = ReadBody(body, connection, headers); - } - } - - switch (status) - { - case PostDataStatus_NoLength: - output.SendHeader(HttpStatus_411_LengthRequired); - return (void*) ""; - - case PostDataStatus_Failure: - output.SendHeader(HttpStatus_400_BadRequest); - return (void*) ""; - - case PostDataStatus_Pending: - output.AnswerBufferWithContentType(NULL, 0, ""); - return (void*) ""; - - default: - break; - } - } - - - // Decompose the URI into its components - UriComponents uri; - try - { - Toolbox::SplitUriComponents(uri, request->uri); - } - catch (OrthancException) - { - output.SendHeader(HttpStatus_400_BadRequest); - return (void*) ""; - } - - - // Loop over the candidate handlers for this URI - LOG(INFO) << EnumerationToString(method) << " " << Toolbox::FlattenUri(uri); - bool found = false; - - for (MongooseServer::Handlers::const_iterator it = - that->GetHandlers().begin(); it != that->GetHandlers().end() && !found; ++it) - { - try - { - found = (*it)->Handle(output, method, uri, headers, argumentsGET, body); - } - catch (OrthancException& e) - { - // Using this candidate handler results in an exception - LOG(ERROR) << "Exception in the HTTP handler: " << e.What(); - return (void*) ""; - } - catch (boost::bad_lexical_cast&) - { - LOG(ERROR) << "Exception in the HTTP handler: Bad lexical cast"; - return (void*) ""; - } - catch (std::runtime_error&) - { - LOG(ERROR) << "Exception in the HTTP handler: Presumably a bad JSON request"; - return (void*) ""; - } - } - - if (!found) - { - try - { - output.SendHeader(HttpStatus_404_NotFound); - } - catch (OrthancException&) - { - } - } + InternalCallback(connection, request); // Mark as processed return (void*) ""; - } - else + } + else { return NULL; } } +#elif MONGOOSE_USE_CALLBACKS == 1 + static int Callback(struct mg_connection *connection) + { + struct mg_request_info *request = mg_get_request_info(connection); + + InternalCallback(connection, request); + + return 1; // Do not let Mongoose handle the request by itself + } + +#else +#error Please set MONGOOSE_USE_CALLBACKS +#endif + + + + bool MongooseServer::IsRunning() const { @@ -798,7 +822,19 @@ NULL }; +#if MONGOOSE_USE_CALLBACKS == 0 pimpl_->context_ = mg_start(&Callback, this, options); + +#elif MONGOOSE_USE_CALLBACKS == 1 + struct mg_callbacks callbacks; + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.begin_request = Callback; + pimpl_->context_ = mg_start(&callbacks, this, options); + +#else +#error Please set MONGOOSE_USE_CALLBACKS +#endif + if (!pimpl_->context_) { throw OrthancException("Unable to launch the Mongoose server"); diff -r 929bf8c2123d -r a119f9ae3640 NEWS --- a/NEWS Mon Sep 01 11:23:13 2014 +0200 +++ b/NEWS Mon Sep 01 12:20:26 2014 +0200 @@ -1,6 +1,9 @@ Pending changes in the mainline =============================== +* Upgrade to Mongoose 3.8 (the last release under the MIT license) +* Fixes for Visual Studio 2013 and Visual Studio 64bit + Version 0.8.2 (2014/08/07) ========================== diff -r 929bf8c2123d -r a119f9ae3640 Resources/CMake/MongooseConfiguration.cmake --- a/Resources/CMake/MongooseConfiguration.cmake Mon Sep 01 11:23:13 2014 +0200 +++ b/Resources/CMake/MongooseConfiguration.cmake Mon Sep 01 12:20:26 2014 +0200 @@ -1,13 +1,30 @@ if (STATIC_BUILD OR NOT USE_SYSTEM_MONGOOSE) SET(MONGOOSE_SOURCES_DIR ${CMAKE_BINARY_DIR}/mongoose) - DownloadPackage( - "e718fc287b4eb1bd523be3fa00942bb0" - "http://www.montefiore.ulg.ac.be/~jodogne/Orthanc/ThirdPartyDownloads/mongoose-3.1.tgz" - "${MONGOOSE_SOURCES_DIR}") + + if (0) + # Use Mongoose 3.1 + DownloadPackage( + "e718fc287b4eb1bd523be3fa00942bb0" + "http://www.montefiore.ulg.ac.be/~jodogne/Orthanc/ThirdPartyDownloads/mongoose-3.1.tgz" + "${MONGOOSE_SOURCES_DIR}") + + add_definitions(-DMONGOOSE_USE_CALLBACKS=0) + set(MONGOOSE_PATCH ${ORTHANC_ROOT}/Resources/Patches/mongoose-3.1-patch.diff) + + else() + # Use Mongoose 3.8 + DownloadPackage( + "7e3296295072792cdc3c633f9404e0c3" + "http://www.montefiore.ulg.ac.be/~jodogne/Orthanc/ThirdPartyDownloads/mongoose-3.8.tgz" + "${MONGOOSE_SOURCES_DIR}") + + add_definitions(-DMONGOOSE_USE_CALLBACKS=1) + set(MONGOOSE_PATCH ${ORTHANC_ROOT}/Resources/Patches/mongoose-3.8-patch.diff) + endif() # Patch mongoose execute_process( - COMMAND patch mongoose.c ${ORTHANC_ROOT}/Resources/Patches/mongoose-3.1-patch.diff + COMMAND patch mongoose.c ${MONGOOSE_PATCH} WORKING_DIRECTORY ${MONGOOSE_SOURCES_DIR} ) @@ -56,5 +73,13 @@ message(FATAL_ERROR "Please install the mongoose-devel package") endif() + if (SYSTEM_MONGOOSE_USE_CALLBACKS) + add_definitions(-DMONGOOSE_USE_CALLBACKS=1) + else() + add_definitions(-DMONGOOSE_USE_CALLBACKS=0) + endif() + link_libraries(mongoose) endif() + + diff -r 929bf8c2123d -r a119f9ae3640 Resources/Patches/mongoose-3.8-patch.diff --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/Patches/mongoose-3.8-patch.diff Mon Sep 01 12:20:26 2014 +0200 @@ -0,0 +1,29 @@ +--- mongoose.c.orig 2014-09-01 11:25:18.223466994 +0200 ++++ mongoose.c 2014-09-01 11:30:21.807479338 +0200 +@@ -50,6 +50,14 @@ + #define PATH_MAX FILENAME_MAX + #endif // __SYMBIAN32__ + ++#if __gnu_hurd__ == 1 ++/** ++ * There is no limit on the length on a path under GNU Hurd, so we set ++ * it to an arbitrary constant. ++ **/ ++#define PATH_MAX 4096 ++#endif ++ + #ifndef _WIN32_WCE // Some ANSI #includes are not available on Windows CE + #include + #include +@@ -108,8 +116,9 @@ + #define strtoll(x, y, z) _atoi64(x) + #else + #define __func__ __FUNCTION__ +-#define strtoull(x, y, z) _strtoui64(x, y, z) +-#define strtoll(x, y, z) _strtoi64(x, y, z) ++#include ++//#define strtoull(x, y, z) _strtoui64(x, y, z) ++//#define strtoll(x, y, z) _strtoi64(x, y, z) + #endif // _MSC_VER + + #define ERRNO GetLastError()