static void process_new_connection(struct mg_connection *conn) { struct mg_request_info *ri = &conn->request_info; const char *cl; reset_per_request_attributes(conn); // If next request is not pipelined, read it in if ((conn->request_len = get_request_len(conn->buf, conn->data_len)) == 0) { conn->request_len = read_request(conn->client.sock, conn->buf, conn->buf_size, &conn->data_len); } assert(conn->data_len >= conn->request_len); if (conn->request_len == 0 && conn->data_len == conn->buf_size) { mg_send_http_error(conn, 413, "Request Too Large", ""); return; } if (conn->request_len <= 0) { return; // Remote end closed the connection } // Nul-terminate the request cause parse_http_request() uses sscanf conn->buf[conn->request_len - 1] = '\0'; if (!parse_http_request(conn->buf, ri)) { // Do not put garbage in the access log, just send it back to the client mg_send_http_error(conn, 400, "Bad Request", "Cannot parse HTTP request: [%.*s]", conn->data_len, conn->buf); } else if (strcmp(ri->http_version, "1.0") && strcmp(ri->http_version, "1.1")) { // Request seems valid, but HTTP version is strange mg_send_http_error(conn, 505, "HTTP version not supported", ""); } else { // Request is valid, handle it cl = get_header(ri, "Content-Length"); conn->content_len = cl == NULL ? -1 : strtoll(cl, NULL, 10); conn->birth_time = time(NULL); handle_request(conn); discard_current_request_from_buffer(conn); } }
// This is the heart of the Mongoose's logic. // This function is called when the request is read, parsed and validated, // and Mongoose must decide what action to take: serve a file, or // a directory, or call embedded function, etcetera. static void handle_request(struct mg_connection *conn) { struct mg_request_info *ri = &conn->request_info; int uri_len; if ((conn->request_info.query_string = strchr(ri->uri, '?')) != NULL) { * conn->request_info.query_string++ = '\0'; } uri_len = strlen(ri->uri); (void) url_decode(ri->uri, (size_t)uri_len, ri->uri, (size_t)(uri_len + 1), 0); remove_double_dots_and_double_slashes(ri->uri); DEBUG_TRACE(("%s", ri->uri)); if (call_user(conn, MG_NEW_REQUEST) == NULL) { mg_send_http_error(conn, 404, "Not Found", "%s", "File not found"); } }
static void *request_handler(enum mg_event event, struct mg_connection *conn, const struct mg_request_info *request_info) { if (event == MG_NEW_REQUEST) { if (!strcmp(request_info->uri, "/dd.xml") && !strcmp(request_info->request_method, "GET")) { mg_printf(conn, "HTTP/1.1 200 OK\r\n" "Content-Type: application/xml\r\n" "Application-URL: http://%s:%d/apps/\r\n" "\r\n", ip_addr, dial_port); mg_printf(conn, ddxml, friendly_name, model_name, uuid); } else { mg_send_http_error(conn, 404, "Not Found", "Not Found"); } return "done"; } return NULL; }
static void *mongoose_callback(enum mg_event event, struct mg_connection *conn) { const struct mg_request_info *request_info = mg_get_request_info(conn); if (event == MG_INIT0) { verify_document_root(mg_get_conn_option(conn, "document_root")); return (void *)1; } #if defined(_WIN32) if (event == MG_EVENT_LOG && strstr(request_info->log_message, "cannot bind to") && !strcmp(request_info->log_severity, "error")) { if (!error_dialog_shown_previously) { MessageBoxA(NULL, request_info->log_message, "Error", MB_OK); error_dialog_shown_previously = 1; } return 0; } #endif if (event != MG_NEW_REQUEST) { // This callback currently only handles new requests return NULL; } { int file_found; struct mgstat fst; assert(request_info->phys_path); file_found = (0 == mg_stat(request_info->phys_path, &fst) && !fst.is_directory); if (file_found) { return NULL; // let mongoose handle the default of 'file exists'... } #ifdef _WIN32 // Send the systray icon as favicon if (!strcmp("/favicon.ico", request_info->uri)) { HMODULE module; HRSRC icon; DWORD len; void *data; module = GetModuleHandle(NULL); icon = FindResource(module, MAKEINTRESOURCE(IDR_FAVICON), RT_RCDATA); data = LockResource(LoadResource(module, icon)); len = SizeofResource(module, icon); mg_add_response_header(conn, 0, "Content-Type", "image/x-icon"); mg_add_response_header(conn, 0, "Cache-Control", "no-cache"); mg_add_response_header(conn, 0, "Content-Length", "%u", (unsigned int)len); //mg_add_response_header(conn, 0, "Connection", suggest_connection_header(conn)); -- not needed any longer mg_write_http_response_head(conn, 200, NULL); if ((int)len != mg_write(conn, data, len)) { mg_send_http_error(conn, 580, NULL, "not all data was written to the socket (len: %u)", (unsigned int)len); // internal error in our custom handler or client closed connection prematurely } return (void *)1; } #endif } return NULL; }
static void *mongoose_callback(enum mg_event event, struct mg_connection *conn) { const struct mg_request_info *request_info = mg_get_request_info(conn); if (event == MG_INIT0) { verify_document_root(mg_get_conn_option(conn, "document_root")); return (void *)1; } #if defined(_WIN32) if (event == MG_EVENT_LOG && strstr(request_info->log_message, "cannot bind to") && !strcmp(request_info->log_severity, "error")) { if (!error_dialog_shown_previously) { MessageBoxA(NULL, request_info->log_message, "Error", MB_OK); error_dialog_shown_previously = 1; } return 0; } #endif #if USE_BEL2125_TEST_NR_18_EVENT_HANDLER { int contentLength = 0; int dataRead = 0; char postData[BUFFER_SIZE] = { 0 }; const char* contentType = NULL; if (event == MG_NEW_REQUEST) { if (strstr(request_info->uri, "/echo") == request_info->uri) { int ie_hack = 0; // testing an assumption; turns out it doesn't matter whether headers make it into TCP stack before you expect to fetch all input data at once. int ie_hack2 = 0; contentLength = atoi(mg_get_header(conn, "Content-Length")); assert(contentLength <= BUFFER_SIZE); mg_set_response_code(conn, 200); if (ie_hack2) mg_connection_must_close(conn); // the stackoverflow suggested fix: http://stackoverflow.com/questions/3731420/why-does-ie-issue-random-xhr-408-12152-responses-using-jquery-post contentType = mg_get_header(conn, "Content-Type"); if (ie_hack) { //mg_add_response_header(conn, 0, "Connection", mg_suggest_connection_header(conn)); -- not needed any longer mg_add_response_header(conn, 0, "Content-Type", contentType); mg_add_response_header(conn, 0, "Content-Length", "%d", contentLength); mg_write_http_response_head(conn, 0, 0); // let the previous mg_set_response_code() decide for us } dataRead = mg_read(conn, postData, contentLength); if (dataRead > 0) { assert(dataRead == contentLength); if (!ie_hack) { //mg_add_response_header(conn, 0, "Connection", mg_suggest_connection_header(conn)); -- not needed any longer mg_add_response_header(conn, 0, "Content-Type", contentType); mg_add_response_header(conn, 0, "Content-Length", "%d", dataRead); mg_write_http_response_head(conn, 0, 0); // let the previous mg_set_response_code() decide for us } if (mg_write(conn, postData, dataRead) != contentLength) { mg_send_http_error(conn, 580, NULL, "not all data was written to the socket (len: %u)", (unsigned int)contentLength); // internal error in our custom handler or client closed connection prematurely } return (void*)1; } else { mg_send_http_error(conn, 500, NULL, "I/O failure during mg_read() from connection: %s", mg_strerror(ERRNO)); } } } } #endif // USE_BEL2125_TEST_NR_18_EVENT_HANDLER if (event != MG_NEW_REQUEST) { // This callback currently only handles new requests return NULL; } { int file_found; struct mgstat fst; assert(request_info->phys_path); file_found = (0 == mg_stat(request_info->phys_path, &fst) && !fst.is_directory); if (file_found) { return NULL; // let mongoose handle the default of 'file exists'... } #ifdef _WIN32 // Send the systray icon as favicon if (!strcmp("/favicon.ico", request_info->uri)) { HMODULE module; HRSRC icon; DWORD len; void *data; module = GetModuleHandle(NULL); icon = FindResource(module, MAKEINTRESOURCE(IDR_FAVICON), RT_RCDATA); data = LockResource(LoadResource(module, icon)); len = SizeofResource(module, icon); mg_add_response_header(conn, 0, "Content-Type", "image/x-icon"); mg_add_response_header(conn, 0, "Cache-Control", "no-cache"); mg_add_response_header(conn, 0, "Content-Length", "%u", (unsigned int)len); //mg_add_response_header(conn, 0, "Connection", suggest_connection_header(conn)); -- not needed any longer mg_write_http_response_head(conn, 200, NULL); if ((int)len != mg_write(conn, data, len)) { mg_send_http_error(conn, 580, NULL, "not all data was written to the socket (len: %u)", (unsigned int)len); // internal error in our custom handler or client closed connection prematurely } return (void *)1; } #endif } return NULL; }