From 8bb4fb1ab7493bcea68d7b34d587ffa5479c2637 Mon Sep 17 00:00:00 2001 From: ThoNohT Date: Fri, 1 May 2026 16:00:53 +0200 Subject: [PATCH] Simple example using libmicrohttpd --- Makefile | 15 + build.sh | 20 + src/main.c | 62 + src/noh.h | 1299 ++++ vendor/libmicrohttpd/include/microhttpd.h | 6586 +++++++++++++++++ vendor/libmicrohttpd/lib/libmicrohttpd.a | Bin 0 -> 1101442 bytes vendor/libmicrohttpd/share/info/dir | 21 + .../share/info/libmicrohttpd-tutorial.info | 5752 ++++++++++++++ .../share/info/libmicrohttpd.info | 6138 +++++++++++++++ .../info/libmicrohttpd_performance_data.png | Bin 0 -> 9169 bytes .../share/man/man3/libmicrohttpd.3 | 46 + 11 files changed, 19939 insertions(+) create mode 100644 Makefile create mode 100755 build.sh create mode 100644 src/main.c create mode 100644 src/noh.h create mode 100644 vendor/libmicrohttpd/include/microhttpd.h create mode 100644 vendor/libmicrohttpd/lib/libmicrohttpd.a create mode 100644 vendor/libmicrohttpd/share/info/dir create mode 100644 vendor/libmicrohttpd/share/info/libmicrohttpd-tutorial.info create mode 100644 vendor/libmicrohttpd/share/info/libmicrohttpd.info create mode 100644 vendor/libmicrohttpd/share/info/libmicrohttpd_performance_data.png create mode 100644 vendor/libmicrohttpd/share/man/man3/libmicrohttpd.3 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c56a802 --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +CFLAGS=-Wall -Wextra + +LIBWS=./vendor/libmicrohttpd/ +LIBWS_LIB=$(LIBWS)lib/libmicrohttpd.a + +LDFLAGS=-lm +INCL_FLAGS=-I$(LIBWS)include + + +main: src/main.c output + gcc $(CFLAGS) $(INCL_FLAGS) -o output/main src/main.c $(LIBWS_LIB) $(LDFLAGS) + + +output: + mkdir -p output diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..516ff1f --- /dev/null +++ b/build.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env sh + +if [ $1 = "build" ]; then + make main -B + +elif [ $1 = "run" ]; then + make main + ./output/main + +elif [ $1 = "debug" ]; then + echo "Debugging" + +elif [ $1 = "clean" ]; then + rm -rf ./output/ + +else + echo "Invalid command." + +fi + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..0dcf0c2 --- /dev/null +++ b/src/main.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include + +static enum MHD_Result request_handler( + void *cls, + struct MHD_Connection *connection, + const char *url, const char *method, const char *version, + const char *upload_data, size_t *upload_data_size, + void **con_cls) { + (void)cls; + (void)url; + (void)method; + (void)version; + (void)upload_data; + (void)upload_data_size; + (void)con_cls; + + // Create an HTTP response + const char *response_text = "Hello, World!"; + struct MHD_Response *response = MHD_create_response_from_buffer( + strlen(response_text), (void *)response_text, MHD_RESPMEM_PERSISTENT); + + if (!response) return MHD_NO; + + // Send the response + printf("%s\n", response_text); + enum MHD_Result ret = MHD_queue_response(connection, MHD_HTTP_OK, response); + MHD_destroy_response(response); + + return ret; +} + + +int main(void) +{ + struct MHD_Daemon *server; + + // Start the HTTP server + server = MHD_start_daemon( + MHD_USE_INTERNAL_POLLING_THREAD, + 5000, + NULL, NULL, + &request_handler, NULL, + MHD_OPTION_END); + + if (!server) { + fprintf(stderr, "Failed to start server\n"); + return 1; + } + + printf("Server is running on http://localhost:5000\n"); + + // Keep the server running + getchar(); + + // Stop the server + MHD_stop_daemon(server); + + return 0; +} diff --git a/src/noh.h b/src/noh.h new file mode 100644 index 0000000..67268c1 --- /dev/null +++ b/src/noh.h @@ -0,0 +1,1299 @@ +// A simple standard library full of functions reused a lot along my +// projects. +// +// Copyright 2024 ThoNohT +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef NOH_H_ +#define NOH_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 + #define WIN32_LEAN_AND_MEAN + #define _WINUSER_ + #define _WINGDI_ + #define _IMM_ + #define _WINCON_ + #include + #include +#else + #include + #include + #include +#endif // _WIN32 + +///////////////////////// Number definitions ///////////////////////// + +#ifndef int8 +#define int8 signed char +#endif + +#ifndef uint8 +#define uint8 unsigned char +#endif + +#ifndef int16 +#define int16 short +#endif + +#ifndef uint16 +#define uint16 unsigned short +#endif + +#ifndef uint +#define uint unsigned int +#endif + +#ifndef _WIN32 +#ifndef int64 +#define int64 long +#endif +#endif + +#ifndef uint64 +#define uint64 unsigned long +#endif + +#ifndef KB +#define KB << 10 +#endif + +#ifndef MB +#define MB << 20 +#endif + +#ifndef GB +#define GB << 30 +#endif + +///////////////////////// Core stuff ///////////////////////// + +#define max(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; }) +#define min(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; }) + +#define noh_array_len(array) (sizeof(array)/sizeof(array[0])) +#define noh_array_get(array, index) \ + (noh_assert(index >= 0), noh_assert(index < noh_array_get(array)), array[index]) + +// Allows returning a file after performing some deferred code. +// Usage: +// Define a result variable before the first call of this macro. +// Place a defer label at the end of the function where the work is done. +// Return result at the end of the deferred work. +#define noh_return_defer(value) do { result = (value); goto defer; } while(0) + +void* noh_realloc_check_(void *target, size_t size); + +// Reallocates some memory and crashes if it failed. +#define noh_realloc_check(target, size) noh_realloc_check_((void*)(target), (size)) + +// Returns the next argument as a c-string, moves the argv pointer to the next argument and decreases argc. +char *noh_shift_args(int *argc, char ***argv); + +///////////////////////// Time ///////////////////////// + +// Returns the result of subtracting the second timespec from the first timespec, in milliseconds. +// There is no absolute compare function, since it is assumed that a higher precision than milliseconds will not be +// needed, and cannot really be expected to be reliable. +long noh_diff_timespec_ms(const struct timespec *time1, const struct timespec *time2); + +// Returns a timespec that represents the local time with the specified number of second and milliseconds added. +// Negative values will lead to a time in the past. +struct timespec noh_get_time_in(int seconds, long milliseconds); + +// Adds the specified number of seconds and milliseconds to a timespec. +void noh_time_add(struct timespec *time, int seconds, long milliseconds); + +///////////////////////// Logging ///////////////////////// + +// An assert macro that outputs a better format for use with vim's make command. +#define noh_assert(condition) { \ + if (!(condition)) { \ + printf("%s:%i: Assertion failed: %s. \n", __FILE__, __LINE__, #condition); \ + exit(1); \ + } \ +} \ + +// Possible log levels. +typedef enum { + NOH_INFO, + NOH_WARNING, + NOH_ERROR, +} Noh_Log_Level; + +// Writes a formatted log message to stderr with the provided log level. +void noh_log(Noh_Log_Level level, const char *fmt, ...); + +///////////////////////// Dynamic array ///////////////////////// + +#define NOH_DA_INIT_CAP 256 + +// Appends an element to a dynamic array, allocates more memory and moves all elements to newly allocated memory +// if needed. +#define noh_da_append(da, elem) \ +do { \ + if ((da)->count >= (da)->capacity) { \ + (da)->capacity = (da)->capacity == 0 ? NOH_DA_INIT_CAP : (da)->capacity * 2; \ + (da)->elems = noh_realloc_check((da)->elems, (da)->capacity * sizeof(*(da)->elems)); \ + } \ + \ + (da)->elems[(da)->count++] = (elem); \ +} while(0) + +// Appends multiple elements to a dynamic array. Allocates more memory and moves all elements to newly allocated memory +// if needed. +#define noh_da_append_multiple(da, new_elems, new_elems_count) \ +do { \ + if ((da)->count + new_elems_count > (da)->capacity) { \ + if ((da)->capacity == 0) (da)->capacity = NOH_DA_INIT_CAP; \ + while ((da)->count + new_elems_count > (da)->capacity) (da)->capacity *= 2; \ + (da)->elems = noh_realloc_check((da)->elems, (da)->capacity * sizeof(*(da)->elems)); \ + } \ + \ + memcpy((da)->elems + (da)->count, new_elems, new_elems_count * sizeof(*(da)->elems)); \ + (da)->count += new_elems_count; \ +} while (0) + +// Removes the element at the specified location. +#define noh_da_remove_at(da, index) \ +do { \ + noh_assert((index) < (da)->count && "Index out of bounds."); \ + (da)->count -= 1; \ + if ((index) < (da)->count) { \ + size_t elem_size = sizeof(*(da)->elems); \ + memmove( \ + (void*)(da)->elems + (index) * elem_size, \ + (void*)(da)->elems + ((index) + 1) * elem_size, \ + ((da)->count - (index)) * elem_size); \ + } \ +} while (0) + +// Frees the elements in a dynamic array, and resets the count and capacity. +#define noh_da_free(da) \ +do { \ + if ((da)->capacity > 0) { \ + (da)->count = 0; \ + (da)->capacity = 0; \ + free((da)->elems); \ + } \ +} while (0) + +// Resets the count of a dynamic array to 0. +#define noh_da_reset(da) \ +do { \ + (da)->count = 0; \ +} while (0) + +///////////////////////// Circular buffer ///////////////////////// + +// Initializes a circular buffer, similar to a dynamic array, but adding elements should be done with noh_cb_insert. +// This call should be the only one to allocate memory to hold the data and set the capacity. +#define noh_cb_initialize(da, size) { \ + noh_assert((da)->capacity == 0 && "Cannot initialize an already initialized circular buffer."); \ + noh_assert((size) > 0 && "Cannot initialize an empty circular buffer."); \ + \ + (da)->capacity = size; \ + (da)->elems = noh_realloc_check((da)->elems, (da)->capacity * sizeof(*(da)->elems)); \ + (da)->start = 0; \ + (da)->count = 0; \ +} \ + +// Inserts an element in a dynamic array as if it is a circular buffer, will not extend beyond the capacity of the +// dynamic array but instead overwrite the oldest element. +#define noh_cb_insert(da, elem) \ +do { \ + noh_assert((da)->capacity > 0 && "Circular buffer is not initialized."); \ + \ + if ((da)->count < (da)->capacity) { \ + (da)->elems[(da)->count++] = (elem); \ + } else { \ + (da)->elems[(da)->start] = (elem); \ + (da)->start = ((da)->start + 1) % (da)->count; \ + } \ +} while(0) + +///////////////////////// Arena ///////////////////////// + +#define NOH_ARENA_INIT_CAP 1<<10 + +// Checkpoints in an arena. +typedef struct { + size_t block_id; + size_t offset_in_block; +} Noh_Arena_Checkpoint; + +typedef struct { + Noh_Arena_Checkpoint *elems; + size_t count; + size_t capacity; +} Noh_Arena_Checkpoints; + +// Data blocks in an arena. +typedef struct { + char *data; + size_t size; + size_t capacity; +} Noh_Arena_Data_Block; + +typedef struct { + Noh_Arena_Data_Block *elems; + size_t count; + size_t capacity; +} Noh_Arena_Data_Blocks; + +// An arena for storing temporary data. +typedef struct { + Noh_Arena_Data_Blocks blocks; // Blocks are always in order of increasing capacity. + Noh_Arena_Checkpoints checkpoints; + size_t active_block; // The index of the block up to which data has been allocated. +} Noh_Arena; + +// Initialize an empty arena with the specified capacity. A checkpoint is also saved at the empty arena. +Noh_Arena noh_arena_init(size_t capacity); + +// Resets the size of an arena to 0, keeping the data reserved. Any checkpoints are removed and one is saved at the +// start of the arena. Requires that the arena is initialized with noh_arena_init. +void noh_arena_reset(Noh_Arena *arena); + +// Frees all data in an arena. Any checkpoints are removed. The arena is no longer initialized, and cannot be used +// anymore. +void noh_arena_free(Noh_Arena *arena); + +// Ensures that there is room available for the requested size of data. Does not return a pointer to the data to the +// caller. Used if you want to pre-allocate a larger set of data that will later be filled by multiple allocations, +// keeping it in a single block. +void noh_arena_reserve(Noh_Arena *arena, size_t size); + +// Allocates data in an arena of the requested size, returns the start of the data. +// Requires at least one checkpoint, either from noh_arena_init, noh_arena_reset or noh_arena_save. +void *noh_arena_alloc(Noh_Arena *arena, size_t size); + +// Saves the current position in of the arena in a checkpoint. Requires that the arena is initialized with +// noh_arena_init. +void noh_arena_save(Noh_Arena *arena); + +// Rewinds an arena to the last saved checkpoint. Requires at least one checkpoint. +void noh_arena_rewind(Noh_Arena *arena); + +// Copies a c-string to the arena. +char *noh_arena_strdup(Noh_Arena *arena, const char *cstr); + +// Prints the specified formatted string to the arena. +char *noh_arena_sprintf(Noh_Arena *arena, const char *format, ...); + +///////////////////////// Strings ///////////////////////// + +// Defines a string that can be extended. +typedef struct { + char *elems; + size_t count; + size_t capacity; +} Noh_String; + +// Copies a Noh_String to the arena, and frees the Noh_String +char *noh_arena_consume_string(Noh_Arena *arena, Noh_String *string); + +// Creates a Noh_String from a c-string. +Noh_String noh_string_from_cstr(const char *cstr); + +// Appends a null-terminated string into a Noh_String. +void noh_string_append_cstr(Noh_String *string, const char *cstr); + +// Appends null into a Noh_String. +void noh_string_append_null(Noh_String *string); + +// Frees a Noh_String, freeing the memory used and settings the count and capacity to 0. +#define noh_string_free(string) noh_da_free(string) + +// Resets a Noh_String, setting the count to 0. +#define noh_string_reset(string) noh_da_reset(string) + +// Reads the contents of a file into a Noh_String. +bool noh_string_read_file(Noh_String *string, const char *filename); + +// Writes the contents of a Noh_String to a file. +bool noh_string_write_file(Noh_String *string, const char *filename); + +///////////////////////// String view ///////////////////////// + +// A view of a string, that does not own the data. +typedef struct { + size_t count; + const char *elems; +} Noh_String_View; + +// Increases the position of a string view by the specified amount, reducing its count by the same +// amount. If the end is reached, the string view will remain empty without moving further. +void noh_sv_increase_position(Noh_String_View *sv, size_t distance); + +// Finds the first occurrence of the specified delimiter in a string view and returns the part of the string until +// that delimiter. The string view itself is shrunk to start after the delimiter. +Noh_String_View noh_sv_chop_by_delim(Noh_String_View *sv, char delim); + +// Finds the first occurrence of a line separator in a string view and returns the part of the string until +// that separator. The string view itself is shrunk to start after the separator. +// Supports '/r', '/n' and '/r/n'. +Noh_String_View noh_sv_chop_line(Noh_String_View *sv); + +// Chops a string while a predicate matches. +Noh_String_View noh_sv_chop_while(Noh_String_View *sv, bool (*do_chop)(char)); + +// Chops a string by the specified distance. +Noh_String_View noh_sv_chop(Noh_String_View *sv, size_t distance); + +// Trims the left part of a string view, until the provided function no longer holds on the current character. +void noh_sv_trim_left(Noh_String_View *sv, bool (*do_trim)(char)); + +// Trims the right part of a string view, until the provided function no longer holds on the current character. +void noh_sv_trim_right(Noh_String_View *sv, bool (*do_trim)(char)); + +// Trims both sides of a string view, until the provided function no longer holds on the current character. +void noh_sv_trim(Noh_String_View *sv, bool (*do_trim)(char)); + +// Trims spaces from the left part of a string view. +inline void noh_sv_trim_space_left(Noh_String_View *sv); + +// Trims spaces from the right part of a string view. +inline void noh_sv_trim_space_right(Noh_String_View *sv); + +// Trims spaces from both sides of a string view. +inline void noh_sv_trim_space(Noh_String_View *sv); + +// Creates a string view from a c-string. +Noh_String_View noh_sv_from_cstr(const char *cstr); + +// Creates a string view from a string. +Noh_String_View noh_sv_from_string(const Noh_String *string); + +// Checks whether to string views contain the same string. +bool noh_sv_eq(Noh_String_View a, Noh_String_View b); + +// Checks whether to string views contain the same string, ignoring the case. +bool noh_sv_eq_ci(Noh_String_View a, Noh_String_View b); + +// Checks whether the first string view starts with the elements from second string view. +bool noh_sv_starts_with(Noh_String_View a, Noh_String_View b); + +// Checks whether the first string view starts with the elements from second string view, ignoring the case. +bool noh_sv_starts_with_ci(Noh_String_View a, Noh_String_View b); + +// Checks whether the first string view ends with the elements from second string view. +bool noh_sv_ends_with(Noh_String_View a, Noh_String_View b); + +// Checks whether the first string view ends with the elements from second string view, ignoring the case. +bool noh_sv_ends_with_ci(Noh_String_View a, Noh_String_View b); + +// Checks whether the first string view contains the elements from the second string view. +inline bool noh_sv_contains(Noh_String_View a, Noh_String_View b); + +// Returns the first index of the second string view in the first string view. +// Returns -1 if it is not found. +int noh_sv_index_of(Noh_String_View a, Noh_String_View b); + +// Checks whether the first string view contains the elements from the second string view, ignoring the case. +inline bool noh_sv_contains_ci(Noh_String_View a, Noh_String_View b); + +// Returns the first index of the second string view in the first string view, ignoring the case. +// Returns -1 if it is not found. +int noh_sv_index_of_ci(Noh_String_View a, Noh_String_View b); + +// Creates a cstring in an arena from a string view. +const char *noh_sv_to_arena_cstr(Noh_Arena *arena, Noh_String_View sv); + +// Creates a substring from a string-view, where the start and end are capped to the bounds of the input string view. +// If a length of 0 is provided, the entire string after start is returned. +Noh_String_View noh_sv_substring(Noh_String_View sv, size_t start, size_t length); + +// printf macros for Noh_String_View or Noh_String. +#define Nsv_Fmt "%.*s" +#define Nsv_Arg(sv) (int) (sv).count, (sv).elems +// USAGE: +// Noh_String_View name = ...; +// printf("Name: "Nsv_Fmt"\n", Nsv_Arg(name)); + +///////////////////////// Files and directories ///////////////////////// + +// File paths. +typedef struct { + char **elems; + size_t count; + size_t capacity; +} Noh_File_Paths; + +// Creates the path at the specified directory if it does not exist. +// Does not create any missing parent directories. +bool noh_mkdir_if_needed(const char *path); + +// Renames a file. +bool noh_rename(const char *path, const char *new_path); + +// Removes a file. +bool noh_remove(const char *path); + +///////////////////////// Processes ///////////////////////// + +// Process identifiers. +#ifdef _WIN32 + typedef HANDLE Noh_Pid; + #define NOH_INVALID_PROC INVALID_HANDLE_VALUE +#else + typedef pid_t Noh_Pid; + #define NOH_INVALID_PROC (-1) +#endif // _WIN32 + +// A collection of processes. +typedef struct { + Noh_Pid *elems; + size_t count; + size_t capacity; +} Noh_Procs; + +// Waits for a single process. +bool noh_proc_wait(Noh_Pid pid); + +// Waits for a collection of processes. +bool noh_procs_wait(Noh_Procs procs); + +// Frees the collection pocesses. +#define noh_procs_free(procs) noh_da_free(procs); + +// Resets the collection of processes. +#define noh_procs_reset(procs) noh_da_reset(procs); + +///////////////////////// Commands ///////////////////////// + +// Defines a command that can be run. +typedef struct { + const char **elems; + size_t count; + size_t capacity; + } Noh_Cmd; + +// Appends one or more strings to a command. +#define noh_cmd_append(cmd, ...) \ + noh_da_append_multiple( \ + cmd, \ + ((const char*[]){__VA_ARGS__}), (sizeof((const char*[]){__VA_ARGS__}) / sizeof(const char*))) + +// Frees a command, freeing the memory used for its elements and setting the count and capacity to 0. +#define noh_cmd_free(cmd) noh_da_free(cmd) + +// Resets a command, setting the count to 0. +#define noh_cmd_reset(cmd) noh_da_reset(cmd) + +// Runs a command asynchronously and returns the process id. +Noh_Pid noh_cmd_run_async(Noh_Cmd cmd); + +// Runs a command synchronously. +bool noh_cmd_run_sync(Noh_Cmd cmd); + +// Renders a textual representation of the command into the provided string. +void noh_cmd_render(Noh_Cmd cmd, Noh_String *string); + +#endif // NOH_H_ + +#ifdef NOH_IMPLEMENTATION + +///////////////////////// Core stuff ///////////////////////// + +void* noh_realloc_check_(void *target, size_t size) { + target = realloc(target, size); + noh_assert(target != NULL && "Could not allocate enough memory"); + return target; +} + +char *noh_shift_args(int *argc, char ***argv) { + noh_assert(*argc > 0 && "No more arguments"); + + char *result = **argv; + (*argv)++; + (*argc)--; + + return result; +} + +///////////////////////// Time ///////////////////////// + +long noh_diff_timespec_ms(const struct timespec *time1, const struct timespec *time2) { + noh_assert(time1); + noh_assert(time2); + + long res = 0; + // Every second adds 1000 milliseconds difference. + res += (time1->tv_sec - time2->tv_sec) * 1000; + // Every 1000 * 1000 nanoseconds add 1 millisecond difference. + res += (time1->tv_nsec - time2->tv_nsec) / 1000 / 1000; + + return res; +} + +struct timespec noh_get_time_in(int seconds, long milliseconds) { + struct timespec time; + if (clock_gettime(CLOCK_REALTIME, &time) == -1) + { + noh_log(NOH_ERROR, "Unable to get the current time: %s", strerror(errno)); + exit(1); + } + + noh_time_add(&time, seconds, milliseconds); + return time; +} + +void noh_time_add(struct timespec *time, int seconds, long milliseconds) { + static long ns_per_ms = 1000 * 1000; + time->tv_sec += seconds; + time->tv_nsec += milliseconds * ns_per_ms; + + // Fix any overflow. + if (time->tv_nsec >= 1000 * ns_per_ms) { + time->tv_sec += time->tv_nsec / (1000 * ns_per_ms); + time->tv_nsec %= 1000 * ns_per_ms; + } +} + +///////////////////////// Logging ///////////////////////// + +void noh_log(Noh_Log_Level level, const char *fmt, ...) +{ + switch (level) { + case NOH_INFO: + fprintf(stderr, "[INFO] "); + break; + case NOH_WARNING: + fprintf(stderr, "[WARNING] "); + break; + case NOH_ERROR: + fprintf(stderr, "[ERROR] "); + break; + default: + noh_assert(false && "Invalid log level"); + } + + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); +} + +///////////////////////// Arena ///////////////////////// + +// Alin a size such that it is a multiple of 8, keeping blocks of 64 bits. +size_t align_size(size_t size) { + return size + (size % 8); +} + +Noh_Arena noh_arena_init(size_t size) { + Noh_Arena arena = {0}; + + Noh_Arena_Data_Blocks blocks = {0}; + arena.blocks = blocks; + + Noh_Arena_Checkpoints checkpoints = {0}; + arena.checkpoints = checkpoints; + arena.active_block = 0; + + Noh_Arena_Data_Block block = {0}; + block.capacity = align_size(size); + block.data = noh_realloc_check(block.data, block.capacity); + block.size = 0; + noh_da_append(&arena.blocks, block); + + // Nice to have a checkpoint at the start. + noh_arena_save(&arena); + + return arena; +} + +void noh_arena_reset(Noh_Arena *arena) { + // We need to load a block and save it in the checkpoint, so at least one block needs to be allocated. + noh_assert(arena->blocks.count > 0 && "Please ensure that the arena is inintialized."); + + // Reset checkpoints. + noh_da_reset(&arena->checkpoints); + + // Insert a checkpoint at the start so we can rewind to this checkpoint. + Noh_Arena_Checkpoint start_checkpoint = {0}; + start_checkpoint.block_id = 0; + start_checkpoint.offset_in_block = 0; + noh_da_append(&arena->checkpoints, start_checkpoint); + + // Rewind to the checkpoint, and place the checkpoint back in such that there is again a checkpoint at the start. + noh_arena_rewind(arena); + arena->checkpoints.count += 1; +} + +void noh_arena_free(Noh_Arena *arena) { + // Remove checkpoints. + noh_da_free(&arena->checkpoints); + + // Free all blocks. + for (size_t i = 0; i < arena->blocks.count; i++) { + Noh_Arena_Data_Block *block = &arena->blocks.elems[i]; + free(block->data); + } + + // Remove blocks. + noh_da_free(&arena->blocks); + + arena->active_block = 0; +} + +void *noh_arena_alloc(Noh_Arena *arena, size_t size) { + // This is technically not needed, but it is nice to be consistent and ensure that there is always a checkpoint + // at the beginning, either from noh_arena_init, noh_arena_reset or noh_arena_save. + noh_assert(arena->checkpoints.count > 0 && "Please ensure that there is at least one checkpoint before allocating."); + + // Reserve will ensure that we have the required space available. Then we just need to find the block where we can + // allocate the requested space. + noh_arena_reserve(arena, size); + + // Find the block that fits the requested size. + size_t current_block = arena->active_block; + Noh_Arena_Data_Block *block = &arena->blocks.elems[current_block]; + while (block->capacity - block->size < size && current_block < arena->blocks.count) { + current_block += 1; + block = &arena->blocks.elems[current_block]; + } + + noh_assert(block->capacity - block->size >= size && "Reserve should have provided a large enough block."); + + arena->active_block = current_block; + + // Allocate data in the block and return a pointer to the start. + void *result = &block->data[block->size]; + block->size += size; + return result; +} + +void noh_arena_reserve(Noh_Arena *arena, size_t size) { + noh_assert(arena->blocks.count > 0 && "Please ensure that the arena is initialized."); + + size_t requested_size = align_size(size); + + while (arena->active_block < arena->blocks.count) { + Noh_Arena_Data_Block *block = &arena->blocks.elems[arena->active_block]; + // If the requested size fits into the current block, use it and return. + if (block->capacity - block->size >= requested_size) { + return; + } + + // If it doesn't, free the block if it was empty. Note that all but the current block will be empty, since + // rewinding sets the sizes of later blocks to 0. Current block may be empty. + if (block->size == 0) { + free(block->data); + + // This reduces arena->blocks.count, thus ensuring termination of the loop. + noh_da_remove_at(&arena->blocks, arena->active_block); + } else { + // If we're not cleaning this block up, move the pointer. + arena->active_block += 1; + } + } + + // If no block was found that fits, create a new one that is at least as big as the requested size, and twice the + // size of the current block. + // arena->active_block will now point to just beyond the last existing block. We can get the previous capacity + // only if we didn't just delete the first block. + size_t prev_cap = 0; + if (arena->active_block > 1) prev_cap = arena->blocks.elems[arena->active_block - 1].capacity; + + size_t new_cap = NOH_ARENA_INIT_CAP; + // If not big enough to double the previous cap, set to double the previous capacity. + if (prev_cap * 2 > new_cap) new_cap = prev_cap * 2; + // Keep doubling until the requested size fits. + while (requested_size > new_cap) new_cap *= 2; + + Noh_Arena_Data_Block new_block = {0}; + new_block.data = noh_realloc_check(new_block.data, new_cap); + new_block.capacity = new_cap; + new_block.size = 0; + + // After adding this block, arena->active_block will point to this new block. + noh_da_append(&(arena->blocks), new_block); +} + +void noh_arena_save(Noh_Arena *arena) { + // We need to load a block and save it in the checkpoint, so at least one block needs to be allocated. + noh_assert(arena->blocks.count > 0 && "Please ensure that the arena is inintialized."); + + Noh_Arena_Checkpoint checkpoint = {0}; + checkpoint.block_id = arena->active_block; + + Noh_Arena_Data_Block *block = &arena->blocks.elems[arena->active_block]; + checkpoint.offset_in_block = block->size; + + noh_da_append(&(arena->checkpoints), checkpoint); +} + +void noh_arena_rewind(Noh_Arena *arena) { + noh_assert(arena->checkpoints.count > 0 && "No history to rewind"); + + // Restore to block from checkpoint. + Noh_Arena_Checkpoint *checkpoint = &arena->checkpoints.elems[arena->checkpoints.count - 1]; + arena->active_block = checkpoint->block_id; + + // Rewind all blocks from the active block to the end. + for (size_t i = arena->active_block; i < arena->blocks.count; i++) { + Noh_Arena_Data_Block *block = &arena->blocks.elems[i]; + if (i == arena->active_block) block->size = checkpoint->offset_in_block; + else block->size = 0; + + } + + // Remove checkpoint. + arena->checkpoints.count -= 1; +} + +char *noh_arena_strdup(Noh_Arena *arena, const char *cstr) { + size_t len = strlen(cstr); + char *result = noh_arena_alloc(arena, len + 1); + memcpy(result, cstr, len); + result[len] = '\0'; + return result; +} + +char *noh_arena_sprintf(Noh_Arena *arena, const char *format, ...) { + va_list args; + va_start(args, format); + int n = vsnprintf(NULL, 0, format, args); + va_end(args); + + noh_assert(n >= 0); + char *result = noh_arena_alloc(arena, n + 1); + va_start(args, format); + vsnprintf(result, n + 1, format, args); + va_end(args); + + return result; +} + +///////////////////////// Strings ///////////////////////// + +char *noh_arena_consume_string(Noh_Arena *arena, Noh_String *string) { + char *result = noh_arena_alloc(arena, string->count + 1); + memcpy(result, string->elems, string->count); + result[string->count] = '\0'; + + noh_string_free(string); + return result; +} + +Noh_String noh_string_from_cstr(const char *cstr) { + Noh_String str = {0}; + noh_string_append_cstr(&str, cstr); + return str; +} + +void noh_string_append_cstr(Noh_String *string, const char *cstr) { + size_t len = strlen(cstr); + noh_da_append_multiple(string, cstr, len); +} + +void noh_string_append_null(Noh_String *string) { + noh_da_append(string, '\0'); +} + +bool noh_string_read_file(Noh_String *string, const char *filename) { + bool result = true; + size_t buf_size = 32*1024; + char *buf = NULL; + buf = noh_realloc_check(buf, buf_size); + + FILE *f = fopen(filename, "rb"); + if (f == NULL) { + noh_log(NOH_ERROR, "Could not open file %s: %s.\n", filename, strerror(errno)); + noh_return_defer(false); + } + + size_t n = fread(buf, 1, buf_size, f); + while (n > 0) { + noh_da_append_multiple(string, buf, n); + n = fread(buf, 1, buf_size, f); + } + + if (ferror(f)) { + noh_log(NOH_ERROR, "Could not read file %s: %s.\n", filename, strerror(errno)); + noh_return_defer(false); + } + +defer: + free(buf); + if (f) fclose(f); + return result; +} + +bool noh_string_write_file(Noh_String *string, const char *filename) { + bool result = true; + + FILE *f = fopen(filename, "wb"); + if (f == NULL) { + noh_log(NOH_ERROR, "Could not open file %s: %s.\n", filename, strerror(errno)); + noh_return_defer(false); + } + + int written = fprintf(f, Nsv_Fmt, Nsv_Arg(*string)); + if (written < 0) { + noh_log(NOH_ERROR, "Could not write to file %s.\n", filename); + noh_return_defer(false); + } + +defer: + if (f) fclose(f); + return result; +} + +///////////////////////// String view ///////////////////////// + +void noh_sv_increase_position(Noh_String_View *sv, size_t distance) { + if (distance < sv->count) { + sv->count -= distance; + sv->elems += distance; + } else { + sv->count = 0; + sv->elems += sv->count; + } +} + +Noh_String_View noh_sv_chop_by_delim(Noh_String_View *sv, char delim) { + size_t i = 0; + // Find the character, or the end of the string view. + while (i < sv->count && sv->elems[i] != delim) i++; + + // The data until the delimiter is returned. + Noh_String_View result = { .count = i, .elems = sv->elems }; + + // Update the current string view beyond the delimiter. + noh_sv_increase_position(sv, i + 1); + + return result; +} + +Noh_String_View noh_sv_chop_while(Noh_String_View *sv, bool (*do_chop)(char)) { + size_t i = 0; + // Keep going until the end or the function no longer matches. + while (i < sv->count && ((*do_chop)(sv->elems[i]))) i++; + + // The data until this point is returned. + Noh_String_View result = { .count = i, .elems = sv->elems }; + + // Update the current string view to after this point. + noh_sv_increase_position(sv, i); + + return result; +} + +Noh_String_View noh_sv_chop(Noh_String_View *sv, size_t distance) { + Noh_String_View result = noh_sv_substring(*sv, 0, distance); + noh_sv_increase_position(sv, distance); + return result; +} + +Noh_String_View noh_sv_chop_line(Noh_String_View *sv) { + size_t i = 0; + // Find a newline or carriage return character. + while (i < sv->count && sv->elems[i] != '\r' && sv->elems[i] != '\n') i++; + + // The data until the line separator(s) is returned. + Noh_String_View result = { .count = i, .elems = sv->elems }; + + // Update the current string view beyond the line separator(s). + if (i + 1 < sv->count && sv->elems[i] == '\r' && sv->elems[i + 1] == '\n') { + // Skip carriage return and newline. + noh_sv_increase_position(sv, i + 2); + } else { + // Skip single newline, carriage return or to the end + // (noh_sv_increase_position allows too high increases). + noh_sv_increase_position(sv, i + 1); + } + + return result; +} + +void noh_sv_trim_left(Noh_String_View *sv, bool (*do_trim)(char)) { + size_t i = 0; + while (i < sv->count && (*do_trim)(sv->elems[i])) i++; + noh_sv_increase_position(sv, i); +} + +void noh_sv_trim_right(Noh_String_View *sv, bool (*do_trim)(char)) { + size_t i = sv->count; + while (i > 0 && (*do_trim)(sv->elems[i-1])) i--; + sv->count = i; +} + +void noh_sv_trim(Noh_String_View *sv, bool (*do_trim)(char)) { + noh_sv_trim_left(sv, do_trim); + noh_sv_trim_right(sv, do_trim); +} + +bool is_space(char c) { + return isspace(c) > 0; +} + +inline void noh_sv_trim_space_left(Noh_String_View *sv) { + noh_sv_trim_left(sv, &is_space); +} + +inline void noh_sv_trim_space_right(Noh_String_View *sv) { + noh_sv_trim_right(sv, &is_space); +} + +inline void noh_sv_trim_space(Noh_String_View *sv) { + noh_sv_trim(sv, &is_space); +} + +Noh_String_View noh_sv_from_cstr(const char *cstr) { + Noh_String_View result = {0}; + result.elems = cstr; + result.count = strlen(cstr); + return result; +} + +Noh_String_View noh_sv_from_string(const Noh_String *string) { + Noh_String_View result = {0}; + result.elems = string->elems; + result.count = string->count; + return result; +} + +bool noh_sv_eq(Noh_String_View a, Noh_String_View b) { + if (a.count != b.count) return false; + + for (size_t i = 0; i < a.count; i++) { + if (a.elems[i] != b.elems[i]) return false; + } + + return true; +} + +// Check two characters case insensitively. +bool char_eq_ci(char a, char b) { + // FUTURE: Unicode support? + // A=65, Z=90 - a=97, z=122 + if (a >= 65 && a <= 90) a +=32; + if (b >= 65 && b <= 90) b +=32; + + return a == b; +} + +bool noh_sv_eq_ci(Noh_String_View a, Noh_String_View b) { + if (a.count != b.count) return false; + + for (size_t i = 0; i < a.count; i++) { + if (!char_eq_ci(a.elems[i], b.elems[i])) return false; + } + + return true; +} + +bool noh_sv_starts_with(Noh_String_View a, Noh_String_View b) { + if (a.count < b.count) return false; + a.count = b.count; + return noh_sv_eq(a, b); +} + +bool noh_sv_starts_with_ci(Noh_String_View a, Noh_String_View b) { + if (a.count < b.count) return false; + a.count = b.count; + return noh_sv_eq_ci(a, b); +} + +bool noh_sv_ends_with(Noh_String_View a, Noh_String_View b) { + if (a.count < b.count) return false; + a.elems += (a.count - b.count); + a.count = b.count; + return noh_sv_eq(a, b); +} + +bool noh_sv_ends_with_ci(Noh_String_View a, Noh_String_View b) { + if (a.count < b.count) return false; + a.elems += (a.count - b.count); + a.count = b.count; + return noh_sv_eq_ci(a, b); +} + +inline bool noh_sv_contains(Noh_String_View a, Noh_String_View b) { + return noh_sv_index_of(a, b) >= 0; +} + +int noh_sv_index_of(Noh_String_View a, Noh_String_View b) { + int i = 0; + while (a.count >= b.count) { + if (noh_sv_starts_with(a, b)) return i; + noh_sv_increase_position(&a, 1); + i++; + } + + return -1; +} + +inline bool noh_sv_contains_ci(Noh_String_View a, Noh_String_View b) { + return noh_sv_index_of_ci(a, b) >= 0; +} + +int noh_sv_index_of_ci(Noh_String_View a, Noh_String_View b) { + int i = 0; + while (a.count >= b.count) { + if (noh_sv_starts_with_ci(a, b)) return i; + noh_sv_increase_position(&a, 1); + i++; + } + + return -1; +} + +const char *noh_sv_to_arena_cstr(Noh_Arena *arena, Noh_String_View sv) +{ + char *result = noh_arena_alloc(arena, sv.count + 1); + memcpy(result, sv.elems, sv.count); + result[sv.count] = '\0'; + return result; +} + +Noh_String_View noh_sv_substring(Noh_String_View sv, size_t start, size_t length) { + Noh_String_View result = (Noh_String_View) { sv.count, sv.elems }; + noh_sv_increase_position(&result, start); + if (result.count > length && length > 0) result.count = length; + return result; +} + +///////////////////////// Files and directories ///////////////////////// + +bool noh_mkdir_if_needed(const char *path) { +#ifdef _WIN32 + int result = mkdir(path); +#else + int result = mkdir(path, 0755); +#endif // _WIN32 + + if (result == 0) { + noh_log(NOH_INFO, "Created directory '%s'.", path); + return true; + } + + if (errno == EEXIST) { + noh_log(NOH_INFO, "Directory '%s' already exists.", path); + return true; + } + + noh_log(NOH_ERROR, "Could not create directory '%s': %s", path, strerror(errno)); + return false; +} + +bool noh_rename(const char *path, const char *new_path) +{ + noh_log(NOH_INFO, "Renaming '%s' to '%s'.", path, new_path); + if (rename(path, new_path) < 0) { + noh_log(NOH_ERROR, "Rename failed: %s", strerror(errno)); + return false; + } + + return true; +} + +bool noh_remove(const char *path) { + noh_log(NOH_INFO, "Removing '%s'.", path); + if (remove(path) < 0) { + noh_log(NOH_ERROR, "Remove failed: %s", strerror(errno)); + return false; + } + + return true; +} + +///////////////////////// Processes ///////////////////////// + +bool noh_proc_wait(Noh_Pid pid) +{ + if (pid == NOH_INVALID_PROC) return false; + +#ifdef _WIN32 + DWORD result = WaitForSingleObject(pid, INFINITE); + + if (result == WAIT_FAILED) { + noh_log(NOH_ERROR, "Could not wait for command: %lu", GetLastError()); + return false; + } + + DWORD exit_status; + if (!GetExitCodeProcess(pid, &exit_status)) { + noh_log(NOH_ERROR, "Could not get command exit code: %lu", GetLastError()); + return false; + } + + if (exit_status != 0) { + noh_log(NOH_ERROR, "Command exited with exit code %lu", exit_status); + return false; + } + + CloseHandle(pid); +#else + for (;;) { + int wstatus = 0; + if (waitpid(pid, &wstatus, 0) < 0) { + noh_log(NOH_ERROR, "Could not wait for command (pid %d): %s", pid, strerror(errno)); + return false; + } + + if (WIFEXITED(wstatus)) { + int exit_status = WEXITSTATUS(wstatus); + if (exit_status != 0) { + noh_log(NOH_ERROR, "Command exited with exit code %d", exit_status); + return false; + } + + break; + } + + if (WIFSIGNALED(wstatus)) { + noh_log(NOH_ERROR, "Command process was terminated by %s", strsignal(WTERMSIG(wstatus))); + return false; + } + } + +#endif // _WIN32 + return true; +} + +bool noh_procs_wait(Noh_Procs procs) { + bool success = true; + for (size_t i = 0; i < procs.count; i++) { + success = noh_proc_wait(procs.elems[i]) && success; + } + + return success; +} + +///////////////////////// Commands ///////////////////////// + +// Adds a c string to a string, surrounding it with single quotes if it contains any spaces. +void noh_quote_if_needed(const char *value, Noh_String *string) { + if (!strchr(value, ' ')) { + noh_string_append_cstr(string, value); + } else { + noh_da_append(string, '\''); + noh_string_append_cstr(string, value); + noh_da_append(string, '\''); + } +} + +void noh_cmd_render(Noh_Cmd cmd, Noh_String *string) { + for (size_t i = 0; i < cmd.count; ++i) { + const char *arg = cmd.elems[i]; + if (arg == NULL) break; + if (i > 0) noh_string_append_cstr(string, " "); + noh_quote_if_needed(arg, string); + } +} + +Noh_Pid noh_cmd_run_async(Noh_Cmd cmd) { + if (cmd.count < 1) { + noh_log(NOH_ERROR, "Cannot run an empty command."); + return NOH_INVALID_PROC; + } + + // Log the command. + Noh_String sb = {0}; + noh_cmd_render(cmd, &sb); + noh_da_append(&sb, '\0'); + noh_log(NOH_INFO, "CMD: %s", sb.elems); + +#ifdef _WIN32 + noh_string_reset(&sb); + + // https://learn.microsoft.com/en-us/windows/win32/procthread/creating-a-child-process-with-redirected-input-and-output + STARTUPINFO suInfo; + ZeroMemory(&suInfo, sizeof(STARTUPINFO)); + suInfo.cb = sizeof(STARTUPINFO); + suInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + suInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + suInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); + suInfo.dwFlags |= STARTF_USESTDHANDLES; + + PROCESS_INFORMATION procInfo; + ZeroMemory(&procInfo, sizeof(PROCESS_INFORMATION)); + + noh_cmd_render(cmd, &sb); + noh_string_append_null(&sb); + bool success = CreateProcessA(NULL, sb.elems, NULL, NULL, true, 0, NULL, NULL, &suInfo, &procInfo); + noh_string_free(&sb); + + if (!success) { + noh_log(NOH_ERROR, "Could not create child process: %lu", GetLastError()); + return NOH_INVALID_PROC; + } + + CloseHandle(procInfo.hThread); + return procInfo.hProcess; +#else + noh_string_free(&sb); + + Noh_Pid cpid = fork(); + if (cpid < 0) { + noh_log(NOH_ERROR, "Could not fork child process: %s", strerror(errno)); + return NOH_INVALID_PROC; + } + + if (cpid == 0) { + // NOTE: This leaks a bit of memory in the child process. + // But do we actually care? It's a one off leak anyway... + // Create a command that is null terminated. + Noh_Cmd cmd_null = {0}; + noh_da_append_multiple(&cmd_null, cmd.elems, cmd.count); + noh_cmd_append(&cmd_null, NULL); + + if (execvp(cmd.elems[0], (char * const*) cmd_null.elems) < 0) { + noh_log(NOH_ERROR, "Could not execute child process: %s", strerror(errno)); + exit(1); + } + noh_assert(0 && "unreachable"); + } + + return cpid; +#endif // _WIN32 +} + +bool noh_cmd_run_sync(Noh_Cmd cmd) { + Noh_Pid pid = noh_cmd_run_async(cmd); + if (pid == NOH_INVALID_PROC) return false; + + return noh_proc_wait(pid); +} + +#endif // NOH_IMPLEMENTATION diff --git a/vendor/libmicrohttpd/include/microhttpd.h b/vendor/libmicrohttpd/include/microhttpd.h new file mode 100644 index 0000000..97c2064 --- /dev/null +++ b/vendor/libmicrohttpd/include/microhttpd.h @@ -0,0 +1,6586 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2006-2021 Christian Grothoff (and other contributing authors) + Copyright (C) 2014-2023 Evgeny Grin (Karlson2k) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * @file microhttpd.h + * @brief public interface to libmicrohttpd + * @author Christian Grothoff + * @author Karlson2k (Evgeny Grin) + * @author Chris GauthierDickey + * + * All symbols defined in this header start with MHD. MHD is a small + * HTTP daemon library. As such, it does not have any API for logging + * errors (you can only enable or disable logging to stderr). Also, + * it may not support all of the HTTP features directly, where + * applicable, portions of HTTP may have to be handled by clients of + * the library. + * + * The library is supposed to handle everything that it must handle + * (because the API would not allow clients to do this), such as basic + * connection management; however, detailed interpretations of headers + * -- such as range requests -- and HTTP methods are left to clients. + * The library does understand HEAD and will only send the headers of + * the response and not the body, even if the client supplied a body. + * The library also understands headers that control connection + * management (specifically, "Connection: close" and "Expect: 100 + * continue" are understood and handled automatically). + * + * MHD understands POST data and is able to decode certain formats + * (at the moment only "application/x-www-form-urlencoded" and + * "multipart/formdata"). Unsupported encodings and large POST + * submissions may require the application to manually process + * the stream, which is provided to the main application (and thus can be + * processed, just not conveniently by MHD). + * + * The header file defines various constants used by the HTTP protocol. + * This does not mean that MHD actually interprets all of these + * values. The provided constants are exported as a convenience + * for users of the library. MHD does not verify that transmitted + * HTTP headers are part of the standard specification; users of the + * library are free to define their own extensions of the HTTP + * standard and use those with MHD. + * + * All functions are guaranteed to be completely reentrant and + * thread-safe (with the exception of #MHD_set_connection_value, + * which must only be used in a particular context). + * + * + * @defgroup event event-loop control + * MHD API to start and stop the HTTP server and manage the event loop. + * @defgroup response generation of responses + * MHD API used to generate responses. + * @defgroup request handling of requests + * MHD API used to access information about requests. + * @defgroup authentication HTTP authentication + * MHD API related to basic and digest HTTP authentication. + * @defgroup logging logging + * MHD API to mange logging and error handling + * @defgroup specialized misc. specialized functions + * This group includes functions that do not fit into any particular + * category and that are rarely used. + */ + +#ifndef MHD_MICROHTTPD_H +#define MHD_MICROHTTPD_H + +#ifndef __cplusplus +# define MHD_C_DECLRATIONS_START_HERE_ /* Empty */ +# define MHD_C_DECLRATIONS_FINISH_HERE_ /* Empty */ +#else /* __cplusplus */ +/* *INDENT-OFF* */ +# define MHD_C_DECLRATIONS_START_HERE_ extern "C" { +# define MHD_C_DECLRATIONS_FINISH_HERE_ } +/* *INDENT-ON* */ +#endif /* __cplusplus */ + + +MHD_C_DECLRATIONS_START_HERE_ + + +/** + * Current version of the library in packed BCD form. + * @note Version number components are coded as Simple Binary-Coded Decimal + * (also called Natural BCD or BCD 8421). While they are hexadecimal numbers, + * they are parsed as decimal numbers. + * Example: 0x01093001 = 1.9.30-1. + */ +#define MHD_VERSION 0x01000500 + +/* If generic headers don't work on your platform, include headers + which define 'va_list', 'size_t', 'ssize_t', 'intptr_t', 'off_t', + 'uint8_t', 'uint16_t', 'int32_t', 'uint32_t', 'int64_t', 'uint64_t', + 'struct sockaddr', 'socklen_t', 'fd_set' and "#define MHD_PLATFORM_H" before + including "microhttpd.h". Then the following "standard" + includes won't be used (which might be a good idea, especially + on platforms where they do not exist). + */ +#ifndef MHD_PLATFORM_H +#if defined(_WIN32) && ! defined(__CYGWIN__) && \ + ! defined(_CRT_DECLARE_NONSTDC_NAMES) +/* Declare POSIX-compatible names */ +#define _CRT_DECLARE_NONSTDC_NAMES 1 +#endif /* _WIN32 && ! __CYGWIN__ && ! _CRT_DECLARE_NONSTDC_NAMES */ +#include +#include +#include +#if ! defined(_WIN32) || defined(__CYGWIN__) +#include +#include +#include +#else /* _WIN32 && ! __CYGWIN__ */ +#include +#if defined(_MSC_FULL_VER) && ! defined(_SSIZE_T_DEFINED) +#define _SSIZE_T_DEFINED +typedef intptr_t ssize_t; +#endif /* !_SSIZE_T_DEFINED */ +#endif /* _WIN32 && ! __CYGWIN__ */ +#endif + +#if defined(__CYGWIN__) && ! defined(_SYS_TYPES_FD_SET) +/* Do not define __USE_W32_SOCKETS under Cygwin! */ +#error Cygwin with winsock fd_set is not supported +#endif + +#ifdef __has_attribute +#if __has_attribute (flag_enum) +#define _MHD_FLAGS_ENUM __attribute__((flag_enum)) +#endif /* flag_enum */ +#if __has_attribute (enum_extensibility) +#define _MHD_FIXED_ENUM __attribute__((enum_extensibility (closed))) +#endif /* enum_extensibility */ +#endif /* __has_attribute */ + +#ifndef _MHD_FLAGS_ENUM +#define _MHD_FLAGS_ENUM +#endif /* _MHD_FLAGS_ENUM */ +#ifndef _MHD_FIXED_ENUM +#define _MHD_FIXED_ENUM +#endif /* _MHD_FIXED_ENUM */ + +#define _MHD_FIXED_FLAGS_ENUM _MHD_FIXED_ENUM _MHD_FLAGS_ENUM + +/** + * Operational results from MHD calls. + */ +enum MHD_Result +{ + /** + * MHD result code for "NO". + */ + MHD_NO = 0, + + /** + * MHD result code for "YES". + */ + MHD_YES = 1 + +} _MHD_FIXED_ENUM; + +/** + * Constant used to indicate unknown size (use when + * creating a response). + */ +#ifdef UINT64_MAX +#define MHD_SIZE_UNKNOWN UINT64_MAX +#else +#define MHD_SIZE_UNKNOWN ((uint64_t) -1LL) +#endif + +#define MHD_CONTENT_READER_END_OF_STREAM ((ssize_t) -1) +#define MHD_CONTENT_READER_END_WITH_ERROR ((ssize_t) -2) + +#ifndef _MHD_EXTERN +#if defined(_WIN32) && defined(MHD_W32LIB) +#define _MHD_EXTERN extern +#elif defined(_WIN32) && defined(MHD_W32DLL) +/* Define MHD_W32DLL when using MHD as W32 .DLL to speed up linker a little */ +#define _MHD_EXTERN __declspec(dllimport) +#else +#define _MHD_EXTERN extern +#endif +#endif + +#ifndef MHD_SOCKET_DEFINED +/** + * MHD_socket is type for socket FDs + */ +#if ! defined(_WIN32) || defined(_SYS_TYPES_FD_SET) +#define MHD_POSIX_SOCKETS 1 +typedef int MHD_socket; +#define MHD_INVALID_SOCKET (-1) +#else /* !defined(_WIN32) || defined(_SYS_TYPES_FD_SET) */ +#define MHD_WINSOCK_SOCKETS 1 +#include +typedef SOCKET MHD_socket; +#define MHD_INVALID_SOCKET (INVALID_SOCKET) +#endif /* !defined(_WIN32) || defined(_SYS_TYPES_FD_SET) */ +#define MHD_SOCKET_DEFINED 1 +#endif /* MHD_SOCKET_DEFINED */ + +/** + * Define MHD_NO_DEPRECATION before including "microhttpd.h" to disable deprecation messages + */ +#ifdef MHD_NO_DEPRECATION +#define _MHD_DEPR_MACRO(msg) +#define _MHD_NO_DEPR_IN_MACRO 1 +#define _MHD_DEPR_IN_MACRO(msg) +#define _MHD_NO_DEPR_FUNC 1 +#define _MHD_DEPR_FUNC(msg) +#endif /* MHD_NO_DEPRECATION */ + +#ifndef _MHD_DEPR_MACRO +#if defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1500 +/* VS 2008 or later */ +/* Stringify macros */ +#define _MHD_INSTRMACRO(a) #a +#define _MHD_STRMACRO(a) _MHD_INSTRMACRO (a) +/* deprecation message */ +#define _MHD_DEPR_MACRO(msg) \ + __pragma \ + (message (__FILE__ "(" _MHD_STRMACRO ( __LINE__) "): warning: " msg)) +#define _MHD_DEPR_IN_MACRO(msg) _MHD_DEPR_MACRO (msg) +#elif defined(__clang__) || defined(__GNUC_PATCHLEVEL__) +/* clang or GCC since 3.0 */ +#define _MHD_GCC_PRAG(x) _Pragma(#x) +#if (defined(__clang__) && \ + (__clang_major__ + 0 >= 5 || \ + (! defined(__apple_build_version__) && \ + (__clang_major__ + 0 > 3 || \ + (__clang_major__ + 0 == 3 && __clang_minor__ >= 3))))) || \ + __GNUC__ + 0 > 4 || (__GNUC__ + 0 == 4 && __GNUC_MINOR__ + 0 >= 8) +/* clang >= 3.3 (or XCode's clang >= 5.0) or + GCC >= 4.8 */ +#define _MHD_DEPR_MACRO(msg) _MHD_GCC_PRAG (GCC warning msg) +#define _MHD_DEPR_IN_MACRO(msg) _MHD_DEPR_MACRO (msg) +#else /* older clang or GCC */ +/* clang < 3.3, XCode's clang < 5.0, 3.0 <= GCC < 4.8 */ +#define _MHD_DEPR_MACRO(msg) _MHD_GCC_PRAG (message msg) +#if (defined(__clang__) && \ + (__clang_major__ + 0 > 2 || \ + (__clang_major__ + 0 == 2 && __clang_minor__ >= 9))) /* clang >= 2.9 */ +/* clang handles inline pragmas better than GCC */ +#define _MHD_DEPR_IN_MACRO(msg) _MHD_DEPR_MACRO (msg) +#endif /* clang >= 2.9 */ +#endif /* older clang or GCC */ +/* #elif defined(SOMEMACRO) */ /* add compiler-specific macros here if required */ +#endif /* clang || GCC >= 3.0 */ +#endif /* !_MHD_DEPR_MACRO */ + +#ifndef _MHD_DEPR_MACRO +#define _MHD_DEPR_MACRO(msg) +#endif /* !_MHD_DEPR_MACRO */ + +#ifndef _MHD_DEPR_IN_MACRO +#define _MHD_NO_DEPR_IN_MACRO 1 +#define _MHD_DEPR_IN_MACRO(msg) +#endif /* !_MHD_DEPR_IN_MACRO */ + +#ifndef _MHD_DEPR_FUNC +#if defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1400 +/* VS 2005 or later */ +#define _MHD_DEPR_FUNC(msg) __declspec(deprecated (msg)) +#elif defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1310 +/* VS .NET 2003 deprecation does not support custom messages */ +#define _MHD_DEPR_FUNC(msg) __declspec(deprecated) +#elif (__GNUC__ + 0 >= 5) || (defined(__clang__) && \ + (__clang_major__ + 0 > 2 || \ + (__clang_major__ + 0 == 2 && __clang_minor__ >= 9))) +/* GCC >= 5.0 or clang >= 2.9 */ +#define _MHD_DEPR_FUNC(msg) __attribute__((deprecated (msg))) +#elif defined(__clang__) || __GNUC__ + 0 > 3 || \ + (__GNUC__ + 0 == 3 && __GNUC_MINOR__ + 0 >= 1) +/* 3.1 <= GCC < 5.0 or clang < 2.9 */ +/* old GCC-style deprecation does not support custom messages */ +#define _MHD_DEPR_FUNC(msg) __attribute__((__deprecated__)) +/* #elif defined(SOMEMACRO) */ /* add compiler-specific macros here if required */ +#endif /* clang < 2.9 || GCC >= 3.1 */ +#endif /* !_MHD_DEPR_FUNC */ + +#ifndef _MHD_DEPR_FUNC +#define _MHD_NO_DEPR_FUNC 1 +#define _MHD_DEPR_FUNC(msg) +#endif /* !_MHD_DEPR_FUNC */ + +/** + * Not all architectures and `printf()`'s support the `long long` type. + * This gives the ability to replace `long long` with just a `long`, + * standard `int` or a `short`. + */ +#ifndef MHD_LONG_LONG +/** + * @deprecated use #MHD_UNSIGNED_LONG_LONG instead! + */ +#define MHD_LONG_LONG long long +#define MHD_UNSIGNED_LONG_LONG unsigned long long +#else /* MHD_LONG_LONG */ +_MHD_DEPR_MACRO ( \ + "Macro MHD_LONG_LONG is deprecated, use MHD_UNSIGNED_LONG_LONG") +#endif +/** + * Format string for printing a variable of type #MHD_LONG_LONG. + * You should only redefine this if you also define #MHD_LONG_LONG. + */ +#ifndef MHD_LONG_LONG_PRINTF +/** + * @deprecated use #MHD_UNSIGNED_LONG_LONG_PRINTF instead! + */ +#define MHD_LONG_LONG_PRINTF "ll" +#define MHD_UNSIGNED_LONG_LONG_PRINTF "%llu" +#else /* MHD_LONG_LONG_PRINTF */ +_MHD_DEPR_MACRO ( \ + "Macro MHD_LONG_LONG_PRINTF is deprecated, use MHD_UNSIGNED_LONG_LONG_PRINTF") +#endif + + +/** + * @defgroup httpcode HTTP response codes. + * These are the status codes defined for HTTP responses. + * See: https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml + * Registry export date: 2023-09-29 + * @{ + */ + +/* 100 "Continue". RFC9110, Section 15.2.1. */ +#define MHD_HTTP_CONTINUE 100 +/* 101 "Switching Protocols". RFC9110, Section 15.2.2. */ +#define MHD_HTTP_SWITCHING_PROTOCOLS 101 +/* 102 "Processing". RFC2518. */ +#define MHD_HTTP_PROCESSING 102 +/* 103 "Early Hints". RFC8297. */ +#define MHD_HTTP_EARLY_HINTS 103 + +/* 200 "OK". RFC9110, Section 15.3.1. */ +#define MHD_HTTP_OK 200 +/* 201 "Created". RFC9110, Section 15.3.2. */ +#define MHD_HTTP_CREATED 201 +/* 202 "Accepted". RFC9110, Section 15.3.3. */ +#define MHD_HTTP_ACCEPTED 202 +/* 203 "Non-Authoritative Information". RFC9110, Section 15.3.4. */ +#define MHD_HTTP_NON_AUTHORITATIVE_INFORMATION 203 +/* 204 "No Content". RFC9110, Section 15.3.5. */ +#define MHD_HTTP_NO_CONTENT 204 +/* 205 "Reset Content". RFC9110, Section 15.3.6. */ +#define MHD_HTTP_RESET_CONTENT 205 +/* 206 "Partial Content". RFC9110, Section 15.3.7. */ +#define MHD_HTTP_PARTIAL_CONTENT 206 +/* 207 "Multi-Status". RFC4918. */ +#define MHD_HTTP_MULTI_STATUS 207 +/* 208 "Already Reported". RFC5842. */ +#define MHD_HTTP_ALREADY_REPORTED 208 + +/* 226 "IM Used". RFC3229. */ +#define MHD_HTTP_IM_USED 226 + +/* 300 "Multiple Choices". RFC9110, Section 15.4.1. */ +#define MHD_HTTP_MULTIPLE_CHOICES 300 +/* 301 "Moved Permanently". RFC9110, Section 15.4.2. */ +#define MHD_HTTP_MOVED_PERMANENTLY 301 +/* 302 "Found". RFC9110, Section 15.4.3. */ +#define MHD_HTTP_FOUND 302 +/* 303 "See Other". RFC9110, Section 15.4.4. */ +#define MHD_HTTP_SEE_OTHER 303 +/* 304 "Not Modified". RFC9110, Section 15.4.5. */ +#define MHD_HTTP_NOT_MODIFIED 304 +/* 305 "Use Proxy". RFC9110, Section 15.4.6. */ +#define MHD_HTTP_USE_PROXY 305 +/* 306 "Switch Proxy". Not used! RFC9110, Section 15.4.7. */ +#define MHD_HTTP_SWITCH_PROXY 306 +/* 307 "Temporary Redirect". RFC9110, Section 15.4.8. */ +#define MHD_HTTP_TEMPORARY_REDIRECT 307 +/* 308 "Permanent Redirect". RFC9110, Section 15.4.9. */ +#define MHD_HTTP_PERMANENT_REDIRECT 308 + +/* 400 "Bad Request". RFC9110, Section 15.5.1. */ +#define MHD_HTTP_BAD_REQUEST 400 +/* 401 "Unauthorized". RFC9110, Section 15.5.2. */ +#define MHD_HTTP_UNAUTHORIZED 401 +/* 402 "Payment Required". RFC9110, Section 15.5.3. */ +#define MHD_HTTP_PAYMENT_REQUIRED 402 +/* 403 "Forbidden". RFC9110, Section 15.5.4. */ +#define MHD_HTTP_FORBIDDEN 403 +/* 404 "Not Found". RFC9110, Section 15.5.5. */ +#define MHD_HTTP_NOT_FOUND 404 +/* 405 "Method Not Allowed". RFC9110, Section 15.5.6. */ +#define MHD_HTTP_METHOD_NOT_ALLOWED 405 +/* 406 "Not Acceptable". RFC9110, Section 15.5.7. */ +#define MHD_HTTP_NOT_ACCEPTABLE 406 +/* 407 "Proxy Authentication Required". RFC9110, Section 15.5.8. */ +#define MHD_HTTP_PROXY_AUTHENTICATION_REQUIRED 407 +/* 408 "Request Timeout". RFC9110, Section 15.5.9. */ +#define MHD_HTTP_REQUEST_TIMEOUT 408 +/* 409 "Conflict". RFC9110, Section 15.5.10. */ +#define MHD_HTTP_CONFLICT 409 +/* 410 "Gone". RFC9110, Section 15.5.11. */ +#define MHD_HTTP_GONE 410 +/* 411 "Length Required". RFC9110, Section 15.5.12. */ +#define MHD_HTTP_LENGTH_REQUIRED 411 +/* 412 "Precondition Failed". RFC9110, Section 15.5.13. */ +#define MHD_HTTP_PRECONDITION_FAILED 412 +/* 413 "Content Too Large". RFC9110, Section 15.5.14. */ +#define MHD_HTTP_CONTENT_TOO_LARGE 413 +/* 414 "URI Too Long". RFC9110, Section 15.5.15. */ +#define MHD_HTTP_URI_TOO_LONG 414 +/* 415 "Unsupported Media Type". RFC9110, Section 15.5.16. */ +#define MHD_HTTP_UNSUPPORTED_MEDIA_TYPE 415 +/* 416 "Range Not Satisfiable". RFC9110, Section 15.5.17. */ +#define MHD_HTTP_RANGE_NOT_SATISFIABLE 416 +/* 417 "Expectation Failed". RFC9110, Section 15.5.18. */ +#define MHD_HTTP_EXPECTATION_FAILED 417 + + +/* 421 "Misdirected Request". RFC9110, Section 15.5.20. */ +#define MHD_HTTP_MISDIRECTED_REQUEST 421 +/* 422 "Unprocessable Content". RFC9110, Section 15.5.21. */ +#define MHD_HTTP_UNPROCESSABLE_CONTENT 422 +/* 423 "Locked". RFC4918. */ +#define MHD_HTTP_LOCKED 423 +/* 424 "Failed Dependency". RFC4918. */ +#define MHD_HTTP_FAILED_DEPENDENCY 424 +/* 425 "Too Early". RFC8470. */ +#define MHD_HTTP_TOO_EARLY 425 +/* 426 "Upgrade Required". RFC9110, Section 15.5.22. */ +#define MHD_HTTP_UPGRADE_REQUIRED 426 + +/* 428 "Precondition Required". RFC6585. */ +#define MHD_HTTP_PRECONDITION_REQUIRED 428 +/* 429 "Too Many Requests". RFC6585. */ +#define MHD_HTTP_TOO_MANY_REQUESTS 429 + +/* 431 "Request Header Fields Too Large". RFC6585. */ +#define MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE 431 + +/* 451 "Unavailable For Legal Reasons". RFC7725. */ +#define MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS 451 + +/* 500 "Internal Server Error". RFC9110, Section 15.6.1. */ +#define MHD_HTTP_INTERNAL_SERVER_ERROR 500 +/* 501 "Not Implemented". RFC9110, Section 15.6.2. */ +#define MHD_HTTP_NOT_IMPLEMENTED 501 +/* 502 "Bad Gateway". RFC9110, Section 15.6.3. */ +#define MHD_HTTP_BAD_GATEWAY 502 +/* 503 "Service Unavailable". RFC9110, Section 15.6.4. */ +#define MHD_HTTP_SERVICE_UNAVAILABLE 503 +/* 504 "Gateway Timeout". RFC9110, Section 15.6.5. */ +#define MHD_HTTP_GATEWAY_TIMEOUT 504 +/* 505 "HTTP Version Not Supported". RFC9110, Section 15.6.6. */ +#define MHD_HTTP_HTTP_VERSION_NOT_SUPPORTED 505 +/* 506 "Variant Also Negotiates". RFC2295. */ +#define MHD_HTTP_VARIANT_ALSO_NEGOTIATES 506 +/* 507 "Insufficient Storage". RFC4918. */ +#define MHD_HTTP_INSUFFICIENT_STORAGE 507 +/* 508 "Loop Detected". RFC5842. */ +#define MHD_HTTP_LOOP_DETECTED 508 + +/* 510 "Not Extended". (OBSOLETED) RFC2774; status-change-http-experiments-to-historic. */ +#define MHD_HTTP_NOT_EXTENDED 510 +/* 511 "Network Authentication Required". RFC6585. */ +#define MHD_HTTP_NETWORK_AUTHENTICATION_REQUIRED 511 + + +/* Not registered non-standard codes */ +/* 449 "Reply With". MS IIS extension. */ +#define MHD_HTTP_RETRY_WITH 449 + +/* 450 "Blocked by Windows Parental Controls". MS extension. */ +#define MHD_HTTP_BLOCKED_BY_WINDOWS_PARENTAL_CONTROLS 450 + +/* 509 "Bandwidth Limit Exceeded". Apache extension. */ +#define MHD_HTTP_BANDWIDTH_LIMIT_EXCEEDED 509 + +/* Deprecated names and codes */ +/** @deprecated */ +#define MHD_HTTP_METHOD_NOT_ACCEPTABLE _MHD_DEPR_IN_MACRO ( \ + "Value MHD_HTTP_METHOD_NOT_ACCEPTABLE is deprecated, use MHD_HTTP_NOT_ACCEPTABLE" \ + ) 406 + +/** @deprecated */ +#define MHD_HTTP_REQUEST_ENTITY_TOO_LARGE _MHD_DEPR_IN_MACRO ( \ + "Value MHD_HTTP_REQUEST_ENTITY_TOO_LARGE is deprecated, use MHD_HTTP_CONTENT_TOO_LARGE" \ + ) 413 + +/** @deprecated */ +#define MHD_HTTP_PAYLOAD_TOO_LARGE _MHD_DEPR_IN_MACRO ( \ + "Value MHD_HTTP_PAYLOAD_TOO_LARGE is deprecated use MHD_HTTP_CONTENT_TOO_LARGE" \ + ) 413 + +/** @deprecated */ +#define MHD_HTTP_REQUEST_URI_TOO_LONG _MHD_DEPR_IN_MACRO ( \ + "Value MHD_HTTP_REQUEST_URI_TOO_LONG is deprecated, use MHD_HTTP_URI_TOO_LONG" \ + ) 414 + +/** @deprecated */ +#define MHD_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE _MHD_DEPR_IN_MACRO ( \ + "Value MHD_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE is deprecated, use MHD_HTTP_RANGE_NOT_SATISFIABLE" \ + ) 416 + +/** @deprecated */ +#define MHD_HTTP_UNPROCESSABLE_ENTITY _MHD_DEPR_IN_MACRO ( \ + "Value MHD_HTTP_UNPROCESSABLE_ENTITY is deprecated, use MHD_HTTP_UNPROCESSABLE_CONTENT" \ + ) 422 + +/** @deprecated */ +#define MHD_HTTP_UNORDERED_COLLECTION _MHD_DEPR_IN_MACRO ( \ + "Value MHD_HTTP_UNORDERED_COLLECTION is deprecated as it was removed from RFC" \ + ) 425 + +/** @deprecated */ +#define MHD_HTTP_NO_RESPONSE _MHD_DEPR_IN_MACRO ( \ + "Value MHD_HTTP_NO_RESPONSE is deprecated as it is nginx internal code for logs only" \ + ) 444 + + +/** @} */ /* end of group httpcode */ + +/** + * Returns the string reason phrase for a response code. + * + * If message string is not available for a status code, + * "Unknown" string will be returned. + */ +_MHD_EXTERN const char * +MHD_get_reason_phrase_for (unsigned int code); + + +/** + * Returns the length of the string reason phrase for a response code. + * + * If message string is not available for a status code, + * 0 is returned. + */ +_MHD_EXTERN size_t +MHD_get_reason_phrase_len_for (unsigned int code); + +/** + * Flag to be or-ed with MHD_HTTP status code for + * SHOUTcast. This will cause the response to begin + * with the SHOUTcast "ICY" line instead of "HTTP/1.x". + * @ingroup specialized + */ +#define MHD_ICY_FLAG ((uint32_t) (((uint32_t) 1) << 31)) + +/** + * @defgroup headers HTTP headers + * The standard headers found in HTTP requests and responses. + * See: https://www.iana.org/assignments/http-fields/http-fields.xhtml + * Registry export date: 2023-10-02 + * @{ + */ + +/* Main HTTP headers. */ +/* Permanent. RFC9110, Section 12.5.1: HTTP Semantics */ +#define MHD_HTTP_HEADER_ACCEPT "Accept" +/* Deprecated. RFC9110, Section 12.5.2: HTTP Semantics */ +#define MHD_HTTP_HEADER_ACCEPT_CHARSET "Accept-Charset" +/* Permanent. RFC9110, Section 12.5.3: HTTP Semantics */ +#define MHD_HTTP_HEADER_ACCEPT_ENCODING "Accept-Encoding" +/* Permanent. RFC9110, Section 12.5.4: HTTP Semantics */ +#define MHD_HTTP_HEADER_ACCEPT_LANGUAGE "Accept-Language" +/* Permanent. RFC9110, Section 14.3: HTTP Semantics */ +#define MHD_HTTP_HEADER_ACCEPT_RANGES "Accept-Ranges" +/* Permanent. RFC9111, Section 5.1: HTTP Caching */ +#define MHD_HTTP_HEADER_AGE "Age" +/* Permanent. RFC9110, Section 10.2.1: HTTP Semantics */ +#define MHD_HTTP_HEADER_ALLOW "Allow" +/* Permanent. RFC9110, Section 11.6.3: HTTP Semantics */ +#define MHD_HTTP_HEADER_AUTHENTICATION_INFO "Authentication-Info" +/* Permanent. RFC9110, Section 11.6.2: HTTP Semantics */ +#define MHD_HTTP_HEADER_AUTHORIZATION "Authorization" +/* Permanent. RFC9111, Section 5.2 */ +#define MHD_HTTP_HEADER_CACHE_CONTROL "Cache-Control" +/* Permanent. RFC9112, Section 9.6: HTTP/1.1 */ +#define MHD_HTTP_HEADER_CLOSE "Close" +/* Permanent. RFC9110, Section 7.6.1: HTTP Semantics */ +#define MHD_HTTP_HEADER_CONNECTION "Connection" +/* Permanent. RFC9110, Section 8.4: HTTP Semantics */ +#define MHD_HTTP_HEADER_CONTENT_ENCODING "Content-Encoding" +/* Permanent. RFC9110, Section 8.5: HTTP Semantics */ +#define MHD_HTTP_HEADER_CONTENT_LANGUAGE "Content-Language" +/* Permanent. RFC9110, Section 8.6: HTTP Semantics */ +#define MHD_HTTP_HEADER_CONTENT_LENGTH "Content-Length" +/* Permanent. RFC9110, Section 8.7: HTTP Semantics */ +#define MHD_HTTP_HEADER_CONTENT_LOCATION "Content-Location" +/* Permanent. RFC9110, Section 14.4: HTTP Semantics */ +#define MHD_HTTP_HEADER_CONTENT_RANGE "Content-Range" +/* Permanent. RFC9110, Section 8.3: HTTP Semantics */ +#define MHD_HTTP_HEADER_CONTENT_TYPE "Content-Type" +/* Permanent. RFC9110, Section 6.6.1: HTTP Semantics */ +#define MHD_HTTP_HEADER_DATE "Date" +/* Permanent. RFC9110, Section 8.8.3: HTTP Semantics */ +#define MHD_HTTP_HEADER_ETAG "ETag" +/* Permanent. RFC9110, Section 10.1.1: HTTP Semantics */ +#define MHD_HTTP_HEADER_EXPECT "Expect" +/* Permanent. RFC9111, Section 5.3: HTTP Caching */ +#define MHD_HTTP_HEADER_EXPIRES "Expires" +/* Permanent. RFC9110, Section 10.1.2: HTTP Semantics */ +#define MHD_HTTP_HEADER_FROM "From" +/* Permanent. RFC9110, Section 7.2: HTTP Semantics */ +#define MHD_HTTP_HEADER_HOST "Host" +/* Permanent. RFC9110, Section 13.1.1: HTTP Semantics */ +#define MHD_HTTP_HEADER_IF_MATCH "If-Match" +/* Permanent. RFC9110, Section 13.1.3: HTTP Semantics */ +#define MHD_HTTP_HEADER_IF_MODIFIED_SINCE "If-Modified-Since" +/* Permanent. RFC9110, Section 13.1.2: HTTP Semantics */ +#define MHD_HTTP_HEADER_IF_NONE_MATCH "If-None-Match" +/* Permanent. RFC9110, Section 13.1.5: HTTP Semantics */ +#define MHD_HTTP_HEADER_IF_RANGE "If-Range" +/* Permanent. RFC9110, Section 13.1.4: HTTP Semantics */ +#define MHD_HTTP_HEADER_IF_UNMODIFIED_SINCE "If-Unmodified-Since" +/* Permanent. RFC9110, Section 8.8.2: HTTP Semantics */ +#define MHD_HTTP_HEADER_LAST_MODIFIED "Last-Modified" +/* Permanent. RFC9110, Section 10.2.2: HTTP Semantics */ +#define MHD_HTTP_HEADER_LOCATION "Location" +/* Permanent. RFC9110, Section 7.6.2: HTTP Semantics */ +#define MHD_HTTP_HEADER_MAX_FORWARDS "Max-Forwards" +/* Permanent. RFC9112, Appendix B.1: HTTP/1.1 */ +#define MHD_HTTP_HEADER_MIME_VERSION "MIME-Version" +/* Deprecated. RFC9111, Section 5.4: HTTP Caching */ +#define MHD_HTTP_HEADER_PRAGMA "Pragma" +/* Permanent. RFC9110, Section 11.7.1: HTTP Semantics */ +#define MHD_HTTP_HEADER_PROXY_AUTHENTICATE "Proxy-Authenticate" +/* Permanent. RFC9110, Section 11.7.3: HTTP Semantics */ +#define MHD_HTTP_HEADER_PROXY_AUTHENTICATION_INFO "Proxy-Authentication-Info" +/* Permanent. RFC9110, Section 11.7.2: HTTP Semantics */ +#define MHD_HTTP_HEADER_PROXY_AUTHORIZATION "Proxy-Authorization" +/* Permanent. RFC9110, Section 14.2: HTTP Semantics */ +#define MHD_HTTP_HEADER_RANGE "Range" +/* Permanent. RFC9110, Section 10.1.3: HTTP Semantics */ +#define MHD_HTTP_HEADER_REFERER "Referer" +/* Permanent. RFC9110, Section 10.2.3: HTTP Semantics */ +#define MHD_HTTP_HEADER_RETRY_AFTER "Retry-After" +/* Permanent. RFC9110, Section 10.2.4: HTTP Semantics */ +#define MHD_HTTP_HEADER_SERVER "Server" +/* Permanent. RFC9110, Section 10.1.4: HTTP Semantics */ +#define MHD_HTTP_HEADER_TE "TE" +/* Permanent. RFC9110, Section 6.6.2: HTTP Semantics */ +#define MHD_HTTP_HEADER_TRAILER "Trailer" +/* Permanent. RFC9112, Section 6.1: HTTP Semantics */ +#define MHD_HTTP_HEADER_TRANSFER_ENCODING "Transfer-Encoding" +/* Permanent. RFC9110, Section 7.8: HTTP Semantics */ +#define MHD_HTTP_HEADER_UPGRADE "Upgrade" +/* Permanent. RFC9110, Section 10.1.5: HTTP Semantics */ +#define MHD_HTTP_HEADER_USER_AGENT "User-Agent" +/* Permanent. RFC9110, Section 12.5.5: HTTP Semantics */ +#define MHD_HTTP_HEADER_VARY "Vary" +/* Permanent. RFC9110, Section 7.6.3: HTTP Semantics */ +#define MHD_HTTP_HEADER_VIA "Via" +/* Permanent. RFC9110, Section 11.6.1: HTTP Semantics */ +#define MHD_HTTP_HEADER_WWW_AUTHENTICATE "WWW-Authenticate" +/* Permanent. RFC9110, Section 12.5.5: HTTP Semantics */ +#define MHD_HTTP_HEADER_ASTERISK "*" + +/* Additional HTTP headers. */ +/* Permanent. RFC 3229: Delta encoding in HTTP */ +#define MHD_HTTP_HEADER_A_IM "A-IM" +/* Permanent. RFC 2324: Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0) */ +#define MHD_HTTP_HEADER_ACCEPT_ADDITIONS "Accept-Additions" +/* Permanent. RFC 8942, Section 3.1: HTTP Client Hints */ +#define MHD_HTTP_HEADER_ACCEPT_CH "Accept-CH" +/* Permanent. RFC 7089: HTTP Framework for Time-Based Access to Resource States -- Memento */ +#define MHD_HTTP_HEADER_ACCEPT_DATETIME "Accept-Datetime" +/* Permanent. RFC 2295: Transparent Content Negotiation in HTTP */ +#define MHD_HTTP_HEADER_ACCEPT_FEATURES "Accept-Features" +/* Permanent. RFC 5789: PATCH Method for HTTP */ +#define MHD_HTTP_HEADER_ACCEPT_PATCH "Accept-Patch" +/* Permanent. Linked Data Platform 1.0 */ +#define MHD_HTTP_HEADER_ACCEPT_POST "Accept-Post" +/* Permanent. RFC-ietf-httpbis-message-signatures-19, Section 5.1: HTTP Message Signatures */ +#define MHD_HTTP_HEADER_ACCEPT_SIGNATURE "Accept-Signature" +/* Permanent. Fetch */ +#define MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS \ + "Access-Control-Allow-Credentials" +/* Permanent. Fetch */ +#define MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_HEADERS \ + "Access-Control-Allow-Headers" +/* Permanent. Fetch */ +#define MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_METHODS \ + "Access-Control-Allow-Methods" +/* Permanent. Fetch */ +#define MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN \ + "Access-Control-Allow-Origin" +/* Permanent. Fetch */ +#define MHD_HTTP_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS \ + "Access-Control-Expose-Headers" +/* Permanent. Fetch */ +#define MHD_HTTP_HEADER_ACCESS_CONTROL_MAX_AGE "Access-Control-Max-Age" +/* Permanent. Fetch */ +#define MHD_HTTP_HEADER_ACCESS_CONTROL_REQUEST_HEADERS \ + "Access-Control-Request-Headers" +/* Permanent. Fetch */ +#define MHD_HTTP_HEADER_ACCESS_CONTROL_REQUEST_METHOD \ + "Access-Control-Request-Method" +/* Permanent. RFC 7639, Section 2: The ALPN HTTP Header Field */ +#define MHD_HTTP_HEADER_ALPN "ALPN" +/* Permanent. RFC 7838: HTTP Alternative Services */ +#define MHD_HTTP_HEADER_ALT_SVC "Alt-Svc" +/* Permanent. RFC 7838: HTTP Alternative Services */ +#define MHD_HTTP_HEADER_ALT_USED "Alt-Used" +/* Permanent. RFC 2295: Transparent Content Negotiation in HTTP */ +#define MHD_HTTP_HEADER_ALTERNATES "Alternates" +/* Permanent. RFC 4437: Web Distributed Authoring and Versioning (WebDAV) Redirect Reference Resources */ +#define MHD_HTTP_HEADER_APPLY_TO_REDIRECT_REF "Apply-To-Redirect-Ref" +/* Permanent. RFC 8053, Section 4: HTTP Authentication Extensions for Interactive Clients */ +#define MHD_HTTP_HEADER_AUTHENTICATION_CONTROL "Authentication-Control" +/* Permanent. RFC9211: The Cache-Status HTTP Response Header Field */ +#define MHD_HTTP_HEADER_CACHE_STATUS "Cache-Status" +/* Permanent. RFC 8607, Section 5.1: Calendaring Extensions to WebDAV (CalDAV): Managed Attachments */ +#define MHD_HTTP_HEADER_CAL_MANAGED_ID "Cal-Managed-ID" +/* Permanent. RFC 7809, Section 7.1: Calendaring Extensions to WebDAV (CalDAV): Time Zones by Reference */ +#define MHD_HTTP_HEADER_CALDAV_TIMEZONES "CalDAV-Timezones" +/* Permanent. RFC9297 */ +#define MHD_HTTP_HEADER_CAPSULE_PROTOCOL "Capsule-Protocol" +/* Permanent. RFC9213: Targeted HTTP Cache Control */ +#define MHD_HTTP_HEADER_CDN_CACHE_CONTROL "CDN-Cache-Control" +/* Permanent. RFC 8586: Loop Detection in Content Delivery Networks (CDNs) */ +#define MHD_HTTP_HEADER_CDN_LOOP "CDN-Loop" +/* Permanent. RFC 8739, Section 3.3: Support for Short-Term, Automatically Renewed (STAR) Certificates in the Automated Certificate Management Environment (ACME) */ +#define MHD_HTTP_HEADER_CERT_NOT_AFTER "Cert-Not-After" +/* Permanent. RFC 8739, Section 3.3: Support for Short-Term, Automatically Renewed (STAR) Certificates in the Automated Certificate Management Environment (ACME) */ +#define MHD_HTTP_HEADER_CERT_NOT_BEFORE "Cert-Not-Before" +/* Permanent. Clear Site Data */ +#define MHD_HTTP_HEADER_CLEAR_SITE_DATA "Clear-Site-Data" +/* Permanent. RFC9440, Section 2: Client-Cert HTTP Header Field */ +#define MHD_HTTP_HEADER_CLIENT_CERT "Client-Cert" +/* Permanent. RFC9440, Section 2: Client-Cert HTTP Header Field */ +#define MHD_HTTP_HEADER_CLIENT_CERT_CHAIN "Client-Cert-Chain" +/* Permanent. RFC-ietf-httpbis-digest-headers-13, Section 2: Digest Fields */ +#define MHD_HTTP_HEADER_CONTENT_DIGEST "Content-Digest" +/* Permanent. RFC 6266: Use of the Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP) */ +#define MHD_HTTP_HEADER_CONTENT_DISPOSITION "Content-Disposition" +/* Permanent. The HTTP Distribution and Replication Protocol */ +#define MHD_HTTP_HEADER_CONTENT_ID "Content-ID" +/* Permanent. Content Security Policy Level 3 */ +#define MHD_HTTP_HEADER_CONTENT_SECURITY_POLICY "Content-Security-Policy" +/* Permanent. Content Security Policy Level 3 */ +#define MHD_HTTP_HEADER_CONTENT_SECURITY_POLICY_REPORT_ONLY \ + "Content-Security-Policy-Report-Only" +/* Permanent. RFC 6265: HTTP State Management Mechanism */ +#define MHD_HTTP_HEADER_COOKIE "Cookie" +/* Permanent. HTML */ +#define MHD_HTTP_HEADER_CROSS_ORIGIN_EMBEDDER_POLICY \ + "Cross-Origin-Embedder-Policy" +/* Permanent. HTML */ +#define MHD_HTTP_HEADER_CROSS_ORIGIN_EMBEDDER_POLICY_REPORT_ONLY \ + "Cross-Origin-Embedder-Policy-Report-Only" +/* Permanent. HTML */ +#define MHD_HTTP_HEADER_CROSS_ORIGIN_OPENER_POLICY "Cross-Origin-Opener-Policy" +/* Permanent. HTML */ +#define MHD_HTTP_HEADER_CROSS_ORIGIN_OPENER_POLICY_REPORT_ONLY \ + "Cross-Origin-Opener-Policy-Report-Only" +/* Permanent. Fetch */ +#define MHD_HTTP_HEADER_CROSS_ORIGIN_RESOURCE_POLICY \ + "Cross-Origin-Resource-Policy" +/* Permanent. RFC 5323: Web Distributed Authoring and Versioning (WebDAV) SEARCH */ +#define MHD_HTTP_HEADER_DASL "DASL" +/* Permanent. RFC 4918: HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV) */ +#define MHD_HTTP_HEADER_DAV "DAV" +/* Permanent. RFC 3229: Delta encoding in HTTP */ +#define MHD_HTTP_HEADER_DELTA_BASE "Delta-Base" +/* Permanent. RFC 4918: HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV) */ +#define MHD_HTTP_HEADER_DEPTH "Depth" +/* Permanent. RFC 4918: HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV) */ +#define MHD_HTTP_HEADER_DESTINATION "Destination" +/* Permanent. The HTTP Distribution and Replication Protocol */ +#define MHD_HTTP_HEADER_DIFFERENTIAL_ID "Differential-ID" +/* Permanent. RFC9449: OAuth 2.0 Demonstrating Proof of Possession (DPoP) */ +#define MHD_HTTP_HEADER_DPOP "DPoP" +/* Permanent. RFC9449: OAuth 2.0 Demonstrating Proof of Possession (DPoP) */ +#define MHD_HTTP_HEADER_DPOP_NONCE "DPoP-Nonce" +/* Permanent. RFC 8470: Using Early Data in HTTP */ +#define MHD_HTTP_HEADER_EARLY_DATA "Early-Data" +/* Permanent. RFC9163: Expect-CT Extension for HTTP */ +#define MHD_HTTP_HEADER_EXPECT_CT "Expect-CT" +/* Permanent. RFC 7239: Forwarded HTTP Extension */ +#define MHD_HTTP_HEADER_FORWARDED "Forwarded" +/* Permanent. RFC 7486, Section 6.1.1: HTTP Origin-Bound Authentication (HOBA) */ +#define MHD_HTTP_HEADER_HOBAREG "Hobareg" +/* Permanent. RFC 4918: HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV) */ +#define MHD_HTTP_HEADER_IF "If" +/* Permanent. RFC 6338: Scheduling Extensions to CalDAV */ +#define MHD_HTTP_HEADER_IF_SCHEDULE_TAG_MATCH "If-Schedule-Tag-Match" +/* Permanent. RFC 3229: Delta encoding in HTTP */ +#define MHD_HTTP_HEADER_IM "IM" +/* Permanent. RFC 8473: Token Binding over HTTP */ +#define MHD_HTTP_HEADER_INCLUDE_REFERRED_TOKEN_BINDING_ID \ + "Include-Referred-Token-Binding-ID" +/* Permanent. RFC 2068: Hypertext Transfer Protocol -- HTTP/1.1 */ +#define MHD_HTTP_HEADER_KEEP_ALIVE "Keep-Alive" +/* Permanent. RFC 3253: Versioning Extensions to WebDAV: (Web Distributed Authoring and Versioning) */ +#define MHD_HTTP_HEADER_LABEL "Label" +/* Permanent. HTML */ +#define MHD_HTTP_HEADER_LAST_EVENT_ID "Last-Event-ID" +/* Permanent. RFC 8288: Web Linking */ +#define MHD_HTTP_HEADER_LINK "Link" +/* Permanent. RFC 4918: HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV) */ +#define MHD_HTTP_HEADER_LOCK_TOKEN "Lock-Token" +/* Permanent. RFC 7089: HTTP Framework for Time-Based Access to Resource States -- Memento */ +#define MHD_HTTP_HEADER_MEMENTO_DATETIME "Memento-Datetime" +/* Permanent. RFC 2227: Simple Hit-Metering and Usage-Limiting for HTTP */ +#define MHD_HTTP_HEADER_METER "Meter" +/* Permanent. RFC 2295: Transparent Content Negotiation in HTTP */ +#define MHD_HTTP_HEADER_NEGOTIATE "Negotiate" +/* Permanent. Network Error Logging */ +#define MHD_HTTP_HEADER_NEL "NEL" +/* Permanent. OData Version 4.01 Part 1: Protocol; OASIS; Chet_Ensign */ +#define MHD_HTTP_HEADER_ODATA_ENTITYID "OData-EntityId" +/* Permanent. OData Version 4.01 Part 1: Protocol; OASIS; Chet_Ensign */ +#define MHD_HTTP_HEADER_ODATA_ISOLATION "OData-Isolation" +/* Permanent. OData Version 4.01 Part 1: Protocol; OASIS; Chet_Ensign */ +#define MHD_HTTP_HEADER_ODATA_MAXVERSION "OData-MaxVersion" +/* Permanent. OData Version 4.01 Part 1: Protocol; OASIS; Chet_Ensign */ +#define MHD_HTTP_HEADER_ODATA_VERSION "OData-Version" +/* Permanent. RFC 8053, Section 3: HTTP Authentication Extensions for Interactive Clients */ +#define MHD_HTTP_HEADER_OPTIONAL_WWW_AUTHENTICATE "Optional-WWW-Authenticate" +/* Permanent. RFC 3648: Web Distributed Authoring and Versioning (WebDAV) Ordered Collections Protocol */ +#define MHD_HTTP_HEADER_ORDERING_TYPE "Ordering-Type" +/* Permanent. RFC 6454: The Web Origin Concept */ +#define MHD_HTTP_HEADER_ORIGIN "Origin" +/* Permanent. HTML */ +#define MHD_HTTP_HEADER_ORIGIN_AGENT_CLUSTER "Origin-Agent-Cluster" +/* Permanent. RFC 8613, Section 11.1: Object Security for Constrained RESTful Environments (OSCORE) */ +#define MHD_HTTP_HEADER_OSCORE "OSCORE" +/* Permanent. OASIS Project Specification 01; OASIS; Chet_Ensign */ +#define MHD_HTTP_HEADER_OSLC_CORE_VERSION "OSLC-Core-Version" +/* Permanent. RFC 4918: HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV) */ +#define MHD_HTTP_HEADER_OVERWRITE "Overwrite" +/* Permanent. HTML */ +#define MHD_HTTP_HEADER_PING_FROM "Ping-From" +/* Permanent. HTML */ +#define MHD_HTTP_HEADER_PING_TO "Ping-To" +/* Permanent. RFC 3648: Web Distributed Authoring and Versioning (WebDAV) Ordered Collections Protocol */ +#define MHD_HTTP_HEADER_POSITION "Position" +/* Permanent. RFC 7240: Prefer Header for HTTP */ +#define MHD_HTTP_HEADER_PREFER "Prefer" +/* Permanent. RFC 7240: Prefer Header for HTTP */ +#define MHD_HTTP_HEADER_PREFERENCE_APPLIED "Preference-Applied" +/* Permanent. RFC9218: Extensible Prioritization Scheme for HTTP */ +#define MHD_HTTP_HEADER_PRIORITY "Priority" +/* Permanent. RFC9209: The Proxy-Status HTTP Response Header Field */ +#define MHD_HTTP_HEADER_PROXY_STATUS "Proxy-Status" +/* Permanent. RFC 7469: Public Key Pinning Extension for HTTP */ +#define MHD_HTTP_HEADER_PUBLIC_KEY_PINS "Public-Key-Pins" +/* Permanent. RFC 7469: Public Key Pinning Extension for HTTP */ +#define MHD_HTTP_HEADER_PUBLIC_KEY_PINS_REPORT_ONLY \ + "Public-Key-Pins-Report-Only" +/* Permanent. RFC 4437: Web Distributed Authoring and Versioning (WebDAV) Redirect Reference Resources */ +#define MHD_HTTP_HEADER_REDIRECT_REF "Redirect-Ref" +/* Permanent. HTML */ +#define MHD_HTTP_HEADER_REFRESH "Refresh" +/* Permanent. RFC 8555, Section 6.5.1: Automatic Certificate Management Environment (ACME) */ +#define MHD_HTTP_HEADER_REPLAY_NONCE "Replay-Nonce" +/* Permanent. RFC-ietf-httpbis-digest-headers-13, Section 3: Digest Fields */ +#define MHD_HTTP_HEADER_REPR_DIGEST "Repr-Digest" +/* Permanent. RFC 6638: Scheduling Extensions to CalDAV */ +#define MHD_HTTP_HEADER_SCHEDULE_REPLY "Schedule-Reply" +/* Permanent. RFC 6338: Scheduling Extensions to CalDAV */ +#define MHD_HTTP_HEADER_SCHEDULE_TAG "Schedule-Tag" +/* Permanent. Fetch */ +#define MHD_HTTP_HEADER_SEC_PURPOSE "Sec-Purpose" +/* Permanent. RFC 8473: Token Binding over HTTP */ +#define MHD_HTTP_HEADER_SEC_TOKEN_BINDING "Sec-Token-Binding" +/* Permanent. RFC 6455: The WebSocket Protocol */ +#define MHD_HTTP_HEADER_SEC_WEBSOCKET_ACCEPT "Sec-WebSocket-Accept" +/* Permanent. RFC 6455: The WebSocket Protocol */ +#define MHD_HTTP_HEADER_SEC_WEBSOCKET_EXTENSIONS "Sec-WebSocket-Extensions" +/* Permanent. RFC 6455: The WebSocket Protocol */ +#define MHD_HTTP_HEADER_SEC_WEBSOCKET_KEY "Sec-WebSocket-Key" +/* Permanent. RFC 6455: The WebSocket Protocol */ +#define MHD_HTTP_HEADER_SEC_WEBSOCKET_PROTOCOL "Sec-WebSocket-Protocol" +/* Permanent. RFC 6455: The WebSocket Protocol */ +#define MHD_HTTP_HEADER_SEC_WEBSOCKET_VERSION "Sec-WebSocket-Version" +/* Permanent. Server Timing */ +#define MHD_HTTP_HEADER_SERVER_TIMING "Server-Timing" +/* Permanent. RFC 6265: HTTP State Management Mechanism */ +#define MHD_HTTP_HEADER_SET_COOKIE "Set-Cookie" +/* Permanent. RFC-ietf-httpbis-message-signatures-19, Section 4.2: HTTP Message Signatures */ +#define MHD_HTTP_HEADER_SIGNATURE "Signature" +/* Permanent. RFC-ietf-httpbis-message-signatures-19, Section 4.1: HTTP Message Signatures */ +#define MHD_HTTP_HEADER_SIGNATURE_INPUT "Signature-Input" +/* Permanent. RFC 5023: The Atom Publishing Protocol */ +#define MHD_HTTP_HEADER_SLUG "SLUG" +/* Permanent. Simple Object Access Protocol (SOAP) 1.1 */ +#define MHD_HTTP_HEADER_SOAPACTION "SoapAction" +/* Permanent. RFC 2518: HTTP Extensions for Distributed Authoring -- WEBDAV */ +#define MHD_HTTP_HEADER_STATUS_URI "Status-URI" +/* Permanent. RFC 6797: HTTP Strict Transport Security (HSTS) */ +#define MHD_HTTP_HEADER_STRICT_TRANSPORT_SECURITY "Strict-Transport-Security" +/* Permanent. RFC 8594: The Sunset HTTP Header Field */ +#define MHD_HTTP_HEADER_SUNSET "Sunset" +/* Permanent. Edge Architecture Specification */ +#define MHD_HTTP_HEADER_SURROGATE_CAPABILITY "Surrogate-Capability" +/* Permanent. Edge Architecture Specification */ +#define MHD_HTTP_HEADER_SURROGATE_CONTROL "Surrogate-Control" +/* Permanent. RFC 2295: Transparent Content Negotiation in HTTP */ +#define MHD_HTTP_HEADER_TCN "TCN" +/* Permanent. RFC 4918: HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV) */ +#define MHD_HTTP_HEADER_TIMEOUT "Timeout" +/* Permanent. RFC 8030, Section 5.4: Generic Event Delivery Using HTTP Push */ +#define MHD_HTTP_HEADER_TOPIC "Topic" +/* Permanent. Trace Context */ +#define MHD_HTTP_HEADER_TRACEPARENT "Traceparent" +/* Permanent. Trace Context */ +#define MHD_HTTP_HEADER_TRACESTATE "Tracestate" +/* Permanent. RFC 8030, Section 5.2: Generic Event Delivery Using HTTP Push */ +#define MHD_HTTP_HEADER_TTL "TTL" +/* Permanent. RFC 8030, Section 5.3: Generic Event Delivery Using HTTP Push */ +#define MHD_HTTP_HEADER_URGENCY "Urgency" +/* Permanent. RFC 2295: Transparent Content Negotiation in HTTP */ +#define MHD_HTTP_HEADER_VARIANT_VARY "Variant-Vary" +/* Permanent. RFC-ietf-httpbis-digest-headers-13, Section 4: Digest Fields */ +#define MHD_HTTP_HEADER_WANT_CONTENT_DIGEST "Want-Content-Digest" +/* Permanent. RFC-ietf-httpbis-digest-headers-13, Section 4: Digest Fields */ +#define MHD_HTTP_HEADER_WANT_REPR_DIGEST "Want-Repr-Digest" +/* Permanent. Fetch */ +#define MHD_HTTP_HEADER_X_CONTENT_TYPE_OPTIONS "X-Content-Type-Options" +/* Permanent. HTML */ +#define MHD_HTTP_HEADER_X_FRAME_OPTIONS "X-Frame-Options" +/* Provisional. AMP-Cache-Transform HTTP request header */ +#define MHD_HTTP_HEADER_AMP_CACHE_TRANSFORM "AMP-Cache-Transform" +/* Provisional. OSLC Configuration Management Version 1.0. Part 3: Configuration Specification */ +#define MHD_HTTP_HEADER_CONFIGURATION_CONTEXT "Configuration-Context" +/* Provisional. RFC 6017: Electronic Data Interchange - Internet Integration (EDIINT) Features Header Field */ +#define MHD_HTTP_HEADER_EDIINT_FEATURES "EDIINT-Features" +/* Provisional. OData Version 4.01 Part 1: Protocol; OASIS; Chet_Ensign */ +#define MHD_HTTP_HEADER_ISOLATION "Isolation" +/* Provisional. Permissions Policy */ +#define MHD_HTTP_HEADER_PERMISSIONS_POLICY "Permissions-Policy" +/* Provisional. Repeatable Requests Version 1.0; OASIS; Chet_Ensign */ +#define MHD_HTTP_HEADER_REPEATABILITY_CLIENT_ID "Repeatability-Client-ID" +/* Provisional. Repeatable Requests Version 1.0; OASIS; Chet_Ensign */ +#define MHD_HTTP_HEADER_REPEATABILITY_FIRST_SENT "Repeatability-First-Sent" +/* Provisional. Repeatable Requests Version 1.0; OASIS; Chet_Ensign */ +#define MHD_HTTP_HEADER_REPEATABILITY_REQUEST_ID "Repeatability-Request-ID" +/* Provisional. Repeatable Requests Version 1.0; OASIS; Chet_Ensign */ +#define MHD_HTTP_HEADER_REPEATABILITY_RESULT "Repeatability-Result" +/* Provisional. Reporting API */ +#define MHD_HTTP_HEADER_REPORTING_ENDPOINTS "Reporting-Endpoints" +/* Provisional. Global Privacy Control (GPC) */ +#define MHD_HTTP_HEADER_SEC_GPC "Sec-GPC" +/* Provisional. Resource Timing Level 1 */ +#define MHD_HTTP_HEADER_TIMING_ALLOW_ORIGIN "Timing-Allow-Origin" +/* Deprecated. PEP - an Extension Mechanism for HTTP; status-change-http-experiments-to-historic */ +#define MHD_HTTP_HEADER_C_PEP_INFO "C-PEP-Info" +/* Deprecated. White Paper: Joint Electronic Payment Initiative */ +#define MHD_HTTP_HEADER_PROTOCOL_INFO "Protocol-Info" +/* Deprecated. White Paper: Joint Electronic Payment Initiative */ +#define MHD_HTTP_HEADER_PROTOCOL_QUERY "Protocol-Query" +/* Obsoleted. Access Control for Cross-site Requests */ +#define MHD_HTTP_HEADER_ACCESS_CONTROL "Access-Control" +/* Obsoleted. RFC 2774: An HTTP Extension Framework; status-change-http-experiments-to-historic */ +#define MHD_HTTP_HEADER_C_EXT "C-Ext" +/* Obsoleted. RFC 2774: An HTTP Extension Framework; status-change-http-experiments-to-historic */ +#define MHD_HTTP_HEADER_C_MAN "C-Man" +/* Obsoleted. RFC 2774: An HTTP Extension Framework; status-change-http-experiments-to-historic */ +#define MHD_HTTP_HEADER_C_OPT "C-Opt" +/* Obsoleted. PEP - an Extension Mechanism for HTTP; status-change-http-experiments-to-historic */ +#define MHD_HTTP_HEADER_C_PEP "C-PEP" +/* Obsoleted. RFC 2068: Hypertext Transfer Protocol -- HTTP/1.1; RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1 */ +#define MHD_HTTP_HEADER_CONTENT_BASE "Content-Base" +/* Obsoleted. RFC 2616, Section 14.15: Hypertext Transfer Protocol -- HTTP/1.1; RFC 7231, Appendix B: Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content */ +#define MHD_HTTP_HEADER_CONTENT_MD5 "Content-MD5" +/* Obsoleted. HTML 4.01 Specification */ +#define MHD_HTTP_HEADER_CONTENT_SCRIPT_TYPE "Content-Script-Type" +/* Obsoleted. HTML 4.01 Specification */ +#define MHD_HTTP_HEADER_CONTENT_STYLE_TYPE "Content-Style-Type" +/* Obsoleted. RFC 2068: Hypertext Transfer Protocol -- HTTP/1.1 */ +#define MHD_HTTP_HEADER_CONTENT_VERSION "Content-Version" +/* Obsoleted. RFC 2965: HTTP State Management Mechanism; RFC 6265: HTTP State Management Mechanism */ +#define MHD_HTTP_HEADER_COOKIE2 "Cookie2" +/* Obsoleted. HTML 4.01 Specification */ +#define MHD_HTTP_HEADER_DEFAULT_STYLE "Default-Style" +/* Obsoleted. RFC 2068: Hypertext Transfer Protocol -- HTTP/1.1 */ +#define MHD_HTTP_HEADER_DERIVED_FROM "Derived-From" +/* Obsoleted. RFC 3230: Instance Digests in HTTP; RFC-ietf-httpbis-digest-headers-13, Section 1.3: Digest Fields */ +#define MHD_HTTP_HEADER_DIGEST "Digest" +/* Obsoleted. RFC 2774: An HTTP Extension Framework; status-change-http-experiments-to-historic */ +#define MHD_HTTP_HEADER_EXT "Ext" +/* Obsoleted. Implementation of OPS Over HTTP */ +#define MHD_HTTP_HEADER_GETPROFILE "GetProfile" +/* Obsoleted. RFC 7540, Section 3.2.1: Hypertext Transfer Protocol Version 2 (HTTP/2) */ +#define MHD_HTTP_HEADER_HTTP2_SETTINGS "HTTP2-Settings" +/* Obsoleted. RFC 2774: An HTTP Extension Framework; status-change-http-experiments-to-historic */ +#define MHD_HTTP_HEADER_MAN "Man" +/* Obsoleted. Access Control for Cross-site Requests */ +#define MHD_HTTP_HEADER_METHOD_CHECK "Method-Check" +/* Obsoleted. Access Control for Cross-site Requests */ +#define MHD_HTTP_HEADER_METHOD_CHECK_EXPIRES "Method-Check-Expires" +/* Obsoleted. RFC 2774: An HTTP Extension Framework; status-change-http-experiments-to-historic */ +#define MHD_HTTP_HEADER_OPT "Opt" +/* Obsoleted. The Platform for Privacy Preferences 1.0 (P3P1.0) Specification */ +#define MHD_HTTP_HEADER_P3P "P3P" +/* Obsoleted. PEP - an Extension Mechanism for HTTP */ +#define MHD_HTTP_HEADER_PEP "PEP" +/* Obsoleted. PEP - an Extension Mechanism for HTTP */ +#define MHD_HTTP_HEADER_PEP_INFO "Pep-Info" +/* Obsoleted. PICS Label Distribution Label Syntax and Communication Protocols */ +#define MHD_HTTP_HEADER_PICS_LABEL "PICS-Label" +/* Obsoleted. Implementation of OPS Over HTTP */ +#define MHD_HTTP_HEADER_PROFILEOBJECT "ProfileObject" +/* Obsoleted. PICS Label Distribution Label Syntax and Communication Protocols */ +#define MHD_HTTP_HEADER_PROTOCOL "Protocol" +/* Obsoleted. PICS Label Distribution Label Syntax and Communication Protocols */ +#define MHD_HTTP_HEADER_PROTOCOL_REQUEST "Protocol-Request" +/* Obsoleted. Notification for Proxy Caches */ +#define MHD_HTTP_HEADER_PROXY_FEATURES "Proxy-Features" +/* Obsoleted. Notification for Proxy Caches */ +#define MHD_HTTP_HEADER_PROXY_INSTRUCTION "Proxy-Instruction" +/* Obsoleted. RFC 2068: Hypertext Transfer Protocol -- HTTP/1.1 */ +#define MHD_HTTP_HEADER_PUBLIC "Public" +/* Obsoleted. Access Control for Cross-site Requests */ +#define MHD_HTTP_HEADER_REFERER_ROOT "Referer-Root" +/* Obsoleted. RFC 2310: The Safe Response Header Field; status-change-http-experiments-to-historic */ +#define MHD_HTTP_HEADER_SAFE "Safe" +/* Obsoleted. RFC 2660: The Secure HyperText Transfer Protocol; status-change-http-experiments-to-historic */ +#define MHD_HTTP_HEADER_SECURITY_SCHEME "Security-Scheme" +/* Obsoleted. RFC 2965: HTTP State Management Mechanism; RFC 6265: HTTP State Management Mechanism */ +#define MHD_HTTP_HEADER_SET_COOKIE2 "Set-Cookie2" +/* Obsoleted. Implementation of OPS Over HTTP */ +#define MHD_HTTP_HEADER_SETPROFILE "SetProfile" +/* Obsoleted. RFC 2068: Hypertext Transfer Protocol -- HTTP/1.1 */ +#define MHD_HTTP_HEADER_URI "URI" +/* Obsoleted. RFC 3230: Instance Digests in HTTP; RFC-ietf-httpbis-digest-headers-13, Section 1.3: Digest Fields */ +#define MHD_HTTP_HEADER_WANT_DIGEST "Want-Digest" +/* Obsoleted. RFC9111, Section 5.5: HTTP Caching */ +#define MHD_HTTP_HEADER_WARNING "Warning" + +/* Headers removed from the registry. Do not use! */ +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_COMPLIANCE "Compliance" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_CONTENT_TRANSFER_ENCODING "Content-Transfer-Encoding" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_COST "Cost" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_MESSAGE_ID "Message-ID" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_NON_COMPLIANCE "Non-Compliance" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_OPTIONAL "Optional" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_RESOLUTION_HINT "Resolution-Hint" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_RESOLVER_LOCATION "Resolver-Location" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_SUBOK "SubOK" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_SUBST "Subst" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_TITLE "Title" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_UA_COLOR "UA-Color" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_UA_MEDIA "UA-Media" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_UA_PIXELS "UA-Pixels" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_UA_RESOLUTION "UA-Resolution" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_UA_WINDOWPIXELS "UA-Windowpixels" +/* Obsoleted. RFC4229 */ +#define MHD_HTTP_HEADER_VERSION "Version" +/* Obsoleted. W3C Mobile Web Best Practices Working Group */ +#define MHD_HTTP_HEADER_X_DEVICE_ACCEPT "X-Device-Accept" +/* Obsoleted. W3C Mobile Web Best Practices Working Group */ +#define MHD_HTTP_HEADER_X_DEVICE_ACCEPT_CHARSET "X-Device-Accept-Charset" +/* Obsoleted. W3C Mobile Web Best Practices Working Group */ +#define MHD_HTTP_HEADER_X_DEVICE_ACCEPT_ENCODING "X-Device-Accept-Encoding" +/* Obsoleted. W3C Mobile Web Best Practices Working Group */ +#define MHD_HTTP_HEADER_X_DEVICE_ACCEPT_LANGUAGE "X-Device-Accept-Language" +/* Obsoleted. W3C Mobile Web Best Practices Working Group */ +#define MHD_HTTP_HEADER_X_DEVICE_USER_AGENT "X-Device-User-Agent" + +/** @} */ /* end of group headers */ + +/** + * @defgroup versions HTTP versions + * These strings should be used to match against the first line of the + * HTTP header. + * @{ + */ +#define MHD_HTTP_VERSION_1_0 "HTTP/1.0" +#define MHD_HTTP_VERSION_1_1 "HTTP/1.1" + +/** @} */ /* end of group versions */ + +/** + * @defgroup methods HTTP methods + * HTTP methods (as strings). + * See: https://www.iana.org/assignments/http-methods/http-methods.xml + * Registry export date: 2023-10-02 + * @{ + */ + +/* Main HTTP methods. */ +/* Safe. Idempotent. RFC9110, Section 9.3.1. */ +#define MHD_HTTP_METHOD_GET "GET" +/* Safe. Idempotent. RFC9110, Section 9.3.2. */ +#define MHD_HTTP_METHOD_HEAD "HEAD" +/* Not safe. Not idempotent. RFC9110, Section 9.3.3. */ +#define MHD_HTTP_METHOD_POST "POST" +/* Not safe. Idempotent. RFC9110, Section 9.3.4. */ +#define MHD_HTTP_METHOD_PUT "PUT" +/* Not safe. Idempotent. RFC9110, Section 9.3.5. */ +#define MHD_HTTP_METHOD_DELETE "DELETE" +/* Not safe. Not idempotent. RFC9110, Section 9.3.6. */ +#define MHD_HTTP_METHOD_CONNECT "CONNECT" +/* Safe. Idempotent. RFC9110, Section 9.3.7. */ +#define MHD_HTTP_METHOD_OPTIONS "OPTIONS" +/* Safe. Idempotent. RFC9110, Section 9.3.8. */ +#define MHD_HTTP_METHOD_TRACE "TRACE" + +/* Additional HTTP methods. */ +/* Not safe. Idempotent. RFC3744, Section 8.1. */ +#define MHD_HTTP_METHOD_ACL "ACL" +/* Not safe. Idempotent. RFC3253, Section 12.6. */ +#define MHD_HTTP_METHOD_BASELINE_CONTROL "BASELINE-CONTROL" +/* Not safe. Idempotent. RFC5842, Section 4. */ +#define MHD_HTTP_METHOD_BIND "BIND" +/* Not safe. Idempotent. RFC3253, Section 4.4, Section 9.4. */ +#define MHD_HTTP_METHOD_CHECKIN "CHECKIN" +/* Not safe. Idempotent. RFC3253, Section 4.3, Section 8.8. */ +#define MHD_HTTP_METHOD_CHECKOUT "CHECKOUT" +/* Not safe. Idempotent. RFC4918, Section 9.8. */ +#define MHD_HTTP_METHOD_COPY "COPY" +/* Not safe. Idempotent. RFC3253, Section 8.2. */ +#define MHD_HTTP_METHOD_LABEL "LABEL" +/* Not safe. Idempotent. RFC2068, Section 19.6.1.2. */ +#define MHD_HTTP_METHOD_LINK "LINK" +/* Not safe. Not idempotent. RFC4918, Section 9.10. */ +#define MHD_HTTP_METHOD_LOCK "LOCK" +/* Not safe. Idempotent. RFC3253, Section 11.2. */ +#define MHD_HTTP_METHOD_MERGE "MERGE" +/* Not safe. Idempotent. RFC3253, Section 13.5. */ +#define MHD_HTTP_METHOD_MKACTIVITY "MKACTIVITY" +/* Not safe. Idempotent. RFC4791, Section 5.3.1; RFC8144, Section 2.3. */ +#define MHD_HTTP_METHOD_MKCALENDAR "MKCALENDAR" +/* Not safe. Idempotent. RFC4918, Section 9.3; RFC5689, Section 3; RFC8144, Section 2.3. */ +#define MHD_HTTP_METHOD_MKCOL "MKCOL" +/* Not safe. Idempotent. RFC4437, Section 6. */ +#define MHD_HTTP_METHOD_MKREDIRECTREF "MKREDIRECTREF" +/* Not safe. Idempotent. RFC3253, Section 6.3. */ +#define MHD_HTTP_METHOD_MKWORKSPACE "MKWORKSPACE" +/* Not safe. Idempotent. RFC4918, Section 9.9. */ +#define MHD_HTTP_METHOD_MOVE "MOVE" +/* Not safe. Idempotent. RFC3648, Section 7. */ +#define MHD_HTTP_METHOD_ORDERPATCH "ORDERPATCH" +/* Not safe. Not idempotent. RFC5789, Section 2. */ +#define MHD_HTTP_METHOD_PATCH "PATCH" +/* Safe. Idempotent. RFC9113, Section 3.4. */ +#define MHD_HTTP_METHOD_PRI "PRI" +/* Safe. Idempotent. RFC4918, Section 9.1; RFC8144, Section 2.1. */ +#define MHD_HTTP_METHOD_PROPFIND "PROPFIND" +/* Not safe. Idempotent. RFC4918, Section 9.2; RFC8144, Section 2.2. */ +#define MHD_HTTP_METHOD_PROPPATCH "PROPPATCH" +/* Not safe. Idempotent. RFC5842, Section 6. */ +#define MHD_HTTP_METHOD_REBIND "REBIND" +/* Safe. Idempotent. RFC3253, Section 3.6; RFC8144, Section 2.1. */ +#define MHD_HTTP_METHOD_REPORT "REPORT" +/* Safe. Idempotent. RFC5323, Section 2. */ +#define MHD_HTTP_METHOD_SEARCH "SEARCH" +/* Not safe. Idempotent. RFC5842, Section 5. */ +#define MHD_HTTP_METHOD_UNBIND "UNBIND" +/* Not safe. Idempotent. RFC3253, Section 4.5. */ +#define MHD_HTTP_METHOD_UNCHECKOUT "UNCHECKOUT" +/* Not safe. Idempotent. RFC2068, Section 19.6.1.3. */ +#define MHD_HTTP_METHOD_UNLINK "UNLINK" +/* Not safe. Idempotent. RFC4918, Section 9.11. */ +#define MHD_HTTP_METHOD_UNLOCK "UNLOCK" +/* Not safe. Idempotent. RFC3253, Section 7.1. */ +#define MHD_HTTP_METHOD_UPDATE "UPDATE" +/* Not safe. Idempotent. RFC4437, Section 7. */ +#define MHD_HTTP_METHOD_UPDATEREDIRECTREF "UPDATEREDIRECTREF" +/* Not safe. Idempotent. RFC3253, Section 3.5. */ +#define MHD_HTTP_METHOD_VERSION_CONTROL "VERSION-CONTROL" +/* Not safe. Not idempotent. RFC9110, Section 18.2. */ +#define MHD_HTTP_METHOD_ASTERISK "*" + +/** @} */ /* end of group methods */ + +/** + * @defgroup postenc HTTP POST encodings + * See also: http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 + * @{ + */ +#define MHD_HTTP_POST_ENCODING_FORM_URLENCODED \ + "application/x-www-form-urlencoded" +#define MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA "multipart/form-data" + +/** @} */ /* end of group postenc */ + + +/** + * @brief Handle for the daemon (listening on a socket for HTTP traffic). + * @ingroup event + */ +struct MHD_Daemon; + +/** + * @brief Handle for a connection / HTTP request. + * + * With HTTP/1.1, multiple requests can be run over the same + * connection. However, MHD will only show one request per TCP + * connection to the client at any given time. + * @ingroup request + */ +struct MHD_Connection; + +/** + * @brief Handle for a response. + * @ingroup response + */ +struct MHD_Response; + +/** + * @brief Handle for POST processing. + * @ingroup response + */ +struct MHD_PostProcessor; + + +/** + * @brief Flags for the `struct MHD_Daemon`. + * + * Note that MHD will run automatically in background thread(s) only + * if #MHD_USE_INTERNAL_POLLING_THREAD is used. Otherwise caller (application) + * must use #MHD_run() or #MHD_run_from_select() to have MHD processed + * network connections and data. + * + * Starting the daemon may also fail if a particular option is not + * implemented or not supported on the target platform (i.e. no + * support for TLS, epoll or IPv6). + */ +enum MHD_FLAG +{ + /** + * No options selected. + */ + MHD_NO_FLAG = 0, + + /** + * Print errors messages to custom error logger or to `stderr` if + * custom error logger is not set. + * @sa ::MHD_OPTION_EXTERNAL_LOGGER + */ + MHD_USE_ERROR_LOG = 1, + + /** + * Run in debug mode. If this flag is used, the library should + * print error messages and warnings to `stderr`. + */ + MHD_USE_DEBUG = 1, + + /** + * Run in HTTPS mode. The modern protocol is called TLS. + */ + MHD_USE_TLS = 2, + + /** @deprecated */ + MHD_USE_SSL = 2, +#if 0 + /* let's do this later once versions that define MHD_USE_TLS a more widely deployed. */ +#define MHD_USE_SSL \ + _MHD_DEPR_IN_MACRO ("Value MHD_USE_SSL is deprecated, use MHD_USE_TLS") \ + MHD_USE_TLS +#endif + + /** + * Run using one thread per connection. + * Must be used only with #MHD_USE_INTERNAL_POLLING_THREAD. + * + * If #MHD_USE_ITC is also not used, closed and expired connections may only + * be cleaned up internally when a new connection is received. + * Consider adding of #MHD_USE_ITC flag to have faster internal cleanups + * at very minor increase in system resources usage. + */ + MHD_USE_THREAD_PER_CONNECTION = 4, + + /** + * Run using an internal thread (or thread pool) for sockets sending + * and receiving and data processing. Without this flag MHD will not + * run automatically in background thread(s). + * If this flag is set, #MHD_run() and #MHD_run_from_select() couldn't + * be used. + * This flag is set explicitly by #MHD_USE_POLL_INTERNAL_THREAD and + * by #MHD_USE_EPOLL_INTERNAL_THREAD. + * When this flag is not set, MHD run in "external" polling mode. + */ + MHD_USE_INTERNAL_POLLING_THREAD = 8, + + /** @deprecated */ + MHD_USE_SELECT_INTERNALLY = 8, +#if 0 /* Will be marked for real deprecation later. */ +#define MHD_USE_SELECT_INTERNALLY \ + _MHD_DEPR_IN_MACRO ( \ + "Value MHD_USE_SELECT_INTERNALLY is deprecated, use MHD_USE_INTERNAL_POLLING_THREAD instead") \ + MHD_USE_INTERNAL_POLLING_THREAD +#endif /* 0 */ + + /** + * Run using the IPv6 protocol (otherwise, MHD will just support + * IPv4). If you want MHD to support IPv4 and IPv6 using a single + * socket, pass #MHD_USE_DUAL_STACK, otherwise, if you only pass + * this option, MHD will try to bind to IPv6-only (resulting in + * no IPv4 support). + */ + MHD_USE_IPv6 = 16, + + /** + * Be pedantic about the protocol (as opposed to as tolerant as + * possible). + * This flag is equivalent to setting 1 as #MHD_OPTION_CLIENT_DISCIPLINE_LVL + * value. + * @sa #MHD_OPTION_CLIENT_DISCIPLINE_LVL + */ + MHD_USE_PEDANTIC_CHECKS = 32, +#if 0 /* Will be marked for real deprecation later. */ +#define MHD_USE_PEDANTIC_CHECKS \ + _MHD_DEPR_IN_MACRO ( \ + "Flag MHD_USE_PEDANTIC_CHECKS is deprecated, " \ + "use option MHD_OPTION_CLIENT_DISCIPLINE_LVL instead") \ + 32 +#endif /* 0 */ + + /** + * Use `poll()` instead of `select()` for polling sockets. + * This allows sockets with `fd >= FD_SETSIZE`. + * This option is not compatible with an "external" polling mode + * (as there is no API to get the file descriptors for the external + * poll() from MHD) and must also not be used in combination + * with #MHD_USE_EPOLL. + * @sa ::MHD_FEATURE_POLL, #MHD_USE_POLL_INTERNAL_THREAD + */ + MHD_USE_POLL = 64, + + /** + * Run using an internal thread (or thread pool) doing `poll()`. + * @sa ::MHD_FEATURE_POLL, #MHD_USE_POLL, #MHD_USE_INTERNAL_POLLING_THREAD + */ + MHD_USE_POLL_INTERNAL_THREAD = MHD_USE_POLL | MHD_USE_INTERNAL_POLLING_THREAD, + + /** @deprecated */ + MHD_USE_POLL_INTERNALLY = MHD_USE_POLL | MHD_USE_INTERNAL_POLLING_THREAD, +#if 0 /* Will be marked for real deprecation later. */ +#define MHD_USE_POLL_INTERNALLY \ + _MHD_DEPR_IN_MACRO ( \ + "Value MHD_USE_POLL_INTERNALLY is deprecated, use MHD_USE_POLL_INTERNAL_THREAD instead") \ + MHD_USE_POLL_INTERNAL_THREAD +#endif /* 0 */ + + /** + * Suppress (automatically) adding the 'Date:' header to HTTP responses. + * This option should ONLY be used on systems that do not have a clock + * and that DO provide other mechanisms for cache control. See also + * RFC 2616, section 14.18 (exception 3). + */ + MHD_USE_SUPPRESS_DATE_NO_CLOCK = 128, + + /** @deprecated */ + MHD_SUPPRESS_DATE_NO_CLOCK = 128, +#if 0 /* Will be marked for real deprecation later. */ +#define MHD_SUPPRESS_DATE_NO_CLOCK \ + _MHD_DEPR_IN_MACRO ( \ + "Value MHD_SUPPRESS_DATE_NO_CLOCK is deprecated, use MHD_USE_SUPPRESS_DATE_NO_CLOCK instead") \ + MHD_USE_SUPPRESS_DATE_NO_CLOCK +#endif /* 0 */ + + /** + * Run without a listen socket. This option only makes sense if + * #MHD_add_connection is to be used exclusively to connect HTTP + * clients to the HTTP server. This option is incompatible with + * using a thread pool; if it is used, #MHD_OPTION_THREAD_POOL_SIZE + * is ignored. + */ + MHD_USE_NO_LISTEN_SOCKET = 256, + + /** + * Use `epoll()` instead of `select()` or `poll()` for the event loop. + * This option is only available on some systems; using the option on + * systems without epoll will cause #MHD_start_daemon to fail. Using + * this option is not supported with #MHD_USE_THREAD_PER_CONNECTION. + * @sa ::MHD_FEATURE_EPOLL + */ + MHD_USE_EPOLL = 512, + + /** @deprecated */ + MHD_USE_EPOLL_LINUX_ONLY = 512, +#if 0 /* Will be marked for real deprecation later. */ +#define MHD_USE_EPOLL_LINUX_ONLY \ + _MHD_DEPR_IN_MACRO ( \ + "Value MHD_USE_EPOLL_LINUX_ONLY is deprecated, use MHD_USE_EPOLL") \ + MHD_USE_EPOLL +#endif /* 0 */ + + /** + * Run using an internal thread (or thread pool) doing `epoll` polling. + * This option is only available on certain platforms; using the option on + * platform without `epoll` support will cause #MHD_start_daemon to fail. + * @sa ::MHD_FEATURE_EPOLL, #MHD_USE_EPOLL, #MHD_USE_INTERNAL_POLLING_THREAD + */ + MHD_USE_EPOLL_INTERNAL_THREAD = MHD_USE_EPOLL + | MHD_USE_INTERNAL_POLLING_THREAD, + + /** @deprecated */ + MHD_USE_EPOLL_INTERNALLY = MHD_USE_EPOLL | MHD_USE_INTERNAL_POLLING_THREAD, + /** @deprecated */ + MHD_USE_EPOLL_INTERNALLY_LINUX_ONLY = MHD_USE_EPOLL + | MHD_USE_INTERNAL_POLLING_THREAD, +#if 0 /* Will be marked for real deprecation later. */ +#define MHD_USE_EPOLL_INTERNALLY \ + _MHD_DEPR_IN_MACRO ( \ + "Value MHD_USE_EPOLL_INTERNALLY is deprecated, use MHD_USE_EPOLL_INTERNAL_THREAD") \ + MHD_USE_EPOLL_INTERNAL_THREAD + /** @deprecated */ +#define MHD_USE_EPOLL_INTERNALLY_LINUX_ONLY \ + _MHD_DEPR_IN_MACRO ( \ + "Value MHD_USE_EPOLL_INTERNALLY_LINUX_ONLY is deprecated, use MHD_USE_EPOLL_INTERNAL_THREAD") \ + MHD_USE_EPOLL_INTERNAL_THREAD +#endif /* 0 */ + + /** + * Use inter-thread communication channel. + * #MHD_USE_ITC can be used with #MHD_USE_INTERNAL_POLLING_THREAD + * and is ignored with any "external" sockets polling. + * It's required for use of #MHD_quiesce_daemon + * or #MHD_add_connection. + * This option is enforced by #MHD_ALLOW_SUSPEND_RESUME or + * #MHD_USE_NO_LISTEN_SOCKET. + * #MHD_USE_ITC is always used automatically on platforms + * where select()/poll()/other ignore shutdown of listen + * socket. + */ + MHD_USE_ITC = 1024, + + /** @deprecated */ + MHD_USE_PIPE_FOR_SHUTDOWN = 1024, +#if 0 /* Will be marked for real deprecation later. */ +#define MHD_USE_PIPE_FOR_SHUTDOWN \ + _MHD_DEPR_IN_MACRO ( \ + "Value MHD_USE_PIPE_FOR_SHUTDOWN is deprecated, use MHD_USE_ITC") \ + MHD_USE_ITC +#endif /* 0 */ + + /** + * Use a single socket for IPv4 and IPv6. + */ + MHD_USE_DUAL_STACK = MHD_USE_IPv6 | 2048, + + /** + * Enable `turbo`. Disables certain calls to `shutdown()`, + * enables aggressive non-blocking optimistic reads and + * other potentially unsafe optimizations. + * Most effects only happen with #MHD_USE_EPOLL. + */ + MHD_USE_TURBO = 4096, + + /** @deprecated */ + MHD_USE_EPOLL_TURBO = 4096, +#if 0 /* Will be marked for real deprecation later. */ +#define MHD_USE_EPOLL_TURBO \ + _MHD_DEPR_IN_MACRO ( \ + "Value MHD_USE_EPOLL_TURBO is deprecated, use MHD_USE_TURBO") \ + MHD_USE_TURBO +#endif /* 0 */ + + /** + * Enable suspend/resume functions, which also implies setting up + * ITC to signal resume. + */ + MHD_ALLOW_SUSPEND_RESUME = 8192 | MHD_USE_ITC, + + /** @deprecated */ + MHD_USE_SUSPEND_RESUME = 8192 | MHD_USE_ITC, +#if 0 /* Will be marked for real deprecation later. */ +#define MHD_USE_SUSPEND_RESUME \ + _MHD_DEPR_IN_MACRO ( \ + "Value MHD_USE_SUSPEND_RESUME is deprecated, use MHD_ALLOW_SUSPEND_RESUME instead") \ + MHD_ALLOW_SUSPEND_RESUME +#endif /* 0 */ + + /** + * Enable TCP_FASTOPEN option. This option is only available on Linux with a + * kernel >= 3.6. On other systems, using this option cases #MHD_start_daemon + * to fail. + */ + MHD_USE_TCP_FASTOPEN = 16384, + + /** + * You need to set this option if you want to use HTTP "Upgrade". + * "Upgrade" may require usage of additional internal resources, + * which we do not want to use unless necessary. + */ + MHD_ALLOW_UPGRADE = 32768, + + /** + * Automatically use best available polling function. + * Choice of polling function is also depend on other daemon options. + * If #MHD_USE_INTERNAL_POLLING_THREAD is specified then epoll, poll() or + * select() will be used (listed in decreasing preference order, first + * function available on system will be used). + * If #MHD_USE_THREAD_PER_CONNECTION is specified then poll() or select() + * will be used. + * If those flags are not specified then epoll or select() will be + * used (as the only suitable for MHD_get_fdset()) + */ + MHD_USE_AUTO = 65536, + + /** + * Run using an internal thread (or thread pool) with best available on + * system polling function. + * This is combination of #MHD_USE_AUTO and #MHD_USE_INTERNAL_POLLING_THREAD + * flags. + */ + MHD_USE_AUTO_INTERNAL_THREAD = MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD, + + /** + * Flag set to enable post-handshake client authentication + * (only useful in combination with #MHD_USE_TLS). + */ + MHD_USE_POST_HANDSHAKE_AUTH_SUPPORT = 1U << 17, + + /** + * Flag set to enable TLS 1.3 early data. This has + * security implications, be VERY careful when using this. + */ + MHD_USE_INSECURE_TLS_EARLY_DATA = 1U << 18, + + /** + * Indicates that MHD daemon will be used by application in single-threaded + * mode only. When this flag is set then application must call any MHD + * function only within a single thread. + * This flag turns off some internal thread-safety and allows MHD making + * some of the internal optimisations suitable only for single-threaded + * environment. + * Not compatible with #MHD_USE_INTERNAL_POLLING_THREAD. + * @note Available since #MHD_VERSION 0x00097707 + */ + MHD_USE_NO_THREAD_SAFETY = 1U << 19 + +}; + + +/** + * Type of a callback function used for logging by MHD. + * + * @param cls closure + * @param fm format string (`printf()`-style) + * @param ap arguments to @a fm + * @ingroup logging + */ +typedef void +(*MHD_LogCallback)(void *cls, + const char *fm, + va_list ap); + + +/** + * Function called to lookup the pre shared key (@a psk) for a given + * HTTP connection based on the @a username. + * + * @param cls closure + * @param connection the HTTPS connection + * @param username the user name claimed by the other side + * @param[out] psk to be set to the pre-shared-key; should be allocated with malloc(), + * will be freed by MHD + * @param[out] psk_size to be set to the number of bytes in @a psk + * @return 0 on success, -1 on errors + */ +typedef int +(*MHD_PskServerCredentialsCallback)(void *cls, + const struct MHD_Connection *connection, + const char *username, + void **psk, + size_t *psk_size); + +/** + * Values for #MHD_OPTION_DIGEST_AUTH_NONCE_BIND_TYPE. + * + * These values can limit the scope of validity of MHD-generated nonces. + * Values can be combined with bitwise OR. + * Any value, except #MHD_DAUTH_BIND_NONCE_NONE, enforce function + * #MHD_digest_auth_check3() (and similar functions) to check nonce by + * re-generating it again with the same parameters, which is CPU-intensive + * operation. + * @note Available since #MHD_VERSION 0x00097701 + */ +enum MHD_DAuthBindNonce +{ + /** + * Generated nonces are valid for any request from any client until expired. + * This is default and recommended value. + * #MHD_digest_auth_check3() (and similar functions) would check only whether + * the nonce value that is used by client has been generated by MHD and not + * expired yet. + * It is recommended because RFC 7616 allows clients to use the same nonce + * for any request in the same "protection space". + * When checking client's authorisation requests CPU is loaded less if this + * value is used. + * This mode gives MHD maximum flexibility for nonces generation and can + * prevent possible nonce collisions (and corresponding log warning messages) + * when clients' requests are intensive. + * This value cannot be biwise-OR combined with other values. + */ + MHD_DAUTH_BIND_NONCE_NONE = 0, + + /** + * Generated nonces are valid only for the same realm. + */ + MHD_DAUTH_BIND_NONCE_REALM = 1 << 0, + + /** + * Generated nonces are valid only for the same URI (excluding parameters + * after '?' in URI) and request method (GET, POST etc). + * Not recommended unless "protection space" is limited to a single URI as + * RFC 7616 allows clients to re-use server-generated nonces for any URI + * in the same "protection space" which by default consists of all server + * URIs. + * Before #MHD_VERSION 0x00097701 this was default (and only supported) + * nonce bind type. + */ + MHD_DAUTH_BIND_NONCE_URI = 1 << 1, + + /** + * Generated nonces are valid only for the same URI including URI parameters + * and request method (GET, POST etc). + * This value implies #MHD_DAUTH_BIND_NONCE_URI. + * Not recommended for that same reasons as #MHD_DAUTH_BIND_NONCE_URI. + */ + MHD_DAUTH_BIND_NONCE_URI_PARAMS = 1 << 2, + + /** + * Generated nonces are valid only for the single client's IP. + * While it looks like security improvement, in practice the same client may + * jump from one IP to another (mobile or Wi-Fi handover, DHCP re-assignment, + * Multi-NAT, different proxy chain and other reasons), while IP address + * spoofing could be used relatively easily. + */ + MHD_DAUTH_BIND_NONCE_CLIENT_IP = 1 << 3 +} _MHD_FLAGS_ENUM; + +/** + * @brief MHD options. + * + * Passed in the varargs portion of #MHD_start_daemon. + */ +enum MHD_OPTION +{ + + /** + * No more options / last option. This is used + * to terminate the VARARGs list. + */ + MHD_OPTION_END = 0, + + /** + * Maximum memory size per connection (followed by a `size_t`). + * Default is 32 kb (#MHD_POOL_SIZE_DEFAULT). + * Values above 128k are unlikely to result in much benefit, as half + * of the memory will be typically used for IO, and TCP buffers are + * unlikely to support window sizes above 64k on most systems. + * Values below 64 bytes are completely unusable. + * Since #MHD_VERSION 0x00097710 silently ignored if followed by zero value. + */ + MHD_OPTION_CONNECTION_MEMORY_LIMIT = 1, + + /** + * Maximum number of concurrent connections to + * accept (followed by an `unsigned int`). + */ + MHD_OPTION_CONNECTION_LIMIT = 2, + + /** + * After how many seconds of inactivity should a + * connection automatically be timed out? (followed + * by an `unsigned int`; use zero for no timeout). + * Values larger than (UINT64_MAX / 2000 - 1) will + * be clipped to this number. + */ + MHD_OPTION_CONNECTION_TIMEOUT = 3, + + /** + * Register a function that should be called whenever a request has + * been completed (this can be used for application-specific clean + * up). Requests that have never been presented to the application + * (via #MHD_AccessHandlerCallback) will not result in + * notifications. + * + * This option should be followed by TWO pointers. First a pointer + * to a function of type #MHD_RequestCompletedCallback and second a + * pointer to a closure to pass to the request completed callback. + * The second pointer may be NULL. + */ + MHD_OPTION_NOTIFY_COMPLETED = 4, + + /** + * Limit on the number of (concurrent) connections made to the + * server from the same IP address. Can be used to prevent one + * IP from taking over all of the allowed connections. If the + * same IP tries to establish more than the specified number of + * connections, they will be immediately rejected. The option + * should be followed by an `unsigned int`. The default is + * zero, which means no limit on the number of connections + * from the same IP address. + */ + MHD_OPTION_PER_IP_CONNECTION_LIMIT = 5, + + /** + * Bind daemon to the supplied `struct sockaddr`. This option should + * be followed by a `struct sockaddr *`. If #MHD_USE_IPv6 is + * specified, the `struct sockaddr*` should point to a `struct + * sockaddr_in6`, otherwise to a `struct sockaddr_in`. + * Silently ignored if followed by NULL pointer. + * @deprecated Use #MHD_OPTION_SOCK_ADDR_LEN + */ + MHD_OPTION_SOCK_ADDR = 6, + + /** + * Specify a function that should be called before parsing the URI from + * the client. The specified callback function can be used for processing + * the URI (including the options) before it is parsed. The URI after + * parsing will no longer contain the options, which maybe inconvenient for + * logging. This option should be followed by two arguments, the first + * one must be of the form + * + * void * my_logger(void *cls, const char *uri, struct MHD_Connection *con) + * + * where the return value will be passed as + * (`* req_cls`) in calls to the #MHD_AccessHandlerCallback + * when this request is processed later; returning a + * value of NULL has no special significance (however, + * note that if you return non-NULL, you can no longer + * rely on the first call to the access handler having + * `NULL == *req_cls` on entry;) + * "cls" will be set to the second argument following + * #MHD_OPTION_URI_LOG_CALLBACK. Finally, uri will + * be the 0-terminated URI of the request. + * + * Note that during the time of this call, most of the connection's + * state is not initialized (as we have not yet parsed the headers). + * However, information about the connecting client (IP, socket) + * is available. + * + * The specified function is called only once per request, therefore some + * programmers may use it to instantiate their own request objects, freeing + * them in the notifier #MHD_OPTION_NOTIFY_COMPLETED. + */ + MHD_OPTION_URI_LOG_CALLBACK = 7, + + /** + * Memory pointer for the private key (key.pem) to be used by the + * HTTPS daemon. This option should be followed by a + * `const char *` argument. + * This should be used in conjunction with #MHD_OPTION_HTTPS_MEM_CERT. + */ + MHD_OPTION_HTTPS_MEM_KEY = 8, + + /** + * Memory pointer for the certificate (cert.pem) to be used by the + * HTTPS daemon. This option should be followed by a + * `const char *` argument. + * This should be used in conjunction with #MHD_OPTION_HTTPS_MEM_KEY. + */ + MHD_OPTION_HTTPS_MEM_CERT = 9, + + /** + * Daemon credentials type. + * Followed by an argument of type + * `gnutls_credentials_type_t`. + */ + MHD_OPTION_HTTPS_CRED_TYPE = 10, + + /** + * Memory pointer to a `const char *` specifying the GnuTLS priorities string. + * If this options is not specified, then MHD will try the following strings: + * * "@LIBMICROHTTPD" (application-specific system-wide configuration) + * * "@SYSTEM" (system-wide configuration) + * * default GnuTLS priorities string + * * "NORMAL" + * The first configuration accepted by GnuTLS will be used. + * For more details see GnuTLS documentation for "Application-specific + * priority strings". + */ + MHD_OPTION_HTTPS_PRIORITIES = 11, + + /** + * Pass a listen socket for MHD to use (systemd-style). If this + * option is used, MHD will not open its own listen socket(s). The + * argument passed must be of type `MHD_socket` and refer to an + * existing socket that has been bound to a port and is listening. + * If followed by MHD_INVALID_SOCKET value, MHD ignores this option + * and creates socket by itself. + */ + MHD_OPTION_LISTEN_SOCKET = 12, + + /** + * Use the given function for logging error messages. This option + * must be followed by two arguments; the first must be a pointer to + * a function of type #MHD_LogCallback and the second a pointer + * `void *` which will be passed as the first argument to the log + * callback. + * Should be specified as the first option, otherwise some messages + * may be printed by standard MHD logger during daemon startup. + * + * Note that MHD will not generate any log messages + * if it was compiled without the "--enable-messages" + * flag being set. + */ + MHD_OPTION_EXTERNAL_LOGGER = 13, + + /** + * Number (`unsigned int`) of threads in thread pool. Enable + * thread pooling by setting this value to to something + * greater than 1. + * Can be used only for daemons started with #MHD_USE_INTERNAL_POLLING_THREAD. + * Ignored if followed by zero value. + */ + MHD_OPTION_THREAD_POOL_SIZE = 14, + + /** + * Additional options given in an array of `struct MHD_OptionItem`. + * The array must be terminated with an entry `{MHD_OPTION_END, 0, NULL}`. + * An example for code using #MHD_OPTION_ARRAY is: + * + * struct MHD_OptionItem ops[] = { + * { MHD_OPTION_CONNECTION_LIMIT, 100, NULL }, + * { MHD_OPTION_CONNECTION_TIMEOUT, 10, NULL }, + * { MHD_OPTION_END, 0, NULL } + * }; + * d = MHD_start_daemon (0, 8080, NULL, NULL, dh, NULL, + * MHD_OPTION_ARRAY, ops, + * MHD_OPTION_END); + * + * For options that expect a single pointer argument, the + * 'value' member of the `struct MHD_OptionItem` is ignored. + * For options that expect two pointer arguments, the first + * argument must be cast to `intptr_t`. + */ + MHD_OPTION_ARRAY = 15, + + /** + * Specify a function that should be called for unescaping escape + * sequences in URIs and URI arguments. Note that this function + * will NOT be used by the `struct MHD_PostProcessor`. If this + * option is not specified, the default method will be used which + * decodes escape sequences of the form "%HH". This option should + * be followed by two arguments, the first one must be of the form + * + * size_t my_unescaper(void *cls, + * struct MHD_Connection *c, + * char *s) + * + * where the return value must be the length of the value left in + * "s" (without the 0-terminator) and "s" should be updated. Note + * that the unescape function must not lengthen "s" (the result must + * be shorter than the input and must still be 0-terminated). + * However, it may also include binary zeros before the + * 0-termination. "cls" will be set to the second argument + * following #MHD_OPTION_UNESCAPE_CALLBACK. + */ + MHD_OPTION_UNESCAPE_CALLBACK = 16, + + /** + * Memory pointer for the random values to be used by the Digest + * Auth module. This option should be followed by two arguments. + * First an integer of type `size_t` which specifies the size + * of the buffer pointed to by the second argument in bytes. + * The recommended size is between 8 and 32. If size is four or less + * then security could be lowered. Sizes more then 32 (or, probably + * more than 16 - debatable) will not increase security. + * Note that the application must ensure that the buffer of the + * second argument remains allocated and unmodified while the + * daemon is running. + * @sa #MHD_OPTION_DIGEST_AUTH_RANDOM_COPY + */ + MHD_OPTION_DIGEST_AUTH_RANDOM = 17, + + /** + * Size of the internal array holding the map of the nonce and + * the nonce counter. This option should be followed by an `unsigend int` + * argument. + * The map size is 4 by default, which is enough to communicate with + * a single client at any given moment of time, but not enough to + * handle several clients simultaneously. + * If Digest Auth is not used, this option can be set to zero to minimise + * memory allocation. + */ + MHD_OPTION_NONCE_NC_SIZE = 18, + + /** + * Desired size of the stack for threads created by MHD. Followed + * by an argument of type `size_t`. Use 0 for system default. + */ + MHD_OPTION_THREAD_STACK_SIZE = 19, + + /** + * Memory pointer for the certificate (ca.pem) to be used by the + * HTTPS daemon for client authentication. + * This option should be followed by a `const char *` argument. + */ + MHD_OPTION_HTTPS_MEM_TRUST = 20, + + /** + * Increment to use for growing the read buffer (followed by a + * `size_t`). + * Must not be higher than 1/4 of #MHD_OPTION_CONNECTION_MEMORY_LIMIT. + * Since #MHD_VERSION 0x00097710 silently ignored if followed by zero value. + */ + MHD_OPTION_CONNECTION_MEMORY_INCREMENT = 21, + + /** + * Use a callback to determine which X.509 certificate should be + * used for a given HTTPS connection. This option should be + * followed by a argument of type `gnutls_certificate_retrieve_function2 *`. + * This option provides an + * alternative to #MHD_OPTION_HTTPS_MEM_KEY, + * #MHD_OPTION_HTTPS_MEM_CERT. You must use this version if + * multiple domains are to be hosted at the same IP address using + * TLS's Server Name Indication (SNI) extension. In this case, + * the callback is expected to select the correct certificate + * based on the SNI information provided. The callback is expected + * to access the SNI data using `gnutls_server_name_get()`. + * Using this option requires GnuTLS 3.0 or higher. + */ + MHD_OPTION_HTTPS_CERT_CALLBACK = 22, + + /** + * When using #MHD_USE_TCP_FASTOPEN, this option changes the default TCP + * fastopen queue length of 50. Note that having a larger queue size can + * cause resource exhaustion attack as the TCP stack has to now allocate + * resources for the SYN packet along with its DATA. This option should be + * followed by an `unsigned int` argument. + */ + MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE = 23, + + /** + * Memory pointer for the Diffie-Hellman parameters (dh.pem) to be used by the + * HTTPS daemon for key exchange. + * This option must be followed by a `const char *` argument. + */ + MHD_OPTION_HTTPS_MEM_DHPARAMS = 24, + + /** + * If present and set to true, allow reusing address:port socket + * (by using SO_REUSEPORT on most platform, or platform-specific ways). + * If present and set to false, disallow reusing address:port socket + * (does nothing on most platform, but uses SO_EXCLUSIVEADDRUSE on Windows). + * This option must be followed by a `unsigned int` argument. + */ + MHD_OPTION_LISTENING_ADDRESS_REUSE = 25, + + /** + * Memory pointer for a password that decrypts the private key (key.pem) + * to be used by the HTTPS daemon. This option should be followed by a + * `const char *` argument. + * This should be used in conjunction with #MHD_OPTION_HTTPS_MEM_KEY. + * @sa ::MHD_FEATURE_HTTPS_KEY_PASSWORD + */ + MHD_OPTION_HTTPS_KEY_PASSWORD = 26, + + /** + * Register a function that should be called whenever a connection is + * started or closed. + * + * This option should be followed by TWO pointers. First a pointer + * to a function of type #MHD_NotifyConnectionCallback and second a + * pointer to a closure to pass to the request completed callback. + * The second pointer may be NULL. + */ + MHD_OPTION_NOTIFY_CONNECTION = 27, + + /** + * Allow to change maximum length of the queue of pending connections on + * listen socket. If not present than default platform-specific SOMAXCONN + * value is used. This option should be followed by an `unsigned int` + * argument. + */ + MHD_OPTION_LISTEN_BACKLOG_SIZE = 28, + + /** + * If set to 1 - be strict about the protocol. Use -1 to be + * as tolerant as possible. + * + * The more flexible option #MHD_OPTION_CLIENT_DISCIPLINE_LVL is recommended + * instead of this option. + * + * The values mapping table: + * #MHD_OPTION_STRICT_FOR_CLIENT | #MHD_OPTION_CLIENT_DISCIPLINE_LVL + * -----------------------------:|:--------------------------------- + * 1 | 1 + * 0 | 0 + * -1 | -3 + * + * This option should be followed by an `int` argument. + * @sa #MHD_OPTION_CLIENT_DISCIPLINE_LVL + */ + MHD_OPTION_STRICT_FOR_CLIENT = 29, + + /** + * This should be a pointer to callback of type + * gnutls_psk_server_credentials_function that will be given to + * gnutls_psk_set_server_credentials_function. It is used to + * retrieve the shared key for a given username. + */ + MHD_OPTION_GNUTLS_PSK_CRED_HANDLER = 30, + + /** + * Use a callback to determine which X.509 certificate should be + * used for a given HTTPS connection. This option should be + * followed by a argument of type `gnutls_certificate_retrieve_function3 *`. + * This option provides an + * alternative/extension to #MHD_OPTION_HTTPS_CERT_CALLBACK. + * You must use this version if you want to use OCSP stapling. + * Using this option requires GnuTLS 3.6.3 or higher. + */ + MHD_OPTION_HTTPS_CERT_CALLBACK2 = 31, + + /** + * Allows the application to disable certain sanity precautions + * in MHD. With these, the client can break the HTTP protocol, + * so this should never be used in production. The options are, + * however, useful for testing HTTP clients against "broken" + * server implementations. + * This argument must be followed by an "unsigned int", corresponding + * to an `enum MHD_DisableSanityCheck`. + */ + MHD_OPTION_SERVER_INSANITY = 32, + + /** + * If followed by value '1' informs MHD that SIGPIPE is suppressed or + * handled by application. Allows MHD to use network functions that could + * generate SIGPIPE, like `sendfile()`. + * Valid only for daemons without #MHD_USE_INTERNAL_POLLING_THREAD as + * MHD automatically suppresses SIGPIPE for threads started by MHD. + * This option should be followed by an `int` argument. + * @note Available since #MHD_VERSION 0x00097205 + */ + MHD_OPTION_SIGPIPE_HANDLED_BY_APP = 33, + + /** + * If followed by 'int' with value '1' disables usage of ALPN for TLS + * connections even if supported by TLS library. + * Valid only for daemons with #MHD_USE_TLS. + * This option should be followed by an `int` argument. + * @note Available since #MHD_VERSION 0x00097207 + */ + MHD_OPTION_TLS_NO_ALPN = 34, + + /** + * Memory pointer for the random values to be used by the Digest + * Auth module. This option should be followed by two arguments. + * First an integer of type `size_t` which specifies the size + * of the buffer pointed to by the second argument in bytes. + * The recommended size is between 8 and 32. If size is four or less + * then security could be lowered. Sizes more then 32 (or, probably + * more than 16 - debatable) will not increase security. + * An internal copy of the buffer will be made, the data do not + * need to be static. + * @sa #MHD_OPTION_DIGEST_AUTH_RANDOM + * @note Available since #MHD_VERSION 0x00097701 + */ + MHD_OPTION_DIGEST_AUTH_RANDOM_COPY = 35, + + /** + * Allow to controls the scope of validity of MHD-generated nonces. + * This regulates how "nonces" are generated and how "nonces" are checked by + * #MHD_digest_auth_check3() and similar functions. + * This option should be followed by an 'unsigned int` argument with value + * formed as bitwise OR combination of #MHD_DAuthBindNonce values. + * When not specified, default value #MHD_DAUTH_BIND_NONCE_NONE is used. + * @note Available since #MHD_VERSION 0x00097701 + */ + MHD_OPTION_DIGEST_AUTH_NONCE_BIND_TYPE = 36, + + /** + * Memory pointer to a `const char *` specifying the GnuTLS priorities to be + * appended to default priorities. + * This allow some specific options to be enabled/disabled, while leaving + * the rest of the settings to their defaults. + * The string does not have to start with a colon ':' character. + * See #MHD_OPTION_HTTPS_PRIORITIES description for details of automatic + * default priorities. + * @note Available since #MHD_VERSION 0x00097701 + */ + MHD_OPTION_HTTPS_PRIORITIES_APPEND = 37, + + /** + * Sets specified client discipline level (i.e. HTTP protocol parsing + * strictness level). + * + * The following basic values are supported: + * 0 - default MHD level, a balance between extra security and broader + * compatibility, as allowed by RFCs for HTTP servers; + * 1 - more strict protocol interpretation, within the limits set by + * RFCs for HTTP servers; + * -1 - more lenient protocol interpretation, within the limits set by + * RFCs for HTTP servers. + * The following extended values could be used as well: + * 2 - stricter protocol interpretation, even stricter then allowed + * by RFCs for HTTP servers, however it should be absolutely compatible + * with clients following at least RFCs' "MUST" type of requirements + * for HTTP clients; + * 3 - strictest protocol interpretation, even stricter then allowed + * by RFCs for HTTP servers, however it should be absolutely compatible + * with clients following RFCs' "SHOULD" and "MUST" types of requirements + * for HTTP clients; + * -2 - more relaxed protocol interpretation, violating RFCs' "SHOULD" type + * of requirements for HTTP servers; + * -3 - the most flexible protocol interpretation, beyond RFCs' "MUST" type of + * requirements for HTTP server. + * Values higher than "3" or lower than "-3" are interpreted as "3" or "-3" + * respectively. + * + * Higher values are more secure, lower values are more compatible with + * various HTTP clients. + * + * The default value ("0") could be used in most cases. + * Value "1" is suitable for highly loaded public servers. + * Values "2" and "3" are generally recommended only for testing of HTTP + * clients against MHD. + * Value "2" may be used for security-centric application, however it is + * slight violation of RFCs' requirements. + * Negative values are not recommended for public servers. + * Values "-1" and "-2" could be used for servers in isolated environment. + * Value "-3" is not recommended unless it is absolutely necessary to + * communicate with some client(s) with badly broken HTTP implementation. + * + * This option should be followed by an `int` argument. + * @note Available since #MHD_VERSION 0x00097701 + */ + MHD_OPTION_CLIENT_DISCIPLINE_LVL = 38, + + /** + * Specifies value of FD_SETSIZE used by application. Only For external + * polling modes (without MHD internal threads). + * Some platforms (FreeBSD, Solaris, W32 etc.) allow overriding of FD_SETSIZE + * value. When polling by select() is used, MHD rejects sockets with numbers + * equal or higher than FD_SETSIZE. If this option is used, MHD treats this + * value as a limitation for socket number instead of FD_SETSIZE value which + * was used for building MHD. + * When external polling is used with #MHD_get_fdset2() (or #MHD_get_fdset() + * macro) and #MHD_run_from_select() interfaces, it is recommended to always + * use this option. + * It is safe to use this option on platforms with fixed FD_SETSIZE (like + * GNU/Linux) if system value of FD_SETSIZE is used as the argument. + * Can be used only for daemons without #MHD_USE_INTERNAL_POLLING_THREAD, i.e. + * only when external sockets polling is used. + * On W32 it is silently ignored, as W32 does not limit the socket number in + * fd_sets. + * This option should be followed by a positive 'int' argument. + * @note Available since #MHD_VERSION 0x00097705 + */ + MHD_OPTION_APP_FD_SETSIZE = 39, + + /** + * Bind daemon to the supplied 'struct sockaddr'. This option should + * be followed by two parameters: 'socklen_t' the size of memory at the next + * pointer and the pointer 'const struct sockaddr *'. + * Note: the order of the arguments is not the same as for system bind() and + * other network functions. + * If #MHD_USE_IPv6 is specified, the 'struct sockaddr*' should + * point to a 'struct sockaddr_in6'. + * The socket domain (protocol family) is detected from provided + * 'struct sockaddr'. IP, IPv6 and UNIX sockets are supported (if supported + * by the platform). Other types may work occasionally. + * Silently ignored if followed by zero size and NULL pointer. + * @note Available since #MHD_VERSION 0x00097706 + */ + MHD_OPTION_SOCK_ADDR_LEN = 40 + , + /** + * Default nonce timeout value used for Digest Auth. + * This option should be followed by an 'unsigned int' argument. + * Silently ignored if followed by zero value. + * @see #MHD_digest_auth_check3(), MHD_digest_auth_check_digest3() + * @note Available since #MHD_VERSION 0x00097709 + */ + MHD_OPTION_DIGEST_AUTH_DEFAULT_NONCE_TIMEOUT = 41 + , + /** + * Default maximum nc (nonce count) value used for Digest Auth. + * This option should be followed by an 'uint32_t' argument. + * Silently ignored if followed by zero value. + * @see #MHD_digest_auth_check3(), MHD_digest_auth_check_digest3() + * @note Available since #MHD_VERSION 0x00097709 + */ + MHD_OPTION_DIGEST_AUTH_DEFAULT_MAX_NC = 42 + , + /** + * Default maximum nc (nonce count) value used for Digest Auth. + * This option must be followed by an 'int' argument. + * If followed by '0' (default) then: + * + requests are rejected if request URI has binary zero (the result + * of %00 decoding) in the path part of the URI. + * If followed by '1' then: + * + binary zero is allowed in request URI path; + * + #MHD_AccessHandlerCallback called with NULL in @a url parameter when + * request URI path has binary zero, the full @a url is available only + * via #MHD_get_connection_URI_path_n() + * If followed by '2' (unsafe!) then: + * + binary zero is allowed in request URI path; + * + #MHD_AccessHandlerCallback called with truncated (unsafe!) @a url + * parameter when request URI path has binary zero. + * @see #MHD_get_connection_URI_path_n() + * @note Available since #MHD_VERSION 0x01000201 + */ + MHD_OPTION_ALLOW_BIN_ZERO_IN_URI_PATH = 43 + +} _MHD_FIXED_ENUM; + + +/** + * Bitfield for the #MHD_OPTION_SERVER_INSANITY specifying + * which santiy checks should be disabled. + */ +enum MHD_DisableSanityCheck +{ + /** + * All sanity checks are enabled. + */ + MHD_DSC_SANE = 0 + +} _MHD_FIXED_FLAGS_ENUM; + + +/** + * Entry in an #MHD_OPTION_ARRAY. + */ +struct MHD_OptionItem +{ + /** + * Which option is being given. Use #MHD_OPTION_END + * to terminate the array. + */ + enum MHD_OPTION option; + + /** + * Option value (for integer arguments, and for options requiring + * two pointer arguments); should be 0 for options that take no + * arguments or only a single pointer argument. + */ + intptr_t value; + + /** + * Pointer option value (use NULL for options taking no arguments + * or only an integer option). + */ + void *ptr_value; + +}; + + +/** + * The `enum MHD_ValueKind` specifies the source of + * the key-value pairs in the HTTP protocol. + */ +enum MHD_ValueKind +{ + + /** + * Response header + * @deprecated + */ + MHD_RESPONSE_HEADER_KIND = 0, +#define MHD_RESPONSE_HEADER_KIND \ + _MHD_DEPR_IN_MACRO ( \ + "Value MHD_RESPONSE_HEADER_KIND is deprecated and not used") \ + MHD_RESPONSE_HEADER_KIND + + /** + * HTTP header (request/response). + */ + MHD_HEADER_KIND = 1, + + /** + * Cookies. Note that the original HTTP header containing + * the cookie(s) will still be available and intact. + */ + MHD_COOKIE_KIND = 2, + + /** + * POST data. This is available only if a content encoding + * supported by MHD is used (currently only URL encoding), + * and only if the posted content fits within the available + * memory pool. Note that in that case, the upload data + * given to the #MHD_AccessHandlerCallback will be + * empty (since it has already been processed). + */ + MHD_POSTDATA_KIND = 4, + + /** + * GET (URI) arguments. + */ + MHD_GET_ARGUMENT_KIND = 8, + + /** + * HTTP footer (only for HTTP 1.1 chunked encodings). + */ + MHD_FOOTER_KIND = 16 +} _MHD_FIXED_ENUM; + + +/** + * The `enum MHD_RequestTerminationCode` specifies reasons + * why a request has been terminated (or completed). + * @ingroup request + */ +enum MHD_RequestTerminationCode +{ + + /** + * We finished sending the response. + * @ingroup request + */ + MHD_REQUEST_TERMINATED_COMPLETED_OK = 0, + + /** + * Error handling the connection (resources + * exhausted, application error accepting request, + * decrypt error (for HTTPS), connection died when + * sending the response etc.) + * @ingroup request + */ + MHD_REQUEST_TERMINATED_WITH_ERROR = 1, + + /** + * No activity on the connection for the number + * of seconds specified using + * #MHD_OPTION_CONNECTION_TIMEOUT. + * @ingroup request + */ + MHD_REQUEST_TERMINATED_TIMEOUT_REACHED = 2, + + /** + * We had to close the session since MHD was being + * shut down. + * @ingroup request + */ + MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN = 3, + + /** + * We tried to read additional data, but the connection became broken or + * the other side hard closed the connection. + * This error is similar to #MHD_REQUEST_TERMINATED_WITH_ERROR, but + * specific to the case where the connection died before request completely + * received. + * @ingroup request + */ + MHD_REQUEST_TERMINATED_READ_ERROR = 4, + + /** + * The client terminated the connection by closing the socket + * for writing (TCP half-closed) while still sending request. + * @ingroup request + */ + MHD_REQUEST_TERMINATED_CLIENT_ABORT = 5 + +} _MHD_FIXED_ENUM; + + +/** + * The `enum MHD_ConnectionNotificationCode` specifies types + * of connection notifications. + * @ingroup request + */ +enum MHD_ConnectionNotificationCode +{ + + /** + * A new connection has been started. + * @ingroup request + */ + MHD_CONNECTION_NOTIFY_STARTED = 0, + + /** + * A connection is closed. + * @ingroup request + */ + MHD_CONNECTION_NOTIFY_CLOSED = 1 + +} _MHD_FIXED_ENUM; + + +/** + * Information about a connection. + */ +union MHD_ConnectionInfo +{ + + /** + * Cipher algorithm used, of type "enum gnutls_cipher_algorithm". + */ + int /* enum gnutls_cipher_algorithm */ cipher_algorithm; + + /** + * Protocol used, of type "enum gnutls_protocol". + */ + int /* enum gnutls_protocol */ protocol; + + /** + * The suspended status of a connection. + */ + int /* MHD_YES or MHD_NO */ suspended; + + /** + * Amount of second that connection could spend in idle state + * before automatically disconnected. + * Zero for no timeout (unlimited idle time). + */ + unsigned int connection_timeout; + + /** + * HTTP status queued with the response, for #MHD_CONNECTION_INFO_HTTP_STATUS. + */ + unsigned int http_status; + + /** + * Connect socket + */ + MHD_socket connect_fd; + + /** + * Size of the client's HTTP header. + * It includes the request line, all request headers, the header section + * terminating empty line, with all CRLF (or LF) characters. + */ + size_t header_size; + + /** + * GNUtls session handle, of type "gnutls_session_t". + */ + void * /* gnutls_session_t */ tls_session; + + /** + * GNUtls client certificate handle, of type "gnutls_x509_crt_t". + */ + void * /* gnutls_x509_crt_t */ client_cert; + + /** + * Address information for the client. + */ + struct sockaddr *client_addr; + + /** + * Which daemon manages this connection (useful in case there are many + * daemons running). + */ + struct MHD_Daemon *daemon; + + /** + * Socket-specific client context. Points to the same address as + * the "socket_context" of the #MHD_NotifyConnectionCallback. + */ + void *socket_context; +}; + + +/** + * I/O vector type. Provided for use with #MHD_create_response_from_iovec(). + * @note Available since #MHD_VERSION 0x00097204 + */ +struct MHD_IoVec +{ + /** + * The pointer to the memory region for I/O. + */ + const void *iov_base; + + /** + * The size in bytes of the memory region for I/O. + */ + size_t iov_len; +}; + + +/** + * Values of this enum are used to specify what + * information about a connection is desired. + * @ingroup request + */ +enum MHD_ConnectionInfoType +{ + /** + * What cipher algorithm is being used. + * Takes no extra arguments. + * @ingroup request + */ + MHD_CONNECTION_INFO_CIPHER_ALGO, + + /** + * + * Takes no extra arguments. + * @ingroup request + */ + MHD_CONNECTION_INFO_PROTOCOL, + + /** + * Obtain IP address of the client. Takes no extra arguments. + * Returns essentially a `struct sockaddr **` (since the API returns + * a `union MHD_ConnectionInfo *` and that union contains a `struct + * sockaddr *`). + * @ingroup request + */ + MHD_CONNECTION_INFO_CLIENT_ADDRESS, + + /** + * Get the gnuTLS session handle. + * @ingroup request + */ + MHD_CONNECTION_INFO_GNUTLS_SESSION, + + /** + * Get the gnuTLS client certificate handle. Dysfunctional (never + * implemented, deprecated). Use #MHD_CONNECTION_INFO_GNUTLS_SESSION + * to get the `gnutls_session_t` and then call + * gnutls_certificate_get_peers(). + */ + MHD_CONNECTION_INFO_GNUTLS_CLIENT_CERT, + + /** + * Get the `struct MHD_Daemon *` responsible for managing this connection. + * @ingroup request + */ + MHD_CONNECTION_INFO_DAEMON, + + /** + * Request the file descriptor for the connection socket. + * MHD sockets are always in non-blocking mode. + * No extra arguments should be passed. + * @ingroup request + */ + MHD_CONNECTION_INFO_CONNECTION_FD, + + /** + * Returns the client-specific pointer to a `void *` that was (possibly) + * set during a #MHD_NotifyConnectionCallback when the socket was + * first accepted. + * Note that this is NOT the same as the "req_cls" argument of + * the #MHD_AccessHandlerCallback. The "req_cls" is fresh for each + * HTTP request, while the "socket_context" is fresh for each socket. + */ + MHD_CONNECTION_INFO_SOCKET_CONTEXT, + + /** + * Check whether the connection is suspended. + * @ingroup request + */ + MHD_CONNECTION_INFO_CONNECTION_SUSPENDED, + + /** + * Get connection timeout + * @ingroup request + */ + MHD_CONNECTION_INFO_CONNECTION_TIMEOUT, + + /** + * Return length of the client's HTTP request header. + * @ingroup request + */ + MHD_CONNECTION_INFO_REQUEST_HEADER_SIZE, + + /** + * Return HTTP status queued with the response. NULL + * if no HTTP response has been queued yet. + */ + MHD_CONNECTION_INFO_HTTP_STATUS + +} _MHD_FIXED_ENUM; + + +/** + * Values of this enum are used to specify what + * information about a daemon is desired. + */ +enum MHD_DaemonInfoType +{ + /** + * No longer supported (will return NULL). + */ + MHD_DAEMON_INFO_KEY_SIZE, + + /** + * No longer supported (will return NULL). + */ + MHD_DAEMON_INFO_MAC_KEY_SIZE, + + /** + * Request the file descriptor for the listening socket. + * No extra arguments should be passed. + */ + MHD_DAEMON_INFO_LISTEN_FD, + + /** + * Request the file descriptor for the "external" sockets polling + * when 'epoll' mode is used. + * No extra arguments should be passed. + * + * Waiting on epoll FD must not block longer than value + * returned by #MHD_get_timeout() otherwise connections + * will "hung" with unprocessed data in network buffers + * and timed-out connections will not be closed. + * + * @sa #MHD_get_timeout(), #MHD_run() + */ + MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY, + MHD_DAEMON_INFO_EPOLL_FD = MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY, + + /** + * Request the number of current connections handled by the daemon. + * No extra arguments should be passed. + * Note: when using MHD in "external" polling mode, this type of request + * could be used only when #MHD_run()/#MHD_run_from_select is not + * working in other thread at the same time. + */ + MHD_DAEMON_INFO_CURRENT_CONNECTIONS, + + /** + * Request the daemon flags. + * No extra arguments should be passed. + * Note: flags may differ from original 'flags' specified for + * daemon, especially if #MHD_USE_AUTO was set. + */ + MHD_DAEMON_INFO_FLAGS, + + /** + * Request the port number of daemon's listen socket. + * No extra arguments should be passed. + * Note: if port '0' was specified for #MHD_start_daemon(), returned + * value will be real port number. + */ + MHD_DAEMON_INFO_BIND_PORT +} _MHD_FIXED_ENUM; + + +/** + * Callback for serious error condition. The default action is to print + * an error message and `abort()`. + * + * @param cls user specified value + * @param file where the error occurred, may be NULL if MHD was built without + * messages support + * @param line where the error occurred + * @param reason error detail, may be NULL + * @ingroup logging + */ +typedef void +(*MHD_PanicCallback) (void *cls, + const char *file, + unsigned int line, + const char *reason); + +/** + * Allow or deny a client to connect. + * + * @param cls closure + * @param addr address information from the client + * @param addrlen length of @a addr + * @return #MHD_YES if connection is allowed, #MHD_NO if not + */ +typedef enum MHD_Result +(*MHD_AcceptPolicyCallback)(void *cls, + const struct sockaddr *addr, + socklen_t addrlen); + + +/** + * A client has requested the given @a url using the given @a method + * (#MHD_HTTP_METHOD_GET, #MHD_HTTP_METHOD_PUT, #MHD_HTTP_METHOD_DELETE, + * #MHD_HTTP_METHOD_POST, etc). + * + * The callback must call MHD function MHD_queue_response() to provide content + * to give back to the client and return an HTTP status code (i.e. + * #MHD_HTTP_OK, #MHD_HTTP_NOT_FOUND, etc.). The response can be created + * in this callback or prepared in advance. + * Alternatively, callback may call MHD_suspend_connection() to temporarily + * suspend data processing for this connection. + * + * As soon as response is provided this callback will not be called anymore + * for the current request. + * + * For each HTTP request this callback is called several times: + * * after request headers are fully received and decoded, + * * for each received part of request body (optional, if request has body), + * * when request is fully received. + * + * If response is provided before request is fully received, the rest + * of the request is discarded and connection is automatically closed + * after sending response. + * + * If the request is fully received, but response hasn't been provided and + * connection is not suspended, the callback can be called again immediately. + * + * The response cannot be queued when this callback is called to process + * the client upload data (when @a upload_data is not NULL). + * + * @param cls argument given together with the function + * pointer when the handler was registered with MHD + * @param connection the connection handle + * @param url the requested url, can be truncated or can be NULL, depending + * on #MHD_OPTION_ALLOW_BIN_ZERO_IN_URI_PATH option, + * see #MHD_get_connection_URI_path_n() + * @param method the HTTP method used (#MHD_HTTP_METHOD_GET, + * #MHD_HTTP_METHOD_PUT, etc.) + * @param version the HTTP version string (i.e. + * #MHD_HTTP_VERSION_1_1) + * @param upload_data the data being uploaded (excluding HEADERS, + * for a POST that fits into memory and that is encoded + * with a supported encoding, the POST data will NOT be + * given in upload_data and is instead available as + * part of #MHD_get_connection_values; very large POST + * data *will* be made available incrementally in + * @a upload_data) + * @param[in,out] upload_data_size set initially to the size of the + * @a upload_data provided; the method must update this + * value to the number of bytes NOT processed; + * @param[in,out] req_cls pointer that the callback can set to some + * address and that will be preserved by MHD for future + * calls for this request; since the access handler may + * be called many times (i.e., for a PUT/POST operation + * with plenty of upload data) this allows the application + * to easily associate some request-specific state. + * If necessary, this state can be cleaned up in the + * global #MHD_RequestCompletedCallback (which + * can be set with the #MHD_OPTION_NOTIFY_COMPLETED). + * Initially, `*req_cls` will be NULL. + * @return #MHD_YES if the connection was handled successfully, + * #MHD_NO if the socket must be closed due to a serious + * error while handling the request + * + * @sa #MHD_queue_response(), #MHD_get_connection_URI_path_n() + */ +typedef enum MHD_Result +(*MHD_AccessHandlerCallback)(void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, + size_t *upload_data_size, + void **req_cls); + + +/** + * Signature of the callback used by MHD to notify the + * application about completed requests. + * + * @param cls client-defined closure + * @param connection connection handle + * @param req_cls value as set by the last call to + * the #MHD_AccessHandlerCallback + * @param toe reason for request termination + * @see #MHD_OPTION_NOTIFY_COMPLETED + * @ingroup request + */ +typedef void +(*MHD_RequestCompletedCallback) (void *cls, + struct MHD_Connection *connection, + void **req_cls, + enum MHD_RequestTerminationCode toe); + + +/** + * Signature of the callback used by MHD to notify the + * application about started/stopped connections + * + * @param cls client-defined closure + * @param connection connection handle + * @param socket_context socket-specific pointer where the + * client can associate some state specific + * to the TCP connection; note that this is + * different from the "req_cls" which is per + * HTTP request. The client can initialize + * during #MHD_CONNECTION_NOTIFY_STARTED and + * cleanup during #MHD_CONNECTION_NOTIFY_CLOSED + * and access in the meantime using + * #MHD_CONNECTION_INFO_SOCKET_CONTEXT. + * @param toe reason for connection notification + * @see #MHD_OPTION_NOTIFY_CONNECTION + * @ingroup request + */ +typedef void +(*MHD_NotifyConnectionCallback) (void *cls, + struct MHD_Connection *connection, + void **socket_context, + enum MHD_ConnectionNotificationCode toe); + + +/** + * Iterator over key-value pairs. This iterator + * can be used to iterate over all of the cookies, + * headers, or POST-data fields of a request, and + * also to iterate over the headers that have been + * added to a response. + * + * @param cls closure + * @param kind kind of the header we are looking at + * @param key key for the value, can be an empty string + * @param value corresponding value, can be NULL + * @return #MHD_YES to continue iterating, + * #MHD_NO to abort the iteration + * @ingroup request + */ +typedef enum MHD_Result +(*MHD_KeyValueIterator)(void *cls, + enum MHD_ValueKind kind, + const char *key, + const char *value); + + +/** + * Iterator over key-value pairs with size parameters. + * This iterator can be used to iterate over all of + * the cookies, headers, or POST-data fields of a + * request, and also to iterate over the headers that + * have been added to a response. + * @note Available since #MHD_VERSION 0x00096303 + * + * @param cls closure + * @param kind kind of the header we are looking at + * @param key key for the value, can be an empty string + * @param value corresponding value, can be NULL + * @param value_size number of bytes in @a value; + * for C-strings, the length excludes the 0-terminator + * @return #MHD_YES to continue iterating, + * #MHD_NO to abort the iteration + * @ingroup request + */ +typedef enum MHD_Result +(*MHD_KeyValueIteratorN)(void *cls, + enum MHD_ValueKind kind, + const char *key, + size_t key_size, + const char *value, + size_t value_size); + + +/** + * Callback used by libmicrohttpd in order to obtain content. + * + * The callback is to copy at most @a max bytes of content into @a buf. + * The total number of bytes that has been placed into @a buf should be + * returned. + * + * Note that returning zero will cause libmicrohttpd to try again. + * Thus, returning zero should only be used in conjunction + * with MHD_suspend_connection() to avoid busy waiting. + * + * @param cls extra argument to the callback + * @param pos position in the datastream to access; + * note that if a `struct MHD_Response` object is re-used, + * it is possible for the same content reader to + * be queried multiple times for the same data; + * however, if a `struct MHD_Response` is not re-used, + * libmicrohttpd guarantees that "pos" will be + * the sum of all non-negative return values + * obtained from the content reader so far. + * @param buf where to copy the data + * @param max maximum number of bytes to copy to @a buf (size of @a buf) + * @return number of bytes written to @a buf; + * 0 is legal unless MHD is started in "internal" sockets polling mode + * (since this would cause busy-waiting); 0 in "external" sockets + * polling mode will cause this function to be called again once + * any MHD_run*() function is called; + * #MHD_CONTENT_READER_END_OF_STREAM (-1) for the regular + * end of transmission (with chunked encoding, MHD will then + * terminate the chunk and send any HTTP footers that might be + * present; without chunked encoding and given an unknown + * response size, MHD will simply close the connection; note + * that while returning #MHD_CONTENT_READER_END_OF_STREAM is not technically + * legal if a response size was specified, MHD accepts this + * and treats it just as #MHD_CONTENT_READER_END_WITH_ERROR; + * #MHD_CONTENT_READER_END_WITH_ERROR (-2) to indicate a server + * error generating the response; this will cause MHD to simply + * close the connection immediately. If a response size was + * given or if chunked encoding is in use, this will indicate + * an error to the client. Note, however, that if the client + * does not know a response size and chunked encoding is not in + * use, then clients will not be able to tell the difference between + * #MHD_CONTENT_READER_END_WITH_ERROR and #MHD_CONTENT_READER_END_OF_STREAM. + * This is not a limitation of MHD but rather of the HTTP protocol. + */ +typedef ssize_t +(*MHD_ContentReaderCallback) (void *cls, + uint64_t pos, + char *buf, + size_t max); + + +/** + * This method is called by libmicrohttpd if we + * are done with a content reader. It should + * be used to free resources associated with the + * content reader. + * + * @param cls closure + * @ingroup response + */ +typedef void +(*MHD_ContentReaderFreeCallback) (void *cls); + + +/** + * Iterator over key-value pairs where the value + * may be made available in increments and/or may + * not be zero-terminated. Used for processing + * POST data. + * + * @param cls user-specified closure + * @param kind type of the value, always #MHD_POSTDATA_KIND when called from MHD + * @param key 0-terminated key for the value, NULL if not known. This value + * is never NULL for url-encoded POST data. + * @param filename name of the uploaded file, NULL if not known + * @param content_type mime-type of the data, NULL if not known + * @param transfer_encoding encoding of the data, NULL if not known + * @param data pointer to @a size bytes of data at the + * specified offset + * @param off offset of data in the overall value + * @param size number of bytes in @a data available + * @return #MHD_YES to continue iterating, + * #MHD_NO to abort the iteration + */ +typedef enum MHD_Result +(*MHD_PostDataIterator)(void *cls, + enum MHD_ValueKind kind, + const char *key, + const char *filename, + const char *content_type, + const char *transfer_encoding, + const char *data, + uint64_t off, + size_t size); + +/* **************** Daemon handling functions ***************** */ + +/** + * Start a webserver on the given port. + * + * @param flags combination of `enum MHD_FLAG` values + * @param port port to bind to (in host byte order), + * use '0' to bind to random free port, + * ignored if MHD_OPTION_SOCK_ADDR or + * MHD_OPTION_LISTEN_SOCKET is provided + * or MHD_USE_NO_LISTEN_SOCKET is specified + * @param apc callback to call to check which clients + * will be allowed to connect; you can pass NULL + * in which case connections from any IP will be + * accepted + * @param apc_cls extra argument to apc + * @param dh handler called for all requests (repeatedly) + * @param dh_cls extra argument to @a dh + * @param ap list of options (type-value pairs, + * terminated with #MHD_OPTION_END). + * @return NULL on error, handle to daemon on success + * @ingroup event + */ +_MHD_EXTERN struct MHD_Daemon * +MHD_start_daemon_va (unsigned int flags, + uint16_t port, + MHD_AcceptPolicyCallback apc, void *apc_cls, + MHD_AccessHandlerCallback dh, void *dh_cls, + va_list ap); + + +/** + * Start a webserver on the given port. Variadic version of + * #MHD_start_daemon_va. + * + * @param flags combination of `enum MHD_FLAG` values + * @param port port to bind to (in host byte order), + * use '0' to bind to random free port, + * ignored if MHD_OPTION_SOCK_ADDR or + * MHD_OPTION_LISTEN_SOCKET is provided + * or MHD_USE_NO_LISTEN_SOCKET is specified + * @param apc callback to call to check which clients + * will be allowed to connect; you can pass NULL + * in which case connections from any IP will be + * accepted + * @param apc_cls extra argument to apc + * @param dh handler called for all requests (repeatedly) + * @param dh_cls extra argument to @a dh + * @return NULL on error, handle to daemon on success + * @ingroup event + */ +_MHD_EXTERN struct MHD_Daemon * +MHD_start_daemon (unsigned int flags, + uint16_t port, + MHD_AcceptPolicyCallback apc, void *apc_cls, + MHD_AccessHandlerCallback dh, void *dh_cls, + ...); + + +/** + * Stop accepting connections from the listening socket. Allows + * clients to continue processing, but stops accepting new + * connections. Note that the caller is responsible for closing the + * returned socket; however, if MHD is run using threads (anything but + * "external" sockets polling mode), it must not be closed until AFTER + * #MHD_stop_daemon has been called (as it is theoretically possible + * that an existing thread is still using it). + * + * Note that some thread modes require the caller to have passed + * #MHD_USE_ITC when using this API. If this daemon is + * in one of those modes and this option was not given to + * #MHD_start_daemon, this function will return #MHD_INVALID_SOCKET. + * + * @param daemon daemon to stop accepting new connections for + * @return old listen socket on success, #MHD_INVALID_SOCKET if + * the daemon was already not listening anymore + * @ingroup specialized + */ +_MHD_EXTERN MHD_socket +MHD_quiesce_daemon (struct MHD_Daemon *daemon); + + +/** + * Shutdown an HTTP daemon. + * + * @param daemon daemon to stop + * @ingroup event + */ +_MHD_EXTERN void +MHD_stop_daemon (struct MHD_Daemon *daemon); + + +/** + * Add another client connection to the set of connections managed by + * MHD. This API is usually not needed (since MHD will accept inbound + * connections on the server socket). Use this API in special cases, + * for example if your HTTP server is behind NAT and needs to connect + * out to the HTTP client, or if you are building a proxy. + * + * If you use this API in conjunction with an "internal" socket polling, + * you must set the option #MHD_USE_ITC to ensure that the freshly added + * connection is immediately processed by MHD. + * + * The given client socket will be managed (and closed!) by MHD after + * this call and must no longer be used directly by the application + * afterwards. + * + * @param daemon daemon that manages the connection + * @param client_socket socket to manage (MHD will expect + * to receive an HTTP request from this socket next). + * @param addr IP address of the client + * @param addrlen number of bytes in @a addr + * @return #MHD_YES on success, #MHD_NO if this daemon could + * not handle the connection (i.e. `malloc()` failed, etc). + * The socket will be closed in any case; `errno` is + * set to indicate further details about the error. + * @ingroup specialized + */ +_MHD_EXTERN enum MHD_Result +MHD_add_connection (struct MHD_Daemon *daemon, + MHD_socket client_socket, + const struct sockaddr *addr, + socklen_t addrlen); + + +/** + * Obtain the `select()` sets for this daemon. + * Daemon's FDs will be added to fd_sets. To get only + * daemon FDs in fd_sets, call FD_ZERO for each fd_set + * before calling this function. FD_SETSIZE is assumed + * to be platform's default. + * + * This function should be called only when MHD is configured to + * use "external" sockets polling with 'select()' or with 'epoll'. + * In the latter case, it will only add the single 'epoll' file + * descriptor used by MHD to the sets. + * It's necessary to use #MHD_get_timeout() to get maximum timeout + * value for `select()`. Usage of `select()` with indefinite timeout + * (or timeout larger than returned by #MHD_get_timeout()) will + * violate MHD API and may results in pending unprocessed data. + * + * This function must be called only for daemon started + * without #MHD_USE_INTERNAL_POLLING_THREAD flag. + * + * @param daemon daemon to get sets from + * @param read_fd_set read set + * @param write_fd_set write set + * @param except_fd_set except set + * @param max_fd increased to largest FD added (if larger + * than existing value); can be NULL + * @return #MHD_YES on success, #MHD_NO if this + * daemon was not started with the right + * options for this call or any FD didn't + * fit fd_set. + * @ingroup event + */ +_MHD_EXTERN enum MHD_Result +MHD_get_fdset (struct MHD_Daemon *daemon, + fd_set *read_fd_set, + fd_set *write_fd_set, + fd_set *except_fd_set, + MHD_socket *max_fd); + + +/** + * Obtain the `select()` sets for this daemon. + * Daemon's FDs will be added to fd_sets. To get only + * daemon FDs in fd_sets, call FD_ZERO for each fd_set + * before calling this function. + * + * Passing custom FD_SETSIZE as @a fd_setsize allow usage of + * larger/smaller than platform's default fd_sets. + * + * This function should be called only when MHD is configured to + * use "external" sockets polling with 'select()' or with 'epoll'. + * In the latter case, it will only add the single 'epoll' file + * descriptor used by MHD to the sets. + * It's necessary to use #MHD_get_timeout() to get maximum timeout + * value for `select()`. Usage of `select()` with indefinite timeout + * (or timeout larger than returned by #MHD_get_timeout()) will + * violate MHD API and may results in pending unprocessed data. + * + * This function must be called only for daemon started + * without #MHD_USE_INTERNAL_POLLING_THREAD flag. + * + * @param daemon daemon to get sets from + * @param read_fd_set read set + * @param write_fd_set write set + * @param except_fd_set except set + * @param max_fd increased to largest FD added (if larger + * than existing value); can be NULL + * @param fd_setsize value of FD_SETSIZE + * @return #MHD_YES on success, #MHD_NO if this + * daemon was not started with the right + * options for this call or any FD didn't + * fit fd_set. + * @ingroup event + */ +_MHD_EXTERN enum MHD_Result +MHD_get_fdset2 (struct MHD_Daemon *daemon, + fd_set *read_fd_set, + fd_set *write_fd_set, + fd_set *except_fd_set, + MHD_socket *max_fd, + unsigned int fd_setsize); + + +/** + * Obtain the `select()` sets for this daemon. + * Daemon's FDs will be added to fd_sets. To get only + * daemon FDs in fd_sets, call FD_ZERO for each fd_set + * before calling this function. Size of fd_set is + * determined by current value of FD_SETSIZE. + * + * This function should be called only when MHD is configured to + * use "external" sockets polling with 'select()' or with 'epoll'. + * In the latter case, it will only add the single 'epoll' file + * descriptor used by MHD to the sets. + * It's necessary to use #MHD_get_timeout() to get maximum timeout + * value for `select()`. Usage of `select()` with indefinite timeout + * (or timeout larger than returned by #MHD_get_timeout()) will + * violate MHD API and may results in pending unprocessed data. + * + * This function must be called only for daemon started + * without #MHD_USE_INTERNAL_POLLING_THREAD flag. + * + * @param daemon daemon to get sets from + * @param read_fd_set read set + * @param write_fd_set write set + * @param except_fd_set except set + * @param max_fd increased to largest FD added (if larger + * than existing value); can be NULL + * @return #MHD_YES on success, #MHD_NO if this + * daemon was not started with the right + * options for this call or any FD didn't + * fit fd_set. + * @ingroup event + */ +#define MHD_get_fdset(daemon,read_fd_set,write_fd_set,except_fd_set,max_fd) \ + MHD_get_fdset2 ((daemon),(read_fd_set),(write_fd_set),(except_fd_set), \ + (max_fd),FD_SETSIZE) + + +/** + * Obtain timeout value for polling function for this daemon. + * + * This function set value to the amount of milliseconds for which polling + * function (`select()`, `poll()` or epoll) should at most block, not the + * timeout value set for connections. + * + * Any "external" sockets polling function must be called with the timeout + * value provided by this function. Smaller timeout values can be used for + * polling function if it is required for any reason, but using larger + * timeout value or no timeout (indefinite timeout) when this function + * return #MHD_YES will break MHD processing logic and result in "hung" + * connections with data pending in network buffers and other problems. + * + * It is important to always use this function (or #MHD_get_timeout64(), + * #MHD_get_timeout64s(), #MHD_get_timeout_i() functions) when "external" + * polling is used. + * If this function returns #MHD_YES then #MHD_run() (or #MHD_run_from_select()) + * must be called right after return from polling function, regardless of + * the states of MHD FDs. + * + * In practice, if #MHD_YES is returned then #MHD_run() (or + * #MHD_run_from_select()) must be called not later than @a timeout + * millisecond even if no activity is detected on sockets by sockets + * polling function. + * + * @param daemon daemon to query for timeout + * @param[out] timeout set to the timeout (in milliseconds) + * @return #MHD_YES on success, #MHD_NO if timeouts are + * not used and no data processing is pending. + * @ingroup event + */ +_MHD_EXTERN enum MHD_Result +MHD_get_timeout (struct MHD_Daemon *daemon, + MHD_UNSIGNED_LONG_LONG *timeout); + + +/** + * Free the memory allocated by MHD. + * + * If any MHD function explicitly mentions that returned pointer must be + * freed by this function, then no other method must be used to free + * the memory. + * + * @param ptr the pointer to free. + * @sa #MHD_digest_auth_get_username(), #MHD_basic_auth_get_username_password3() + * @sa #MHD_basic_auth_get_username_password() + * @note Available since #MHD_VERSION 0x00095600 + * @ingroup specialized + */ +_MHD_EXTERN void +MHD_free (void *ptr); + +/** + * Obtain timeout value for external polling function for this daemon. + * + * This function set value to the amount of milliseconds for which polling + * function (`select()`, `poll()` or epoll) should at most block, not the + * timeout value set for connections. + * + * Any "external" sockets polling function must be called with the timeout + * value provided by this function. Smaller timeout values can be used for + * polling function if it is required for any reason, but using larger + * timeout value or no timeout (indefinite timeout) when this function + * return #MHD_YES will break MHD processing logic and result in "hung" + * connections with data pending in network buffers and other problems. + * + * It is important to always use this function (or #MHD_get_timeout(), + * #MHD_get_timeout64s(), #MHD_get_timeout_i() functions) when "external" + * polling is used. + * If this function returns #MHD_YES then #MHD_run() (or #MHD_run_from_select()) + * must be called right after return from polling function, regardless of + * the states of MHD FDs. + * + * In practice, if #MHD_YES is returned then #MHD_run() (or + * #MHD_run_from_select()) must be called not later than @a timeout + * millisecond even if no activity is detected on sockets by sockets + * polling function. + * + * @param daemon daemon to query for timeout + * @param[out] timeout64 the pointer to the variable to be set to the + * timeout (in milliseconds) + * @return #MHD_YES if timeout value has been set, + * #MHD_NO if timeouts are not used and no data processing is pending. + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup event + */ +_MHD_EXTERN enum MHD_Result +MHD_get_timeout64 (struct MHD_Daemon *daemon, + uint64_t *timeout); + + +/** + * Obtain timeout value for external polling function for this daemon. + * + * This function set value to the amount of milliseconds for which polling + * function (`select()`, `poll()` or epoll) should at most block, not the + * timeout value set for connections. + * + * Any "external" sockets polling function must be called with the timeout + * value provided by this function (if returned value is non-negative). + * Smaller timeout values can be used for polling function if it is required + * for any reason, but using larger timeout value or no timeout (indefinite + * timeout) when this function returns non-negative value will break MHD + * processing logic and result in "hung" connections with data pending in + * network buffers and other problems. + * + * It is important to always use this function (or #MHD_get_timeout(), + * #MHD_get_timeout64(), #MHD_get_timeout_i() functions) when "external" + * polling is used. + * If this function returns non-negative value then #MHD_run() (or + * #MHD_run_from_select()) must be called right after return from polling + * function, regardless of the states of MHD FDs. + * + * In practice, if zero or positive value is returned then #MHD_run() (or + * #MHD_run_from_select()) must be called not later than returned amount of + * millisecond even if no activity is detected on sockets by sockets + * polling function. + * + * @param daemon the daemon to query for timeout + * @return -1 if connections' timeouts are not set and no data processing + * is pending, so external polling function may wait for sockets + * activity for indefinite amount of time, + * otherwise returned value is the the maximum amount of millisecond + * that external polling function must wait for the activity of FDs. + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup event + */ +_MHD_EXTERN int64_t +MHD_get_timeout64s (struct MHD_Daemon *daemon); + + +/** + * Obtain timeout value for external polling function for this daemon. + * + * This function set value to the amount of milliseconds for which polling + * function (`select()`, `poll()` or epoll) should at most block, not the + * timeout value set for connections. + * + * Any "external" sockets polling function must be called with the timeout + * value provided by this function (if returned value is non-negative). + * Smaller timeout values can be used for polling function if it is required + * for any reason, but using larger timeout value or no timeout (indefinite + * timeout) when this function returns non-negative value will break MHD + * processing logic and result in "hung" connections with data pending in + * network buffers and other problems. + * + * It is important to always use this function (or #MHD_get_timeout(), + * #MHD_get_timeout64(), #MHD_get_timeout64s() functions) when "external" + * polling is used. + * If this function returns non-negative value then #MHD_run() (or + * #MHD_run_from_select()) must be called right after return from polling + * function, regardless of the states of MHD FDs. + * + * In practice, if zero or positive value is returned then #MHD_run() (or + * #MHD_run_from_select()) must be called not later than returned amount of + * millisecond even if no activity is detected on sockets by sockets + * polling function. + * + * @param daemon the daemon to query for timeout + * @return -1 if connections' timeouts are not set and no data processing + * is pending, so external polling function may wait for sockets + * activity for indefinite amount of time, + * otherwise returned value is the the maximum amount of millisecond + * (capped at INT_MAX) that external polling function must wait + * for the activity of FDs. + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup event + */ +_MHD_EXTERN int +MHD_get_timeout_i (struct MHD_Daemon *daemon); + + +/** + * Run webserver operations (without blocking unless in client callbacks). + * + * This method should be called by clients in combination with + * #MHD_get_fdset() (or #MHD_get_daemon_info() with MHD_DAEMON_INFO_EPOLL_FD + * if epoll is used) and #MHD_get_timeout() if the client-controlled + * connection polling method is used (i.e. daemon was started without + * #MHD_USE_INTERNAL_POLLING_THREAD flag). + * + * This function is a convenience method, which is useful if the + * fd_sets from #MHD_get_fdset were not directly passed to `select()`; + * with this function, MHD will internally do the appropriate `select()` + * call itself again. While it is acceptable to call #MHD_run (if + * #MHD_USE_INTERNAL_POLLING_THREAD is not set) at any moment, you should + * call #MHD_run_from_select() if performance is important (as it saves an + * expensive call to `select()`). + * + * If #MHD_get_timeout() returned #MHD_YES, than this function must be called + * right after polling function returns regardless of detected activity on + * the daemon's FDs. + * + * @param daemon daemon to run + * @return #MHD_YES on success, #MHD_NO if this + * daemon was not started with the right + * options for this call. + * @ingroup event + */ +_MHD_EXTERN enum MHD_Result +MHD_run (struct MHD_Daemon *daemon); + + +/** + * Run websever operation with possible blocking. + * + * This function does the following: waits for any network event not more than + * specified number of milliseconds, processes all incoming and outgoing data, + * processes new connections, processes any timed-out connection, and does + * other things required to run webserver. + * Once all connections are processed, function returns. + * + * This function is useful for quick and simple (lazy) webserver implementation + * if application needs to run a single thread only and does not have any other + * network activity. + * + * This function calls MHD_get_timeout() internally and use returned value as + * maximum wait time if it less than value of @a millisec parameter. + * + * It is expected that the "external" socket polling function is not used in + * conjunction with this function unless the @a millisec is set to zero. + * + * @param daemon the daemon to run + * @param millisec the maximum time in milliseconds to wait for network and + * other events. Note: there is no guarantee that function + * blocks for the specified amount of time. The real processing + * time can be shorter (if some data or connection timeout + * comes earlier) or longer (if data processing requires more + * time, especially in user callbacks). + * If set to '0' then function does not block and processes + * only already available data (if any). + * If set to '-1' then function waits for events + * indefinitely (blocks until next network activity or + * connection timeout). + * @return #MHD_YES on success, #MHD_NO if this + * daemon was not started with the right + * options for this call or some serious + * unrecoverable error occurs. + * @note Available since #MHD_VERSION 0x00097206 + * @ingroup event + */ +_MHD_EXTERN enum MHD_Result +MHD_run_wait (struct MHD_Daemon *daemon, + int32_t millisec); + + +/** + * Run webserver operations. This method should be called by clients + * in combination with #MHD_get_fdset and #MHD_get_timeout() if the + * client-controlled select method is used. + * + * You can use this function instead of #MHD_run if you called + * `select()` on the result from #MHD_get_fdset. File descriptors in + * the sets that are not controlled by MHD will be ignored. Calling + * this function instead of #MHD_run is more efficient as MHD will + * not have to call `select()` again to determine which operations are + * ready. + * + * If #MHD_get_timeout() returned #MHD_YES, than this function must be + * called right after `select()` returns regardless of detected activity + * on the daemon's FDs. + * + * This function cannot be used with daemon started with + * #MHD_USE_INTERNAL_POLLING_THREAD flag. + * + * @param daemon daemon to run select loop for + * @param read_fd_set read set + * @param write_fd_set write set + * @param except_fd_set except set + * @return #MHD_NO on serious errors, #MHD_YES on success + * @ingroup event + */ +_MHD_EXTERN enum MHD_Result +MHD_run_from_select (struct MHD_Daemon *daemon, + const fd_set *read_fd_set, + const fd_set *write_fd_set, + const fd_set *except_fd_set); + + +/** + * Run webserver operations. This method should be called by clients + * in combination with #MHD_get_fdset and #MHD_get_timeout() if the + * client-controlled select method is used. + * This function specifies FD_SETSIZE used when provided fd_sets were + * created. It is important on platforms where FD_SETSIZE can be + * overridden. + * + * You can use this function instead of #MHD_run if you called + * 'select()' on the result from #MHD_get_fdset2(). File descriptors in + * the sets that are not controlled by MHD will be ignored. Calling + * this function instead of #MHD_run() is more efficient as MHD will + * not have to call 'select()' again to determine which operations are + * ready. + * + * If #MHD_get_timeout() returned #MHD_YES, than this function must be + * called right after 'select()' returns regardless of detected activity + * on the daemon's FDs. + * + * This function cannot be used with daemon started with + * #MHD_USE_INTERNAL_POLLING_THREAD flag. + * + * @param daemon the daemon to run select loop for + * @param read_fd_set the read set + * @param write_fd_set the write set + * @param except_fd_set the except set + * @param fd_setsize the value of FD_SETSIZE + * @return #MHD_NO on serious errors, #MHD_YES on success + * @sa #MHD_get_fdset2(), #MHD_OPTION_APP_FD_SETSIZE + * @ingroup event + */ +_MHD_EXTERN enum MHD_Result +MHD_run_from_select2 (struct MHD_Daemon *daemon, + const fd_set *read_fd_set, + const fd_set *write_fd_set, + const fd_set *except_fd_set, + unsigned int fd_setsize); + + +/** + * Run webserver operations. This method should be called by clients + * in combination with #MHD_get_fdset and #MHD_get_timeout() if the + * client-controlled select method is used. + * This macro automatically substitutes current FD_SETSIZE value. + * It is important on platforms where FD_SETSIZE can be overridden. + * + * You can use this function instead of #MHD_run if you called + * 'select()' on the result from #MHD_get_fdset2(). File descriptors in + * the sets that are not controlled by MHD will be ignored. Calling + * this function instead of #MHD_run() is more efficient as MHD will + * not have to call 'select()' again to determine which operations are + * ready. + * + * If #MHD_get_timeout() returned #MHD_YES, than this function must be + * called right after 'select()' returns regardless of detected activity + * on the daemon's FDs. + * + * This function cannot be used with daemon started with + * #MHD_USE_INTERNAL_POLLING_THREAD flag. + * + * @param daemon the daemon to run select loop for + * @param read_fd_set the read set + * @param write_fd_set the write set + * @param except_fd_set the except set + * @param fd_setsize the value of FD_SETSIZE + * @return #MHD_NO on serious errors, #MHD_YES on success + * @sa #MHD_get_fdset2(), #MHD_OPTION_APP_FD_SETSIZE + * @ingroup event + */ +#define MHD_run_from_select(d,r,w,e) \ + MHD_run_from_select2 ((d),(r),(w),(e),(unsigned int) (FD_SETSIZE)) + +/* **************** Connection handling functions ***************** */ + + +/** + * Get request URI path (the request target without query part). + * + * The value obtained by this function is the same value as @a url provided + * for #MHD_AccessHandlerCallback callback, but this function also provides + * the size of the string. + * + * This function is critically important when binary zero is allowed by daemon + * option #MHD_OPTION_ALLOW_BIN_ZERO_IN_URI_PATH as this is the only way to + * get the non-truncated request URI. + * + * Returned @a uri pointer is valid until response is started or connection + * is terminated. + * + * @param connection the connection to URI from + * @param[out] uri set to the request URI without query part, may contain + * binary zeros (NUL) characters, never set to NULL on + * success; can be NULL + * @param[out] uri_size set to the size of the @a uri in bytes, not including + * final zero-termination; can be NULL + * @return #MHD_NO if failed (request is not yet processed or response has + * been queued already); + * #MHD_YES on success (*uri set to valid pointer) + * @note Available since #MHD_VERSION 0x01000201 + * @sa #MHD_OPTION_ALLOW_BIN_ZERO_IN_URI_PATH, #MHD_AccessHandlerCallback + * @ingroup request + */ +_MHD_EXTERN enum MHD_Result +MHD_get_connection_URI_path_n (struct MHD_Connection *connection, + const char **uri, + size_t *uri_size); + +/** + * Get all of the headers from the request. + * + * @param connection connection to get values from + * @param kind types of values to iterate over, can be a bitmask + * @param iterator callback to call on each header; + * may be NULL (then just count headers) + * @param iterator_cls extra argument to @a iterator + * @return number of entries iterated over, + * -1 if connection is NULL. + * @ingroup request + */ +_MHD_EXTERN int +MHD_get_connection_values (struct MHD_Connection *connection, + enum MHD_ValueKind kind, + MHD_KeyValueIterator iterator, + void *iterator_cls); + + +/** + * Get all of the headers from the request. + * + * @param connection connection to get values from + * @param kind types of values to iterate over, can be a bitmask + * @param iterator callback to call on each header; + * may be NULL (then just count headers) + * @param iterator_cls extra argument to @a iterator + * @return number of entries iterated over, + * -1 if connection is NULL. + * @note Available since #MHD_VERSION 0x00096400 + * @ingroup request + */ +_MHD_EXTERN int +MHD_get_connection_values_n (struct MHD_Connection *connection, + enum MHD_ValueKind kind, + MHD_KeyValueIteratorN iterator, + void *iterator_cls); + + +/** + * This function can be used to add an entry to the HTTP headers of a + * connection (so that the #MHD_get_connection_values function will + * return them -- and the `struct MHD_PostProcessor` will also see + * them). This maybe required in certain situations (see Mantis + * #1399) where (broken) HTTP implementations fail to supply values + * needed by the post processor (or other parts of the application). + * + * This function MUST only be called from within the + * #MHD_AccessHandlerCallback (otherwise, access maybe improperly + * synchronized). Furthermore, the client must guarantee that the key + * and value arguments are 0-terminated strings that are NOT freed + * until the connection is closed. (The easiest way to do this is by + * passing only arguments to permanently allocated strings.). + * + * @param connection the connection for which a + * value should be set + * @param kind kind of the value + * @param key key for the value + * @param value the value itself + * @return #MHD_NO if the operation could not be + * performed due to insufficient memory; + * #MHD_YES on success + * @ingroup request + */ +_MHD_EXTERN enum MHD_Result +MHD_set_connection_value (struct MHD_Connection *connection, + enum MHD_ValueKind kind, + const char *key, + const char *value); + + +/** + * This function can be used to add an arbitrary entry to connection. + * This function could add entry with binary zero, which is allowed + * for #MHD_GET_ARGUMENT_KIND. For other kind on entries it is + * recommended to use #MHD_set_connection_value. + * + * This function MUST only be called from within the + * #MHD_AccessHandlerCallback (otherwise, access maybe improperly + * synchronized). Furthermore, the client must guarantee that the key + * and value arguments are 0-terminated strings that are NOT freed + * until the connection is closed. (The easiest way to do this is by + * passing only arguments to permanently allocated strings.). + * + * @param connection the connection for which a + * value should be set + * @param kind kind of the value + * @param key key for the value, must be zero-terminated + * @param key_size number of bytes in @a key (excluding 0-terminator) + * @param value the value itself, must be zero-terminated + * @param value_size number of bytes in @a value (excluding 0-terminator) + * @return #MHD_NO if the operation could not be + * performed due to insufficient memory; + * #MHD_YES on success + * @note Available since #MHD_VERSION 0x00096400 + * @ingroup request + */ +_MHD_EXTERN enum MHD_Result +MHD_set_connection_value_n (struct MHD_Connection *connection, + enum MHD_ValueKind kind, + const char *key, + size_t key_size, + const char *value, + size_t value_size); + + +/** + * Sets the global error handler to a different implementation. + * + * @a cb will only be called in the case of typically fatal, serious internal + * consistency issues or serious system failures like failed lock of mutex. + * + * These issues should only arise in the case of serious memory corruption or + * similar problems with the architecture, there is no safe way to continue + * even for closing of the application. + * + * The default implementation that is used if no panic function is set simply + * prints an error message and calls `abort()`. + * Alternative implementations might call `exit()` or other similar functions. + * + * @param cb new error handler or NULL to use default handler + * @param cls passed to @a cb + * @ingroup logging + */ +_MHD_EXTERN void +MHD_set_panic_func (MHD_PanicCallback cb, void *cls); + + +/** + * Process escape sequences ('%HH') Updates val in place; the + * result cannot be larger than the input. + * The result is still be 0-terminated. + * + * @param val value to unescape (modified in the process) + * @return length of the resulting val (`strlen(val)` may be + * shorter afterwards due to elimination of escape sequences) + */ +_MHD_EXTERN size_t +MHD_http_unescape (char *val); + + +/** + * Get a particular header value. If multiple + * values match the kind, return any one of them. + * + * @param connection connection to get values from + * @param kind what kind of value are we looking for + * @param key the header to look for, NULL to lookup 'trailing' value without a key + * @return NULL if no such item was found + * @ingroup request + */ +_MHD_EXTERN const char * +MHD_lookup_connection_value (struct MHD_Connection *connection, + enum MHD_ValueKind kind, + const char *key); + + +/** + * Get a particular header value. If multiple + * values match the kind, return any one of them. + * @note Since MHD_VERSION 0x00096304 + * + * @param connection connection to get values from + * @param kind what kind of value are we looking for + * @param key the header to look for, NULL to lookup 'trailing' value without a key + * @param key_size the length of @a key in bytes + * @param[out] value_ptr the pointer to variable, which will be set to found value, + * will not be updated if key not found, + * could be NULL to just check for presence of @a key + * @param[out] value_size_ptr the pointer variable, which will set to found value, + * will not be updated if key not found, + * could be NULL + * @return #MHD_YES if key is found, + * #MHD_NO otherwise. + * @ingroup request + */ +_MHD_EXTERN enum MHD_Result +MHD_lookup_connection_value_n (struct MHD_Connection *connection, + enum MHD_ValueKind kind, + const char *key, + size_t key_size, + const char **value_ptr, + size_t *value_size_ptr); + + +/** + * Queue a response to be transmitted to the client (as soon as + * possible but after #MHD_AccessHandlerCallback returns). + * + * For any active connection this function must be called + * only by #MHD_AccessHandlerCallback callback. + * + * For suspended connection this function can be called at any moment (this + * behaviour is deprecated and will be removed!). Response will be sent + * as soon as connection is resumed. + * + * For single thread environment, when MHD is used in "external polling" mode + * (without MHD_USE_SELECT_INTERNALLY) this function can be called any + * time (this behaviour is deprecated and will be removed!). + * + * If HTTP specifications require use no body in reply, like @a status_code with + * value 1xx, the response body is automatically not sent even if it is present + * in the response. No "Content-Length" or "Transfer-Encoding" headers are + * generated and added. + * + * When the response is used to respond HEAD request or used with @a status_code + * #MHD_HTTP_NOT_MODIFIED, then response body is not sent, but "Content-Length" + * header is added automatically based the size of the body in the response. + * If body size it set to #MHD_SIZE_UNKNOWN or chunked encoding is enforced + * then "Transfer-Encoding: chunked" header (for HTTP/1.1 only) is added instead + * of "Content-Length" header. For example, if response with zero-size body is + * used for HEAD request, then "Content-Length: 0" is added automatically to + * reply headers. + * @sa #MHD_RF_HEAD_ONLY_RESPONSE + * + * In situations, where reply body is required, like answer for the GET request + * with @a status_code #MHD_HTTP_OK, headers "Content-Length" (for known body + * size) or "Transfer-Encoding: chunked" (for #MHD_SIZE_UNKNOWN with HTTP/1.1) + * are added automatically. + * In practice, the same response object can be used to respond to both HEAD and + * GET requests. + * + * @param connection the connection identifying the client + * @param status_code HTTP status code (i.e. #MHD_HTTP_OK) + * @param response response to transmit, the NULL is tolerated + * @return #MHD_NO on error (reply already sent, response is NULL), + * #MHD_YES on success or if message has been queued + * @ingroup response + * @sa #MHD_AccessHandlerCallback + */ +_MHD_EXTERN enum MHD_Result +MHD_queue_response (struct MHD_Connection *connection, + unsigned int status_code, + struct MHD_Response *response); + + +/** + * Suspend handling of network data for a given connection. + * This can be used to dequeue a connection from MHD's event loop + * (not applicable to thread-per-connection!) for a while. + * + * If you use this API in conjunction with an "internal" socket polling, + * you must set the option #MHD_USE_ITC to ensure that a resumed + * connection is immediately processed by MHD. + * + * Suspended connections continue to count against the total number of + * connections allowed (per daemon, as well as per IP, if such limits + * are set). Suspended connections will NOT time out; timeouts will + * restart when the connection handling is resumed. While a + * connection is suspended, MHD will not detect disconnects by the + * client. + * + * The only safe way to call this function is to call it from the + * #MHD_AccessHandlerCallback or #MHD_ContentReaderCallback. + * + * Finally, it is an API violation to call #MHD_stop_daemon while + * having suspended connections (this will at least create memory and + * socket leaks or lead to undefined behavior). You must explicitly + * resume all connections before stopping the daemon. + * + * @param connection the connection to suspend + * + * @sa #MHD_AccessHandlerCallback + */ +_MHD_EXTERN void +MHD_suspend_connection (struct MHD_Connection *connection); + + +/** + * Resume handling of network data for suspended connection. It is + * safe to resume a suspended connection at any time. Calling this + * function on a connection that was not previously suspended will + * result in undefined behavior. + * + * If you are using this function in "external" sockets polling mode, you must + * make sure to run #MHD_run() and #MHD_get_timeout() afterwards (before + * again calling #MHD_get_fdset()), as otherwise the change may not be + * reflected in the set returned by #MHD_get_fdset() and you may end up + * with a connection that is stuck until the next network activity. + * + * @param connection the connection to resume + */ +_MHD_EXTERN void +MHD_resume_connection (struct MHD_Connection *connection); + + +/* **************** Response manipulation functions ***************** */ + + +/** + * Flags for special handling of responses. + */ +enum MHD_ResponseFlags +{ + /** + * Default: no special flags. + * @note Available since #MHD_VERSION 0x00093701 + */ + MHD_RF_NONE = 0, + + /** + * Only respond in conservative (dumb) HTTP/1.0-compatible mode. + * Response still use HTTP/1.1 version in header, but always close + * the connection after sending the response and do not use chunked + * encoding for the response. + * You can also set the #MHD_RF_HTTP_1_0_SERVER flag to force + * HTTP/1.0 version in the response. + * Responses are still compatible with HTTP/1.1. + * This option can be used to communicate with some broken client, which + * does not implement HTTP/1.1 features, but advertises HTTP/1.1 support. + * @note Available since #MHD_VERSION 0x00097308 + */ + MHD_RF_HTTP_1_0_COMPATIBLE_STRICT = 1 << 0, + /** + * The same as #MHD_RF_HTTP_1_0_COMPATIBLE_STRICT + * @note Available since #MHD_VERSION 0x00093701 + */ + MHD_RF_HTTP_VERSION_1_0_ONLY = 1 << 0, + + /** + * Only respond in HTTP 1.0-mode. + * Contrary to the #MHD_RF_HTTP_1_0_COMPATIBLE_STRICT flag, the response's + * HTTP version will always be set to 1.0 and keep-alive connections + * will be used if explicitly requested by the client. + * The "Connection:" header will be added for both "close" and "keep-alive" + * connections. + * Chunked encoding will not be used for the response. + * Due to backward compatibility, responses still can be used with + * HTTP/1.1 clients. + * This option can be used to emulate HTTP/1.0 server (for response part + * only as chunked encoding in requests (if any) is processed by MHD). + * @note Available since #MHD_VERSION 0x00097308 + */ + MHD_RF_HTTP_1_0_SERVER = 1 << 1, + /** + * The same as #MHD_RF_HTTP_1_0_SERVER + * @note Available since #MHD_VERSION 0x00096000 + */ + MHD_RF_HTTP_VERSION_1_0_RESPONSE = 1 << 1, + + /** + * Disable sanity check preventing clients from manually + * setting the HTTP content length option. + * Allow to set several "Content-Length" headers. These headers will + * be used even with replies without body. + * @note Available since #MHD_VERSION 0x00096702 + */ + MHD_RF_INSANITY_HEADER_CONTENT_LENGTH = 1 << 2, + + /** + * Enable sending of "Connection: keep-alive" header even for + * HTTP/1.1 clients when "Keep-Alive" connection is used. + * Disabled by default for HTTP/1.1 clients as per RFC. + * @note Available since #MHD_VERSION 0x00097310 + */ + MHD_RF_SEND_KEEP_ALIVE_HEADER = 1 << 3, + + /** + * Enable special processing of the response as body-less (with undefined + * body size). No automatic "Content-Length" or "Transfer-Encoding: chunked" + * headers are added when the response is used with #MHD_HTTP_NOT_MODIFIED + * code or to respond to HEAD request. + * The flag also allow to set arbitrary "Content-Length" by + * MHD_add_response_header() function. + * This flag value can be used only with responses created without body + * (zero-size body). + * Responses with this flag enabled cannot be used in situations where + * reply body must be sent to the client. + * This flag is primarily intended to be used when automatic "Content-Length" + * header is undesirable in response to HEAD requests. + * @note Available since #MHD_VERSION 0x00097701 + */ + MHD_RF_HEAD_ONLY_RESPONSE = 1 << 4 +} _MHD_FIXED_FLAGS_ENUM; + + +/** + * MHD options (for future extensions). + */ +enum MHD_ResponseOptions +{ + /** + * End of the list of options. + */ + MHD_RO_END = 0 +} _MHD_FIXED_ENUM; + + +/** + * Set special flags and options for a response. + * + * @param response the response to modify + * @param flags to set for the response + * @param ... #MHD_RO_END terminated list of options + * @return #MHD_YES on success, #MHD_NO on error + */ +_MHD_EXTERN enum MHD_Result +MHD_set_response_options (struct MHD_Response *response, + enum MHD_ResponseFlags flags, + ...); + + +/** + * Create a response object. + * The response object can be extended with header information and then be used + * any number of times. + * + * If response object is used to answer HEAD request then the body of the + * response is not used, while all headers (including automatic headers) are + * used. + * + * @param size size of the data portion of the response, #MHD_SIZE_UNKNOWN for unknown + * @param block_size preferred block size for querying crc (advisory only, + * MHD may still call @a crc using smaller chunks); this + * is essentially the buffer size used for IO, clients + * should pick a value that is appropriate for IO and + * memory performance requirements + * @param crc callback to use to obtain response data + * @param crc_cls extra argument to @a crc + * @param crfc callback to call to free @a crc_cls resources + * @return NULL on error (i.e. invalid arguments, out of memory) + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_callback (uint64_t size, + size_t block_size, + MHD_ContentReaderCallback crc, void *crc_cls, + MHD_ContentReaderFreeCallback crfc); + + +/** + * Create a response object. + * The response object can be extended with header information and then be used + * any number of times. + * + * If response object is used to answer HEAD request then the body of the + * response is not used, while all headers (including automatic headers) are + * used. + * + * @param size size of the @a data portion of the response + * @param data the data itself + * @param must_free libmicrohttpd should free data when done + * @param must_copy libmicrohttpd must make a copy of @a data + * right away, the data may be released anytime after + * this call returns + * @return NULL on error (i.e. invalid arguments, out of memory) + * @deprecated use #MHD_create_response_from_buffer instead + * @ingroup response + */ +_MHD_DEPR_FUNC ( \ + "MHD_create_response_from_data() is deprecated, use MHD_create_response_from_buffer()" \ + ) \ + _MHD_EXTERN struct MHD_Response * +MHD_create_response_from_data (size_t size, + void *data, + int must_free, + int must_copy); + + +/** + * Specification for how MHD should treat the memory buffer + * given for the response. + * @ingroup response + */ +enum MHD_ResponseMemoryMode +{ + + /** + * Buffer is a persistent (static/global) buffer that won't change + * for at least the lifetime of the response, MHD should just use + * it, not free it, not copy it, just keep an alias to it. + * @ingroup response + */ + MHD_RESPMEM_PERSISTENT, + + /** + * Buffer is heap-allocated with `malloc()` (or equivalent) and + * should be freed by MHD after processing the response has + * concluded (response reference counter reaches zero). + * The more portable way to automatically free the buffer is function + * MHD_create_response_from_buffer_with_free_callback() with '&free' as + * crfc parameter as it does not require to use the same runtime library. + * @warning It is critical to make sure that the same C-runtime library + * is used by both application and MHD (especially + * important for W32). + * @ingroup response + */ + MHD_RESPMEM_MUST_FREE, + + /** + * Buffer is in transient memory, but not on the heap (for example, + * on the stack or non-`malloc()` allocated) and only valid during the + * call to #MHD_create_response_from_buffer. MHD must make its + * own private copy of the data for processing. + * @ingroup response + */ + MHD_RESPMEM_MUST_COPY + +} _MHD_FIXED_ENUM; + + +/** + * Create a response object with the content of provided buffer used as + * the response body. + * + * The response object can be extended with header information and then + * be used any number of times. + * + * If response object is used to answer HEAD request then the body + * of the response is not used, while all headers (including automatic + * headers) are used. + * + * @param size size of the data portion of the response + * @param buffer size bytes containing the response's data portion + * @param mode flags for buffer management + * @return NULL on error (i.e. invalid arguments, out of memory) + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_buffer (size_t size, + void *buffer, + enum MHD_ResponseMemoryMode mode); + + +/** + * Create a response object with the content of provided statically allocated + * buffer used as the response body. + * + * The buffer must be valid for the lifetime of the response. The easiest way + * to achieve this is to use a statically allocated buffer. + * + * The response object can be extended with header information and then + * be used any number of times. + * + * If response object is used to answer HEAD request then the body + * of the response is not used, while all headers (including automatic + * headers) are used. + * + * @param size the size of the data in @a buffer, can be zero + * @param buffer the buffer with the data for the response body, can be NULL + * if @a size is zero + * @return NULL on error (i.e. invalid arguments, out of memory) + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_buffer_static (size_t size, + const void *buffer); + + +/** + * Create a response object with the content of provided temporal buffer + * used as the response body. + * + * An internal copy of the buffer will be made automatically, so buffer have + * to be valid only during the call of this function (as a typical example: + * buffer is a local (non-static) array). + * + * The response object can be extended with header information and then + * be used any number of times. + * + * If response object is used to answer HEAD request then the body + * of the response is not used, while all headers (including automatic + * headers) are used. + * + * @param size the size of the data in @a buffer, can be zero + * @param buffer the buffer with the data for the response body, can be NULL + * if @a size is zero + * @return NULL on error (i.e. invalid arguments, out of memory) + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_buffer_copy (size_t size, + const void *buffer); + + +/** + * Create a response object with the content of provided buffer used as + * the response body. + * + * The response object can be extended with header information and then + * be used any number of times. + * + * If response object is used to answer HEAD request then the body + * of the response is not used, while all headers (including automatic + * headers) are used. + * + * @param size size of the data portion of the response + * @param buffer size bytes containing the response's data portion + * @param crfc function to call to free the @a buffer + * @return NULL on error (i.e. invalid arguments, out of memory) + * @note Available since #MHD_VERSION 0x00096000 + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_buffer_with_free_callback (size_t size, + void *buffer, + MHD_ContentReaderFreeCallback + crfc); + + +/** + * Create a response object with the content of provided buffer used as + * the response body. + * + * The response object can be extended with header information and then + * be used any number of times. + * + * If response object is used to answer HEAD request then the body + * of the response is not used, while all headers (including automatic + * headers) are used. + * + * @param size size of the data portion of the response + * @param buffer size bytes containing the response's data portion + * @param crfc function to call to cleanup, if set to NULL then callback + * is not called + * @param crfc_cls an argument for @a crfc + * @return NULL on error (i.e. invalid arguments, out of memory) + * @note Available since #MHD_VERSION 0x00097302 + * @note 'const' qualifier is used for @a buffer since #MHD_VERSION 0x00097701 + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_buffer_with_free_callback_cls (size_t size, + const void *buffer, + MHD_ContentReaderFreeCallback + crfc, + void *crfc_cls); + + +/** + * Create a response object with the content of provided file used as + * the response body. + * + * The response object can be extended with header information and then + * be used any number of times. + * + * If response object is used to answer HEAD request then the body + * of the response is not used, while all headers (including automatic + * headers) are used. + * + * @param size size of the data portion of the response + * @param fd file descriptor referring to a file on disk with the + * data; will be closed when response is destroyed; + * fd should be in 'blocking' mode + * @return NULL on error (i.e. invalid arguments, out of memory) + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_fd (size_t size, + int fd); + + +/** + * Create a response object with the response body created by reading + * the provided pipe. + * + * The response object can be extended with header information and + * then be used ONLY ONCE. + * + * If response object is used to answer HEAD request then the body + * of the response is not used, while all headers (including automatic + * headers) are used. + * + * @param fd file descriptor referring to a read-end of a pipe with the + * data; will be closed when response is destroyed; + * fd should be in 'blocking' mode + * @return NULL on error (i.e. invalid arguments, out of memory) + * @note Available since #MHD_VERSION 0x00097102 + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_pipe (int fd); + + +/** + * Create a response object with the content of provided file used as + * the response body. + * + * The response object can be extended with header information and then + * be used any number of times. + * + * If response object is used to answer HEAD request then the body + * of the response is not used, while all headers (including automatic + * headers) are used. + * + * @param size size of the data portion of the response; + * sizes larger than 2 GiB may be not supported by OS or + * MHD build; see ::MHD_FEATURE_LARGE_FILE + * @param fd file descriptor referring to a file on disk with the + * data; will be closed when response is destroyed; + * fd should be in 'blocking' mode + * @return NULL on error (i.e. invalid arguments, out of memory) + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_fd64 (uint64_t size, + int fd); + + +/** + * Create a response object with the content of provided file with + * specified offset used as the response body. + * + * The response object can be extended with header information and then + * be used any number of times. + * + * If response object is used to answer HEAD request then the body + * of the response is not used, while all headers (including automatic + * headers) are used. + * + * @param size size of the data portion of the response + * @param fd file descriptor referring to a file on disk with the + * data; will be closed when response is destroyed; + * fd should be in 'blocking' mode + * @param offset offset to start reading from in the file; + * Be careful! `off_t` may have been compiled to be a + * 64-bit variable for MHD, in which case your application + * also has to be compiled using the same options! Read + * the MHD manual for more details. + * @return NULL on error (i.e. invalid arguments, out of memory) + * @ingroup response + */ +_MHD_DEPR_FUNC ( \ + "Function MHD_create_response_from_fd_at_offset() is deprecated, use MHD_create_response_from_fd_at_offset64()" \ + ) \ + _MHD_EXTERN struct MHD_Response * +MHD_create_response_from_fd_at_offset (size_t size, + int fd, + off_t offset); + +#if ! defined(_MHD_NO_DEPR_IN_MACRO) || defined(_MHD_NO_DEPR_FUNC) +/* Substitute MHD_create_response_from_fd_at_offset64() instead of MHD_create_response_from_fd_at_offset() + to minimize potential problems with different off_t sizes */ +#define MHD_create_response_from_fd_at_offset(size,fd,offset) \ + _MHD_DEPR_IN_MACRO ( \ + "Usage of MHD_create_response_from_fd_at_offset() is deprecated, use MHD_create_response_from_fd_at_offset64()") \ + MHD_create_response_from_fd_at_offset64 ((size),(fd),(offset)) +#endif /* !_MHD_NO_DEPR_IN_MACRO || _MHD_NO_DEPR_FUNC */ + + +/** + * Create a response object with the content of provided file with + * specified offset used as the response body. + * + * The response object can be extended with header information and then + * be used any number of times. + * + * If response object is used to answer HEAD request then the body + * of the response is not used, while all headers (including automatic + * headers) are used. + * + * @param size size of the data portion of the response; + * sizes larger than 2 GiB may be not supported by OS or + * MHD build; see ::MHD_FEATURE_LARGE_FILE + * @param fd file descriptor referring to a file on disk with the + * data; will be closed when response is destroyed; + * fd should be in 'blocking' mode + * @param offset offset to start reading from in the file; + * reading file beyond 2 GiB may be not supported by OS or + * MHD build; see ::MHD_FEATURE_LARGE_FILE + * @return NULL on error (i.e. invalid arguments, out of memory) + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_fd_at_offset64 (uint64_t size, + int fd, + uint64_t offset); + + +/** + * Create a response object with an array of memory buffers + * used as the response body. + * + * The response object can be extended with header information and then + * be used any number of times. + * + * If response object is used to answer HEAD request then the body + * of the response is not used, while all headers (including automatic + * headers) are used. + * + * @param iov the array for response data buffers, an internal copy of this + * will be made + * @param iovcnt the number of elements in @a iov + * @param free_cb the callback to clean up any data associated with @a iov when + * the response is destroyed. + * @param cls the argument passed to @a free_cb + * @return NULL on error (i.e. invalid arguments, out of memory) + * @note Available since #MHD_VERSION 0x00097204 + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_iovec (const struct MHD_IoVec *iov, + unsigned int iovcnt, + MHD_ContentReaderFreeCallback free_cb, + void *cls); + + +/** + * Create a response object with empty (zero size) body. + * + * The response object can be extended with header information and then be used + * any number of times. + * + * This function is a faster equivalent of #MHD_create_response_from_buffer call + * with zero size combined with call of #MHD_set_response_options. + * + * @param flags the flags for the new response object + * @return NULL on error (i.e. invalid arguments, out of memory), + * the pointer to the created response object otherwise + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_empty (enum MHD_ResponseFlags flags); + + +/** + * Enumeration for actions MHD should perform on the underlying socket + * of the upgrade. This API is not finalized, and in particular + * the final set of actions is yet to be decided. This is just an + * idea for what we might want. + */ +enum MHD_UpgradeAction +{ + + /** + * Close the socket, the application is done with it. + * + * Takes no extra arguments. + */ + MHD_UPGRADE_ACTION_CLOSE = 0, + + /** + * Enable CORKing on the underlying socket. + */ + MHD_UPGRADE_ACTION_CORK_ON = 1, + + /** + * Disable CORKing on the underlying socket. + */ + MHD_UPGRADE_ACTION_CORK_OFF = 2 + +} _MHD_FIXED_ENUM; + + +/** + * Handle given to the application to manage special + * actions relating to MHD responses that "upgrade" + * the HTTP protocol (i.e. to WebSockets). + */ +struct MHD_UpgradeResponseHandle; + + +/** + * This connection-specific callback is provided by MHD to + * applications (unusual) during the #MHD_UpgradeHandler. + * It allows applications to perform 'special' actions on + * the underlying socket from the upgrade. + * + * @param urh the handle identifying the connection to perform + * the upgrade @a action on. + * @param action which action should be performed + * @param ... arguments to the action (depends on the action) + * @return #MHD_NO on error, #MHD_YES on success + */ +_MHD_EXTERN enum MHD_Result +MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh, + enum MHD_UpgradeAction action, + ...); + + +/** + * Function called after a protocol "upgrade" response was sent + * successfully and the socket should now be controlled by some + * protocol other than HTTP. + * + * Any data already received on the socket will be made available in + * @e extra_in. This can happen if the application sent extra data + * before MHD send the upgrade response. The application should + * treat data from @a extra_in as if it had read it from the socket. + * + * Note that the application must not close() @a sock directly, + * but instead use #MHD_upgrade_action() for special operations + * on @a sock. + * + * Data forwarding to "upgraded" @a sock will be started as soon + * as this function return. + * + * Except when in 'thread-per-connection' mode, implementations + * of this function should never block (as it will still be called + * from within the main event loop). + * + * @param cls closure, whatever was given to #MHD_create_response_for_upgrade(). + * @param connection original HTTP connection handle, + * giving the function a last chance + * to inspect the original HTTP request + * @param req_cls last value left in `req_cls` of the `MHD_AccessHandlerCallback` + * @param extra_in if we happened to have read bytes after the + * HTTP header already (because the client sent + * more than the HTTP header of the request before + * we sent the upgrade response), + * these are the extra bytes already read from @a sock + * by MHD. The application should treat these as if + * it had read them from @a sock. + * @param extra_in_size number of bytes in @a extra_in + * @param sock socket to use for bi-directional communication + * with the client. For HTTPS, this may not be a socket + * that is directly connected to the client and thus certain + * operations (TCP-specific setsockopt(), getsockopt(), etc.) + * may not work as expected (as the socket could be from a + * socketpair() or a TCP-loopback). The application is expected + * to perform read()/recv() and write()/send() calls on the socket. + * The application may also call shutdown(), but must not call + * close() directly. + * @param urh argument for #MHD_upgrade_action()s on this @a connection. + * Applications must eventually use this callback to (indirectly) + * perform the close() action on the @a sock. + */ +typedef void +(*MHD_UpgradeHandler)(void *cls, + struct MHD_Connection *connection, + void *req_cls, + const char *extra_in, + size_t extra_in_size, + MHD_socket sock, + struct MHD_UpgradeResponseHandle *urh); + + +/** + * Create a response object that can be used for 101 UPGRADE + * responses, for example to implement WebSockets. After sending the + * response, control over the data stream is given to the callback (which + * can then, for example, start some bi-directional communication). + * If the response is queued for multiple connections, the callback + * will be called for each connection. The callback + * will ONLY be called after the response header was successfully passed + * to the OS; if there are communication errors before, the usual MHD + * connection error handling code will be performed. + * + * Setting the correct HTTP code (i.e. MHD_HTTP_SWITCHING_PROTOCOLS) + * and setting correct HTTP headers for the upgrade must be done + * manually (this way, it is possible to implement most existing + * WebSocket versions using this API; in fact, this API might be useful + * for any protocol switch, not just WebSockets). Note that + * draft-ietf-hybi-thewebsocketprotocol-00 cannot be implemented this + * way as the header "HTTP/1.1 101 WebSocket Protocol Handshake" + * cannot be generated; instead, MHD will always produce "HTTP/1.1 101 + * Switching Protocols" (if the response code 101 is used). + * + * As usual, the response object can be extended with header + * information and then be used any number of times (as long as the + * header information is not connection-specific). + * + * @param upgrade_handler function to call with the "upgraded" socket + * @param upgrade_handler_cls closure for @a upgrade_handler + * @return NULL on error (i.e. invalid arguments, out of memory) + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_for_upgrade (MHD_UpgradeHandler upgrade_handler, + void *upgrade_handler_cls); + + +/** + * Destroy a response object and associated resources. Note that + * libmicrohttpd may keep some of the resources around if the response + * is still in the queue for some clients, so the memory may not + * necessarily be freed immediately. + * + * @param response response to destroy + * @ingroup response + */ +_MHD_EXTERN void +MHD_destroy_response (struct MHD_Response *response); + + +/** + * Add a header line to the response. + * + * When reply is generated with queued response, some headers are generated + * automatically. Automatically generated headers are only sent to the client, + * but not added back to the response object. + * + * The list of automatic headers: + * + "Date" header is added automatically unless already set by + * this function + * @see #MHD_USE_SUPPRESS_DATE_NO_CLOCK + * + "Content-Length" is added automatically when required, attempt to set + * it manually by this function is ignored. + * @see #MHD_RF_INSANITY_HEADER_CONTENT_LENGTH + * + "Transfer-Encoding" with value "chunked" is added automatically, + * when chunked transfer encoding is used automatically. Same header with + * the same value can be set manually by this function to enforce chunked + * encoding, however for HTTP/1.0 clients chunked encoding will not be used + * and manually set "Transfer-Encoding" header is automatically removed + * for HTTP/1.0 clients + * + "Connection" may be added automatically with value "Keep-Alive" (only + * for HTTP/1.0 clients) or "Close". The header "Connection" with value + * "Close" could be set by this function to enforce closure of + * the connection after sending this response. "Keep-Alive" cannot be + * enforced and will be removed automatically. + * @see #MHD_RF_SEND_KEEP_ALIVE_HEADER + * + * Some headers are pre-processed by this function: + * * "Connection" headers are combined into single header entry, value is + * normilised, "Keep-Alive" tokens are removed. + * * "Transfer-Encoding" header: the only one header is allowed, the only + * allowed value is "chunked". + * * "Date" header: the only one header is allowed, the second added header + * replaces the first one. + * * "Content-Length" application-defined header is not allowed. + * @see #MHD_RF_INSANITY_HEADER_CONTENT_LENGTH + * + * Headers are used in order as they were added. + * + * @param response the response to add a header to + * @param header the header name to add, no need to be static, an internal copy + * will be created automatically + * @param content the header value to add, no need to be static, an internal + * copy will be created automatically + * @return #MHD_YES on success, + * #MHD_NO on error (i.e. invalid header or content format), + * or out of memory + * @ingroup response + */ +_MHD_EXTERN enum MHD_Result +MHD_add_response_header (struct MHD_Response *response, + const char *header, + const char *content); + + +/** + * Add a footer line to the response. + * + * @param response response to remove a header from + * @param footer the footer to delete + * @param content value to delete + * @return #MHD_NO on error (i.e. invalid footer or content format). + * @ingroup response + */ +_MHD_EXTERN enum MHD_Result +MHD_add_response_footer (struct MHD_Response *response, + const char *footer, + const char *content); + + +/** + * Delete a header (or footer) line from the response. + * + * For "Connection" headers this function remove all tokens from existing + * value. Successful result means that at least one token has been removed. + * If all tokens are removed from "Connection" header, the empty "Connection" + * header removed. + * + * @param response response to remove a header from + * @param header the header to delete + * @param content value to delete + * @return #MHD_NO on error (no such header known) + * @ingroup response + */ +_MHD_EXTERN enum MHD_Result +MHD_del_response_header (struct MHD_Response *response, + const char *header, + const char *content); + + +/** + * Get all of the headers (and footers) added to a response. + * + * @param response response to query + * @param iterator callback to call on each header; + * may be NULL (then just count headers) + * @param iterator_cls extra argument to @a iterator + * @return number of entries iterated over + * @ingroup response + */ +_MHD_EXTERN int +MHD_get_response_headers (struct MHD_Response *response, + MHD_KeyValueIterator iterator, + void *iterator_cls); + + +/** + * Get a particular header (or footer) from the response. + * + * @param response response to query + * @param key which header to get + * @return NULL if header does not exist + * @ingroup response + */ +_MHD_EXTERN const char * +MHD_get_response_header (struct MHD_Response *response, + const char *key); + + +/* ********************** PostProcessor functions ********************** */ + +/** + * Create a `struct MHD_PostProcessor`. + * + * A `struct MHD_PostProcessor` can be used to (incrementally) parse + * the data portion of a POST request. Note that some buggy browsers + * fail to set the encoding type. If you want to support those, you + * may have to call #MHD_set_connection_value with the proper encoding + * type before creating a post processor (if no supported encoding + * type is set, this function will fail). + * + * @param connection the connection on which the POST is + * happening (used to determine the POST format) + * @param buffer_size maximum number of bytes to use for + * internal buffering (used only for the parsing, + * specifically the parsing of the keys). A + * tiny value (256-1024) should be sufficient. + * Do NOT use a value smaller than 256. For good + * performance, use 32 or 64k (i.e. 65536). + * @param iter iterator to be called with the parsed data, + * Must NOT be NULL. + * @param iter_cls first argument to @a iter + * @return NULL on error (out of memory, unsupported encoding), + * otherwise a PP handle + * @ingroup request + */ +_MHD_EXTERN struct MHD_PostProcessor * +MHD_create_post_processor (struct MHD_Connection *connection, + size_t buffer_size, + MHD_PostDataIterator iter, void *iter_cls); + + +/** + * Parse and process POST data. Call this function when POST data is + * available (usually during an #MHD_AccessHandlerCallback) with the + * "upload_data" and "upload_data_size". Whenever possible, this will + * then cause calls to the #MHD_PostDataIterator. + * + * @param pp the post processor + * @param post_data @a post_data_len bytes of POST data + * @param post_data_len length of @a post_data + * @return #MHD_YES on success, #MHD_NO on error + * (out-of-memory, iterator aborted, parse error) + * @ingroup request + */ +_MHD_EXTERN enum MHD_Result +MHD_post_process (struct MHD_PostProcessor *pp, + const char *post_data, + size_t post_data_len); + + +/** + * Release PostProcessor resources. + * + * @param pp the PostProcessor to destroy + * @return #MHD_YES if processing completed nicely, + * #MHD_NO if there were spurious characters / formatting + * problems; it is common to ignore the return + * value of this function + * @ingroup request + */ +_MHD_EXTERN enum MHD_Result +MHD_destroy_post_processor (struct MHD_PostProcessor *pp); + + +/* ********************* Digest Authentication functions *************** */ + + +/** + * Length of the binary output of the MD5 hash function. + * @sa #MHD_digest_get_hash_size() + * @ingroup authentication + */ +#define MHD_MD5_DIGEST_SIZE 16 + +/** + * Length of the binary output of the SHA-256 hash function. + * @sa #MHD_digest_get_hash_size() + * @ingroup authentication + */ +#define MHD_SHA256_DIGEST_SIZE 32 + +/** + * Length of the binary output of the SHA-512/256 hash function. + * @warning While this value is the same as the #MHD_SHA256_DIGEST_SIZE, + * the calculated digests for SHA-256 and SHA-512/256 are different. + * @sa #MHD_digest_get_hash_size() + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup authentication + */ +#define MHD_SHA512_256_DIGEST_SIZE 32 + +/** + * Base type of hash calculation. + * Used as part of #MHD_DigestAuthAlgo3 values. + * + * @warning Not used directly by MHD API. + * @note Available since #MHD_VERSION 0x00097701 + */ +enum MHD_DigestBaseAlgo +{ + /** + * Invalid hash algorithm value + */ + MHD_DIGEST_BASE_ALGO_INVALID = 0, + + /** + * MD5 hash algorithm. + * As specified by RFC1321 + */ + MHD_DIGEST_BASE_ALGO_MD5 = (1 << 0), + + /** + * SHA-256 hash algorithm. + * As specified by FIPS PUB 180-4 + */ + MHD_DIGEST_BASE_ALGO_SHA256 = (1 << 1), + + /** + * SHA-512/256 hash algorithm. + * As specified by FIPS PUB 180-4 + */ + MHD_DIGEST_BASE_ALGO_SHA512_256 = (1 << 2) +} _MHD_FIXED_FLAGS_ENUM; + +/** + * The flag indicating non-session algorithm types, + * like 'MD5', 'SHA-256' or 'SHA-512-256'. + * @note Available since #MHD_VERSION 0x00097701 + */ +#define MHD_DIGEST_AUTH_ALGO3_NON_SESSION (1 << 6) + +/** + * The flag indicating session algorithm types, + * like 'MD5-sess', 'SHA-256-sess' or 'SHA-512-256-sess'. + * @note Available since #MHD_VERSION 0x00097701 + */ +#define MHD_DIGEST_AUTH_ALGO3_SESSION (1 << 7) + +/** + * Digest algorithm identification + * @warning Do not be confused with #MHD_DigestAuthAlgorithm, + * which uses other values! + * @note Available since #MHD_VERSION 0x00097701 + */ +enum MHD_DigestAuthAlgo3 +{ + /** + * Unknown or wrong algorithm type. + * Used in struct MHD_DigestAuthInfo to indicate client value that + * cannot by identified. + */ + MHD_DIGEST_AUTH_ALGO3_INVALID = 0, + + /** + * The 'MD5' algorithm, non-session version. + */ + MHD_DIGEST_AUTH_ALGO3_MD5 = + MHD_DIGEST_BASE_ALGO_MD5 | MHD_DIGEST_AUTH_ALGO3_NON_SESSION, + + /** + * The 'MD5-sess' algorithm. + * Not supported by MHD for authentication. + */ + MHD_DIGEST_AUTH_ALGO3_MD5_SESSION = + MHD_DIGEST_BASE_ALGO_MD5 | MHD_DIGEST_AUTH_ALGO3_SESSION, + + /** + * The 'SHA-256' algorithm, non-session version. + */ + MHD_DIGEST_AUTH_ALGO3_SHA256 = + MHD_DIGEST_BASE_ALGO_SHA256 | MHD_DIGEST_AUTH_ALGO3_NON_SESSION, + + /** + * The 'SHA-256-sess' algorithm. + * Not supported by MHD for authentication. + */ + MHD_DIGEST_AUTH_ALGO3_SHA256_SESSION = + MHD_DIGEST_BASE_ALGO_SHA256 | MHD_DIGEST_AUTH_ALGO3_SESSION, + + /** + * The 'SHA-512-256' (SHA-512/256) algorithm. + */ + MHD_DIGEST_AUTH_ALGO3_SHA512_256 = + MHD_DIGEST_BASE_ALGO_SHA512_256 | MHD_DIGEST_AUTH_ALGO3_NON_SESSION, + + /** + * The 'SHA-512-256-sess' (SHA-512/256 session) algorithm. + * Not supported by MHD for authentication. + */ + MHD_DIGEST_AUTH_ALGO3_SHA512_256_SESSION = + MHD_DIGEST_BASE_ALGO_SHA512_256 | MHD_DIGEST_AUTH_ALGO3_SESSION +}; + + +/** + * Get digest size for specified algorithm. + * + * The size of the digest specifies the size of the userhash, userdigest + * and other parameters which size depends on used hash algorithm. + * @param algo3 the algorithm to check + * @return the size of the digest (either #MHD_MD5_DIGEST_SIZE or + * #MHD_SHA256_DIGEST_SIZE/MHD_SHA512_256_DIGEST_SIZE) + * or zero if the input value is not supported or not valid + * @sa #MHD_digest_auth_calc_userdigest() + * @sa #MHD_digest_auth_calc_userhash(), #MHD_digest_auth_calc_userhash_hex() + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup authentication + */ +_MHD_EXTERN size_t +MHD_digest_get_hash_size (enum MHD_DigestAuthAlgo3 algo3); + +/** + * Digest algorithm identification, allow multiple selection. + * + * #MHD_DigestAuthAlgo3 always can be casted to #MHD_DigestAuthMultiAlgo3, but + * not vice versa. + * + * @note Available since #MHD_VERSION 0x00097701 + */ +enum MHD_DigestAuthMultiAlgo3 +{ + /** + * Unknown or wrong algorithm type. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_INVALID = MHD_DIGEST_AUTH_ALGO3_INVALID, + + /** + * The 'MD5' algorithm, non-session version. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_MD5 = MHD_DIGEST_AUTH_ALGO3_MD5, + + /** + * The 'MD5-sess' algorithm. + * Not supported by MHD for authentication. + * Reserved value. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_MD5_SESSION = MHD_DIGEST_AUTH_ALGO3_MD5_SESSION, + + /** + * The 'SHA-256' algorithm, non-session version. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_SHA256 = MHD_DIGEST_AUTH_ALGO3_SHA256, + + /** + * The 'SHA-256-sess' algorithm. + * Not supported by MHD for authentication. + * Reserved value. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_SHA256_SESSION = + MHD_DIGEST_AUTH_ALGO3_SHA256_SESSION, + + /** + * The 'SHA-512-256' (SHA-512/256) algorithm, non-session version. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256 = MHD_DIGEST_AUTH_ALGO3_SHA512_256, + + /** + * The 'SHA-512-256-sess' (SHA-512/256 session) algorithm. + * Not supported by MHD for authentication. + * Reserved value. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256_SESSION = + MHD_DIGEST_AUTH_ALGO3_SHA512_256_SESSION, + + /** + * SHA-256 or SHA-512/256 non-session algorithm, MHD will choose + * the preferred or the matching one. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_SHA_ANY_NON_SESSION = + MHD_DIGEST_AUTH_ALGO3_SHA256 | MHD_DIGEST_AUTH_ALGO3_SHA512_256, + + /** + * Any non-session algorithm, MHD will choose the preferred or + * the matching one. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_ANY_NON_SESSION = + (0x3F) | MHD_DIGEST_AUTH_ALGO3_NON_SESSION, + + /** + * The SHA-256 or SHA-512/256 session algorithm. + * Not supported by MHD. + * Reserved value. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_SHA_ANY_SESSION = + MHD_DIGEST_AUTH_ALGO3_SHA256_SESSION + | MHD_DIGEST_AUTH_ALGO3_SHA512_256_SESSION, + + /** + * Any session algorithm. + * Not supported by MHD. + * Reserved value. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_ANY_SESSION = + (0x3F) | MHD_DIGEST_AUTH_ALGO3_SESSION, + + /** + * The MD5 algorithm, session or non-session. + * Currently supported as non-session only. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_MD5_ANY = + MHD_DIGEST_AUTH_MULT_ALGO3_MD5 | MHD_DIGEST_AUTH_MULT_ALGO3_MD5_SESSION, + + /** + * The SHA-256 algorithm, session or non-session. + * Currently supported as non-session only. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_SHA256_ANY = + MHD_DIGEST_AUTH_MULT_ALGO3_SHA256 + | MHD_DIGEST_AUTH_MULT_ALGO3_SHA256_SESSION, + + /** + * The SHA-512/256 algorithm, session or non-session. + * Currently supported as non-session only. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256_ANY = + MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256 + | MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256_SESSION, + + /** + * The SHA-256 or SHA-512/256 algorithm, session or non-session. + * Currently supported as non-session only. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_SHA_ANY_ANY = + MHD_DIGEST_AUTH_MULT_ALGO3_SHA_ANY_NON_SESSION + | MHD_DIGEST_AUTH_MULT_ALGO3_SHA_ANY_SESSION, + + /** + * Any algorithm, MHD will choose the preferred or the matching one. + */ + MHD_DIGEST_AUTH_MULT_ALGO3_ANY = + (0x3F) | MHD_DIGEST_AUTH_ALGO3_NON_SESSION | MHD_DIGEST_AUTH_ALGO3_SESSION +}; + + +/** + * Calculate "userhash", return it as binary data. + * + * The "userhash" is the hash of the string "username:realm". + * + * The "userhash" could be used to avoid sending username in cleartext in Digest + * Authorization client's header. + * + * Userhash is not designed to hide the username in local database or files, + * as username in cleartext is required for #MHD_digest_auth_check3() function + * to check the response, but it can be used to hide username in HTTP headers. + * + * This function could be used when the new username is added to the username + * database to save the "userhash" alongside with the username (preferably) or + * when loading list of the usernames to generate the userhash for every loaded + * username (this will cause delays at the start with the long lists). + * + * Once "userhash" is generated it could be used to identify users by clients + * with "userhash" support. + * Avoid repetitive usage of this function for the same username/realm + * combination as it will cause excessive CPU load; save and re-use the result + * instead. + * + * @param algo3 the algorithm for userhash calculations + * @param username the username + * @param realm the realm + * @param[out] userhash_bin the output buffer for userhash as binary data; + * if this function succeeds, then this buffer has + * #MHD_digest_get_hash_size(algo3) bytes of userhash + * upon return + * @param bin_buf_size the size of the @a userhash_bin buffer, must be + * at least #MHD_digest_get_hash_size(algo3) bytes long + * @return MHD_YES on success, + * MHD_NO if @a bin_buf_size is too small or if @a algo3 algorithm is + * not supported (or external error has occurred, + * see #MHD_FEATURE_EXTERN_HASH) + * @sa #MHD_digest_auth_calc_userhash_hex() + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup authentication + */ +_MHD_EXTERN enum MHD_Result +MHD_digest_auth_calc_userhash (enum MHD_DigestAuthAlgo3 algo3, + const char *username, + const char *realm, + void *userhash_bin, + size_t bin_buf_size); + + +/** + * Calculate "userhash", return it as hexadecimal string. + * + * The "userhash" is the hash of the string "username:realm". + * + * The "userhash" could be used to avoid sending username in cleartext in Digest + * Authorization client's header. + * + * Userhash is not designed to hide the username in local database or files, + * as username in cleartext is required for #MHD_digest_auth_check3() function + * to check the response, but it can be used to hide username in HTTP headers. + * + * This function could be used when the new username is added to the username + * database to save the "userhash" alongside with the username (preferably) or + * when loading list of the usernames to generate the userhash for every loaded + * username (this will cause delays at the start with the long lists). + * + * Once "userhash" is generated it could be used to identify users by clients + * with "userhash" support. + * Avoid repetitive usage of this function for the same username/realm + * combination as it will cause excessive CPU load; save and re-use the result + * instead. + * + * @param algo3 the algorithm for userhash calculations + * @param username the username + * @param realm the realm + * @param[out] userhash_hex the output buffer for userhash as hex string; + * if this function succeeds, then this buffer has + * #MHD_digest_get_hash_size(algo3)*2 chars long + * userhash zero-terminated string + * @param bin_buf_size the size of the @a userhash_bin buffer, must be + * at least #MHD_digest_get_hash_size(algo3)*2+1 chars long + * @return MHD_YES on success, + * MHD_NO if @a bin_buf_size is too small or if @a algo3 algorithm is + * not supported (or external error has occurred, + * see #MHD_FEATURE_EXTERN_HASH). + * @sa #MHD_digest_auth_calc_userhash() + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup authentication + */ +_MHD_EXTERN enum MHD_Result +MHD_digest_auth_calc_userhash_hex (enum MHD_DigestAuthAlgo3 algo3, + const char *username, + const char *realm, + char *userhash_hex, + size_t hex_buf_size); + + +/** + * The type of username used by client in Digest Authorization header + * + * Values are sorted so simplified checks could be used. + * For example: + * * (value <= MHD_DIGEST_AUTH_UNAME_TYPE_INVALID) is true if no valid username + * is provided by the client + * * (value >= MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH) is true if username is + * provided in any form + * * (value >= MHD_DIGEST_AUTH_UNAME_TYPE_STANDARD) is true if username is + * provided in clear text (no userhash matching is needed) + * + * @note Available since #MHD_VERSION 0x00097701 + */ +enum MHD_DigestAuthUsernameType +{ + /** + * No username parameter in in Digest Authorization header. + * This should be treated as an error. + */ + MHD_DIGEST_AUTH_UNAME_TYPE_MISSING = 0, + + /** + * The 'username' parameter is used to specify the username. + */ + MHD_DIGEST_AUTH_UNAME_TYPE_STANDARD = (1 << 2), + + /** + * The username is specified by 'username*' parameter with + * the extended notation (see RFC 5987 #section-3.2.1). + * The only difference between standard and extended types is + * the way how username value is encoded in the header. + */ + MHD_DIGEST_AUTH_UNAME_TYPE_EXTENDED = (1 << 3), + + /** + * The username provided in form of 'userhash' as + * specified by RFC 7616 #section-3.4.4. + * @sa #MHD_digest_auth_calc_userhash_hex(), #MHD_digest_auth_calc_userhash() + */ + MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH = (1 << 1), + + /** + * The invalid combination of username parameters are used by client. + * Either: + * * both 'username' and 'username*' are used + * * 'username*' is used with 'userhash=true' + * * 'username*' used with invalid extended notation + * * 'username' is not hexadecimal string, while 'userhash' set to 'true' + */ + MHD_DIGEST_AUTH_UNAME_TYPE_INVALID = (1 << 0) +} _MHD_FIXED_ENUM; + +/** + * The QOP ('quality of protection') types. + * @note Available since #MHD_VERSION 0x00097701 + */ +enum MHD_DigestAuthQOP +{ + /** + * Invalid/unknown QOP. + * Used in struct MHD_DigestAuthInfo to indicate client value that + * cannot by identified. + */ + MHD_DIGEST_AUTH_QOP_INVALID = 0, + + /** + * No QOP parameter. + * As described in old RFC 2069 original specification. + * This mode is not allowed by latest RFCs and should be used only to + * communicate with clients that do not support more modern modes (with QOP + * parameter). + * This mode is less secure than other modes and inefficient. + */ + MHD_DIGEST_AUTH_QOP_NONE = 1 << 0, + + /** + * The 'auth' QOP type. + */ + MHD_DIGEST_AUTH_QOP_AUTH = 1 << 1, + + /** + * The 'auth-int' QOP type. + * Not supported by MHD for authentication. + */ + MHD_DIGEST_AUTH_QOP_AUTH_INT = 1 << 2 +} _MHD_FIXED_FLAGS_ENUM; + +/** + * The QOP ('quality of protection') types, multiple selection. + * + * #MHD_DigestAuthQOP always can be casted to #MHD_DigestAuthMultiQOP, but + * not vice versa. + * + * @note Available since #MHD_VERSION 0x00097701 + */ +enum MHD_DigestAuthMultiQOP +{ + /** + * Invalid/unknown QOP. + */ + MHD_DIGEST_AUTH_MULT_QOP_INVALID = MHD_DIGEST_AUTH_QOP_INVALID, + + /** + * No QOP parameter. + * As described in old RFC 2069 original specification. + * This mode is not allowed by latest RFCs and should be used only to + * communicate with clients that do not support more modern modes (with QOP + * parameter). + * This mode is less secure than other modes and inefficient. + */ + MHD_DIGEST_AUTH_MULT_QOP_NONE = MHD_DIGEST_AUTH_QOP_NONE, + + /** + * The 'auth' QOP type. + */ + MHD_DIGEST_AUTH_MULT_QOP_AUTH = MHD_DIGEST_AUTH_QOP_AUTH, + + /** + * The 'auth-int' QOP type. + * Not supported by MHD. + * Reserved value. + */ + MHD_DIGEST_AUTH_MULT_QOP_AUTH_INT = MHD_DIGEST_AUTH_QOP_AUTH_INT, + + /** + * The 'auth' QOP type OR the old RFC2069 (no QOP) type. + * In other words: any types except 'auth-int'. + * RFC2069-compatible mode is allowed, thus this value should be used only + * when it is really necessary. + */ + MHD_DIGEST_AUTH_MULT_QOP_ANY_NON_INT = + MHD_DIGEST_AUTH_QOP_NONE | MHD_DIGEST_AUTH_QOP_AUTH, + + /** + * Any 'auth' QOP type ('auth' or 'auth-int'). + * Currently supported as 'auth' QOP type only. + */ + MHD_DIGEST_AUTH_MULT_QOP_AUTH_ANY = + MHD_DIGEST_AUTH_QOP_AUTH | MHD_DIGEST_AUTH_QOP_AUTH_INT +} _MHD_FIXED_ENUM; + +/** + * The invalid value of 'nc' parameter in client Digest Authorization header. + * @note Available since #MHD_VERSION 0x00097701 + */ +#define MHD_DIGEST_AUTH_INVALID_NC_VALUE (0) + +/** + * Information from Digest Authorization client's header. + * + * All buffers pointed by any struct members are freed when #MHD_free() is + * called for pointer to this structure. + * + * Application may modify buffers as needed until #MHD_free() is called for + * pointer to this structure + * @note Available since #MHD_VERSION 0x00097701 + */ +struct MHD_DigestAuthInfo +{ + /** + * The algorithm as defined by client. + * Set automatically to MD5 if not specified by client. + * @warning Do not be confused with #MHD_DigestAuthAlgorithm, + * which uses other values! + */ + enum MHD_DigestAuthAlgo3 algo3; + + /** + * The type of username used by client. + */ + enum MHD_DigestAuthUsernameType uname_type; + + /** + * The username string. + * Used only if username type is standard or extended, always NULL otherwise. + * If extended notation is used, this string is pct-decoded string + * with charset and language tag removed (i.e. it is original username + * extracted from the extended notation). + * When userhash is used by the client, this member is NULL and + * @a userhash_hex and @a userhash_bin are set. + * The buffer pointed by the @a username becomes invalid when the pointer + * to the structure is freed by #MHD_free(). + */ + char *username; + + /** + * The length of the @a username. + * When the @a username is NULL, this member is always zero. + */ + size_t username_len; + + /** + * The userhash string. + * Valid only if username type is userhash. + * This is unqoted string without decoding of the hexadecimal + * digits (as provided by the client). + * The buffer pointed by the @a userhash_hex becomes invalid when the pointer + * to the structure is freed by #MHD_free(). + * @sa #MHD_digest_auth_calc_userhash_hex() + */ + char *userhash_hex; + + /** + * The length of the @a userhash_hex in characters. + * The valid size should be #MHD_digest_get_hash_size(algo3) * 2 characters. + * When the @a userhash_hex is NULL, this member is always zero. + */ + size_t userhash_hex_len; + + /** + * The userhash decoded to binary form. + * Used only if username type is userhash, always NULL otherwise. + * When not NULL, this points to binary sequence @a userhash_hex_len /2 bytes + * long. + * The valid size should be #MHD_digest_get_hash_size(algo3) bytes. + * The buffer pointed by the @a userhash_bin becomes invalid when the pointer + * to the structure is freed by #MHD_free(). + * @warning This is a binary data, no zero termination. + * @warning To avoid buffer overruns, always check the size of the data before + * use, because @a userhash_bin can point even to zero-sized + * data. + * @sa #MHD_digest_auth_calc_userhash() + */ + uint8_t *userhash_bin; + + /** + * The 'opaque' parameter value, as specified by client. + * NULL if not specified by client. + * The buffer pointed by the @a opaque becomes invalid when the pointer + * to the structure is freed by #MHD_free(). + */ + char *opaque; + + /** + * The length of the @a opaque. + * When the @a opaque is NULL, this member is always zero. + */ + size_t opaque_len; + + /** + * The 'realm' parameter value, as specified by client. + * NULL if not specified by client. + * The buffer pointed by the @a realm becomes invalid when the pointer + * to the structure is freed by #MHD_free(). + */ + char *realm; + + /** + * The length of the @a realm. + * When the @a realm is NULL, this member is always zero. + */ + size_t realm_len; + + /** + * The 'qop' parameter value. + */ + enum MHD_DigestAuthQOP qop; + + /** + * The length of the 'cnonce' parameter value, including possible + * backslash-escape characters. + * 'cnonce' is used in hash calculation, which is CPU-intensive procedure. + * An application may want to reject too large cnonces to limit the CPU load. + * A few kilobytes is a reasonable limit, typically cnonce is just 32-160 + * characters long. + */ + size_t cnonce_len; + + /** + * The nc parameter value. + * Can be used by application to limit the number of nonce re-uses. If @a nc + * is higher than application wants to allow, then "auth required" response + * with 'stale=true' could be used to force client to retry with the fresh + * 'nonce'. + * If not specified by client or does not have hexadecimal digits only, the + * value is #MHD_DIGEST_AUTH_INVALID_NC_VALUE. + */ + uint32_t nc; +}; + + +/** + * Get information about Digest Authorization client's header. + * + * @param connection The MHD connection structure + * @return NULL if no valid Digest Authorization header is used in the request; + * a pointer to the structure with information if the valid request + * header found, free using #MHD_free(). + * @sa #MHD_digest_auth_get_username3() + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup authentication + */ +_MHD_EXTERN struct MHD_DigestAuthInfo * +MHD_digest_auth_get_request_info3 (struct MHD_Connection *connection); + + +/** + * Information from Digest Authorization client's header. + * + * All buffers pointed by any struct members are freed when #MHD_free() is + * called for pointer to this structure. + * + * Application may modify buffers as needed until #MHD_free() is called for + * pointer to this structure + * @note Available since #MHD_VERSION 0x00097701 + */ +struct MHD_DigestAuthUsernameInfo +{ + /** + * The algorithm as defined by client. + * Set automatically to MD5 if not specified by client. + * @warning Do not be confused with #MHD_DigestAuthAlgorithm, + * which uses other values! + */ + enum MHD_DigestAuthAlgo3 algo3; + + /** + * The type of username used by client. + * The 'invalid' and 'missing' types are not used in this structure, + * instead NULL is returned by #MHD_digest_auth_get_username3(). + */ + enum MHD_DigestAuthUsernameType uname_type; + + /** + * The username string. + * Used only if username type is standard or extended, always NULL otherwise. + * If extended notation is used, this string is pct-decoded string + * with charset and language tag removed (i.e. it is original username + * extracted from the extended notation). + * When userhash is used by the client, this member is NULL and + * @a userhash_hex and @a userhash_bin are set. + * The buffer pointed by the @a username becomes invalid when the pointer + * to the structure is freed by #MHD_free(). + */ + char *username; + + /** + * The length of the @a username. + * When the @a username is NULL, this member is always zero. + */ + size_t username_len; + + /** + * The userhash string. + * Valid only if username type is userhash. + * This is unqoted string without decoding of the hexadecimal + * digits (as provided by the client). + * The buffer pointed by the @a userhash_hex becomes invalid when the pointer + * to the structure is freed by #MHD_free(). + * @sa #MHD_digest_auth_calc_userhash_hex() + */ + char *userhash_hex; + + /** + * The length of the @a userhash_hex in characters. + * The valid size should be #MHD_digest_get_hash_size(algo3) * 2 characters. + * When the @a userhash_hex is NULL, this member is always zero. + */ + size_t userhash_hex_len; + + /** + * The userhash decoded to binary form. + * Used only if username type is userhash, always NULL otherwise. + * When not NULL, this points to binary sequence @a userhash_hex_len /2 bytes + * long. + * The valid size should be #MHD_digest_get_hash_size(algo3) bytes. + * The buffer pointed by the @a userhash_bin becomes invalid when the pointer + * to the structure is freed by #MHD_free(). + * @warning This is a binary data, no zero termination. + * @warning To avoid buffer overruns, always check the size of the data before + * use, because @a userhash_bin can point even to zero-sized + * data. + * @sa #MHD_digest_auth_calc_userhash() + */ + uint8_t *userhash_bin; +}; + + +/** + * Get the username from Digest Authorization client's header. + * + * @param connection The MHD connection structure + * @return NULL if no valid Digest Authorization header is used in the request, + * or no username parameter is present in the header, or username is + * provided incorrectly by client (see description for + * #MHD_DIGEST_AUTH_UNAME_TYPE_INVALID); + * a pointer structure with information if the valid request header + * found, free using #MHD_free(). + * @sa #MHD_digest_auth_get_request_info3() provides more complete information + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup authentication + */ +_MHD_EXTERN struct MHD_DigestAuthUsernameInfo * +MHD_digest_auth_get_username3 (struct MHD_Connection *connection); + + +/** + * The result of digest authentication of the client. + * + * All error values are zero or negative. + * + * @note Available since #MHD_VERSION 0x00097701 + */ +enum MHD_DigestAuthResult +{ + /** + * Authentication OK. + */ + MHD_DAUTH_OK = 1, + + /** + * General error, like "out of memory". + */ + MHD_DAUTH_ERROR = 0, + + /** + * No "Authorization" header or wrong format of the header. + * Also may be returned if required parameters in client Authorisation header + * are missing or broken (in invalid format). + */ + MHD_DAUTH_WRONG_HEADER = -1, + + /** + * Wrong 'username'. + */ + MHD_DAUTH_WRONG_USERNAME = -2, + + /** + * Wrong 'realm'. + */ + MHD_DAUTH_WRONG_REALM = -3, + + /** + * Wrong 'URI' (or URI parameters). + */ + MHD_DAUTH_WRONG_URI = -4, + + /** + * Wrong 'qop'. + */ + MHD_DAUTH_WRONG_QOP = -5, + + /** + * Wrong 'algorithm'. + */ + MHD_DAUTH_WRONG_ALGO = -6, + + /** + * Too large (>64 KiB) Authorization parameter value. + */ + MHD_DAUTH_TOO_LARGE = -15, + + /* The different form of naming is intentionally used for the results below, + * as they are more important */ + + /** + * The 'nonce' is too old. Suggest the client to retry with the same + * username and password to get the fresh 'nonce'. + * The validity of the 'nonce' may be not checked. + */ + MHD_DAUTH_NONCE_STALE = -17, + + /** + * The 'nonce' was generated by MHD for other conditions. + * This value is only returned if #MHD_OPTION_DIGEST_AUTH_NONCE_BIND_TYPE + * is set to anything other than #MHD_DAUTH_BIND_NONCE_NONE. + * The interpretation of this code could be different. For example, if + * #MHD_DAUTH_BIND_NONCE_URI is set and client just used the same 'nonce' for + * another URI, the code could be handled as #MHD_DAUTH_NONCE_STALE as + * RFCs allow nonces re-using for other URIs in the same "protection + * space". However, if only #MHD_DAUTH_BIND_NONCE_CLIENT_IP bit is set and + * it is know that clients have fixed IP addresses, this return code could + * be handled like #MHD_DAUTH_NONCE_WRONG. + */ + MHD_DAUTH_NONCE_OTHER_COND = -18, + + /** + * The 'nonce' is wrong. May indicate an attack attempt. + */ + MHD_DAUTH_NONCE_WRONG = -33, + + /** + * The 'response' is wrong. Typically it means that wrong password used. + * May indicate an attack attempt. + */ + MHD_DAUTH_RESPONSE_WRONG = -34 +}; + + +/** + * Authenticates the authorization header sent by the client. + * + * If RFC2069 mode is allowed by setting bit #MHD_DIGEST_AUTH_QOP_NONE in + * @a mqop and the client uses this mode, then server generated nonces are + * used as one-time nonces because nonce-count is not supported in this old RFC. + * Communication in this mode is very inefficient, especially if the client + * requests several resources one-by-one as for every request a new nonce must + * be generated and client repeats all requests twice (first time to get a new + * nonce and second time to perform an authorised request). + * + * @param connection the MHD connection structure + * @param realm the realm for authorization of the client + * @param username the username to be authenticated, must be in clear text + * even if userhash is used by the client + * @param password the password matching the @a username (and the @a realm) + * @param nonce_timeout the period of seconds since nonce generation, when + * the nonce is recognised as valid and not stale; + * if zero is specified then daemon default value is used. + * @param max_nc the maximum allowed nc (Nonce Count) value, if client's nc + * exceeds the specified value then MHD_DAUTH_NONCE_STALE is + * returned; + * if zero is specified then daemon default value is used. + * @param mqop the QOP to use + * @param malgo3 digest algorithms allowed to use, fail if algorithm used + * by the client is not allowed by this parameter + * @return #MHD_DAUTH_OK if authenticated, + * the error code otherwise + * @note Available since #MHD_VERSION 0x00097708 + * @ingroup authentication + */ +_MHD_EXTERN enum MHD_DigestAuthResult +MHD_digest_auth_check3 (struct MHD_Connection *connection, + const char *realm, + const char *username, + const char *password, + unsigned int nonce_timeout, + uint32_t max_nc, + enum MHD_DigestAuthMultiQOP mqop, + enum MHD_DigestAuthMultiAlgo3 malgo3); + + +/** + * Calculate userdigest, return it as a binary data. + * + * The "userdigest" is the hash of the "username:realm:password" string. + * + * The "userdigest" can be used to avoid storing the password in clear text + * in database/files + * + * This function is designed to improve security of stored credentials, + * the "userdigest" does not improve security of the authentication process. + * + * The results can be used to store username & userdigest pairs instead of + * username & password pairs. To further improve security, application may + * store username & userhash & userdigest triplets. + * + * @param algo3 the digest algorithm + * @param username the username + * @param realm the realm + * @param password the password + * @param[out] userdigest_bin the output buffer for userdigest; + * if this function succeeds, then this buffer has + * #MHD_digest_get_hash_size(algo3) bytes of + * userdigest upon return + * @param bin_buf_size the size of the @a userdigest_bin buffer, must be + * at least #MHD_digest_get_hash_size(algo3) bytes long + * @return MHD_YES on success, + * MHD_NO if @a userdigest_bin is too small or if @a algo3 algorithm is + * not supported (or external error has occurred, + * see #MHD_FEATURE_EXTERN_HASH). + * @sa #MHD_digest_auth_check_digest3() + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup authentication + */ +_MHD_EXTERN enum MHD_Result +MHD_digest_auth_calc_userdigest (enum MHD_DigestAuthAlgo3 algo3, + const char *username, + const char *realm, + const char *password, + void *userdigest_bin, + size_t bin_buf_size); + + +/** + * Authenticates the authorization header sent by the client by using + * hash of "username:realm:password". + * + * If RFC2069 mode is allowed by setting bit #MHD_DIGEST_AUTH_QOP_NONE in + * @a mqop and the client uses this mode, then server generated nonces are + * used as one-time nonces because nonce-count is not supported in this old RFC. + * Communication in this mode is very inefficient, especially if the client + * requests several resources one-by-one as for every request a new nonce must + * be generated and client repeats all requests twice (first time to get a new + * nonce and second time to perform an authorised request). + * + * @param connection the MHD connection structure + * @param realm the realm for authorization of the client + * @param username the username to be authenticated, must be in clear text + * even if userhash is used by the client + * @param userdigest the precalculated binary hash of the string + * "username:realm:password", + * see #MHD_digest_auth_calc_userdigest() + * @param userdigest_size the size of the @a userdigest in bytes, must match the + * hashing algorithm (see #MHD_MD5_DIGEST_SIZE, + * #MHD_SHA256_DIGEST_SIZE, #MHD_SHA512_256_DIGEST_SIZE, + * #MHD_digest_get_hash_size()) + * @param nonce_timeout the period of seconds since nonce generation, when + * the nonce is recognised as valid and not stale; + * if zero is specified then daemon default value is used. + * @param max_nc the maximum allowed nc (Nonce Count) value, if client's nc + * exceeds the specified value then MHD_DAUTH_NONCE_STALE is + * returned; + * if zero is specified then daemon default value is used. + * @param mqop the QOP to use + * @param malgo3 digest algorithms allowed to use, fail if algorithm used + * by the client is not allowed by this parameter; + * more than one base algorithms (MD5, SHA-256, SHA-512/256) + * cannot be used at the same time for this function + * as @a userdigest must match specified algorithm + * @return #MHD_DAUTH_OK if authenticated, + * the error code otherwise + * @sa #MHD_digest_auth_calc_userdigest() + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup authentication + */ +_MHD_EXTERN enum MHD_DigestAuthResult +MHD_digest_auth_check_digest3 (struct MHD_Connection *connection, + const char *realm, + const char *username, + const void *userdigest, + size_t userdigest_size, + unsigned int nonce_timeout, + uint32_t max_nc, + enum MHD_DigestAuthMultiQOP mqop, + enum MHD_DigestAuthMultiAlgo3 malgo3); + + +/** + * Queues a response to request authentication from the client + * + * This function modifies provided @a response. The @a response must not be + * reused and should be destroyed (by #MHD_destroy_response()) after call of + * this function. + * + * If @a mqop allows both RFC 2069 (MHD_DIGEST_AUTH_QOP_NONE) and QOP with + * value, then response is formed like if MHD_DIGEST_AUTH_QOP_NONE bit was + * not set, because such response should be backward-compatible with RFC 2069. + * + * If @a mqop allows only MHD_DIGEST_AUTH_MULT_QOP_NONE, then the response is + * formed in strict accordance with RFC 2069 (no 'qop', no 'userhash', no + * 'charset'). For better compatibility with clients, it is recommended (but + * not required) to set @a domain to NULL in this mode. + * + * @param connection the MHD connection structure + * @param realm the realm presented to the client + * @param opaque the string for opaque value, can be NULL, but NULL is + * not recommended for better compatibility with clients; + * the recommended format is hex or Base64 encoded string + * @param domain the optional space-separated list of URIs for which the + * same authorisation could be used, URIs can be in form + * "path-absolute" (the path for the same host with initial slash) + * or in form "absolute-URI" (the full path with protocol), in + * any case client may assume that URI is in the same "protection + * space" if it starts with any of values specified here; + * could be NULL (clients typically assume that the same + * credentials could be used for any URI on the same host); + * this list provides information for the client only and does + * not actually restrict anything on the server side + * @param response the reply to send; should contain the "access denied" + * body; + * note: this function sets the "WWW Authenticate" header and + * the caller should not set this header; + * the NULL is tolerated + * @param signal_stale if set to #MHD_YES then indication of stale nonce used in + * the client's request is signalled by adding 'stale=true' + * to the authentication header, this instructs the client + * to retry immediately with the new nonce and the same + * credentials, without asking user for the new password + * @param mqop the QOP to use + * @param malgo3 digest algorithm to use; if several algorithms are allowed + * then MD5 is preferred (currently, may be changed in next + * versions) + * @param userhash_support if set to non-zero value (#MHD_YES) then support of + * userhash is indicated, allowing client to provide + * hash("username:realm") instead of the username in + * clear text; + * note that clients are allowed to provide the username + * in cleartext even if this parameter set to non-zero; + * when userhash is used, application must be ready to + * identify users by provided userhash value instead of + * username; see #MHD_digest_auth_calc_userhash() and + * #MHD_digest_auth_calc_userhash_hex() + * @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is + * added, indicating for the client that UTF-8 encoding for + * the username is preferred + * @return #MHD_YES on success, #MHD_NO otherwise + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup authentication + */ +_MHD_EXTERN enum MHD_Result +MHD_queue_auth_required_response3 (struct MHD_Connection *connection, + const char *realm, + const char *opaque, + const char *domain, + struct MHD_Response *response, + int signal_stale, + enum MHD_DigestAuthMultiQOP mqop, + enum MHD_DigestAuthMultiAlgo3 algo, + int userhash_support, + int prefer_utf8); + + +/** + * Constant to indicate that the nonce of the provided + * authentication code was wrong. + * Used as return code by #MHD_digest_auth_check(), #MHD_digest_auth_check2(), + * #MHD_digest_auth_check_digest(), #MHD_digest_auth_check_digest2(). + * @ingroup authentication + */ +#define MHD_INVALID_NONCE -1 + + +/** + * Get the username from the authorization header sent by the client + * + * This function supports username in standard and extended notations. + * "userhash" is not supported by this function. + * + * @param connection The MHD connection structure + * @return NULL if no username could be found, username provided as + * "userhash", extended notation broken or memory allocation error + * occurs; + * a pointer to the username if found, free using #MHD_free(). + * @warning Returned value must be freed by #MHD_free(). + * @sa #MHD_digest_auth_get_username3() + * @ingroup authentication + */ +_MHD_EXTERN char * +MHD_digest_auth_get_username (struct MHD_Connection *connection); + + +/** + * Which digest algorithm should MHD use for HTTP digest authentication? + * Used as parameter for #MHD_digest_auth_check2(), + * #MHD_digest_auth_check_digest2(), #MHD_queue_auth_fail_response2(). + */ +enum MHD_DigestAuthAlgorithm +{ + + /** + * MHD should pick (currently defaults to MD5). + */ + MHD_DIGEST_ALG_AUTO = 0, + + /** + * Force use of MD5. + */ + MHD_DIGEST_ALG_MD5, + + /** + * Force use of SHA-256. + */ + MHD_DIGEST_ALG_SHA256 + +} _MHD_FIXED_ENUM; + + +/** + * Authenticates the authorization header sent by the client. + * + * @param connection The MHD connection structure + * @param realm The realm presented to the client + * @param username The username needs to be authenticated + * @param password The password used in the authentication + * @param nonce_timeout The amount of time for a nonce to be + * invalid in seconds + * @param algo digest algorithms allowed for verification + * @return #MHD_YES if authenticated, #MHD_NO if not, + * #MHD_INVALID_NONCE if nonce is invalid or stale + * @note Available since #MHD_VERSION 0x00096200 + * @deprecated use MHD_digest_auth_check3() + * @ingroup authentication + */ +_MHD_EXTERN int +MHD_digest_auth_check2 (struct MHD_Connection *connection, + const char *realm, + const char *username, + const char *password, + unsigned int nonce_timeout, + enum MHD_DigestAuthAlgorithm algo); + + +/** + * Authenticates the authorization header sent by the client. + * Uses #MHD_DIGEST_ALG_MD5 (for now, for backwards-compatibility). + * Note that this MAY change to #MHD_DIGEST_ALG_AUTO in the future. + * If you want to be sure you get MD5, use #MHD_digest_auth_check2() + * and specify MD5 explicitly. + * + * @param connection The MHD connection structure + * @param realm The realm presented to the client + * @param username The username needs to be authenticated + * @param password The password used in the authentication + * @param nonce_timeout The amount of time for a nonce to be + * invalid in seconds + * @return #MHD_YES if authenticated, #MHD_NO if not, + * #MHD_INVALID_NONCE if nonce is invalid or stale + * @deprecated use MHD_digest_auth_check3() + * @ingroup authentication + */ +_MHD_EXTERN int +MHD_digest_auth_check (struct MHD_Connection *connection, + const char *realm, + const char *username, + const char *password, + unsigned int nonce_timeout); + + +/** + * Authenticates the authorization header sent by the client. + * + * @param connection The MHD connection structure + * @param realm The realm presented to the client + * @param username The username needs to be authenticated + * @param digest An `unsigned char *' pointer to the binary MD5 sum + * for the precalculated hash value "username:realm:password" + * of @a digest_size bytes + * @param digest_size number of bytes in @a digest (size must match @a algo!) + * @param nonce_timeout The amount of time for a nonce to be + * invalid in seconds + * @param algo digest algorithms allowed for verification + * @return #MHD_YES if authenticated, #MHD_NO if not, + * #MHD_INVALID_NONCE if nonce is invalid or stale + * @note Available since #MHD_VERSION 0x00096200 + * @deprecated use MHD_digest_auth_check_digest3() + * @ingroup authentication + */ +_MHD_EXTERN int +MHD_digest_auth_check_digest2 (struct MHD_Connection *connection, + const char *realm, + const char *username, + const uint8_t *digest, + size_t digest_size, + unsigned int nonce_timeout, + enum MHD_DigestAuthAlgorithm algo); + + +/** + * Authenticates the authorization header sent by the client + * Uses #MHD_DIGEST_ALG_MD5 (required, as @a digest is of fixed + * size). + * + * @param connection The MHD connection structure + * @param realm The realm presented to the client + * @param username The username needs to be authenticated + * @param digest An `unsigned char *' pointer to the binary hash + * for the precalculated hash value "username:realm:password"; + * length must be #MHD_MD5_DIGEST_SIZE bytes + * @param nonce_timeout The amount of time for a nonce to be + * invalid in seconds + * @return #MHD_YES if authenticated, #MHD_NO if not, + * #MHD_INVALID_NONCE if nonce is invalid or stale + * @note Available since #MHD_VERSION 0x00096000 + * @deprecated use #MHD_digest_auth_check_digest3() + * @ingroup authentication + */ +_MHD_EXTERN int +MHD_digest_auth_check_digest (struct MHD_Connection *connection, + const char *realm, + const char *username, + const uint8_t digest[MHD_MD5_DIGEST_SIZE], + unsigned int nonce_timeout); + + +/** + * Queues a response to request authentication from the client + * + * This function modifies provided @a response. The @a response must not be + * reused and should be destroyed after call of this function. + * + * @param connection The MHD connection structure + * @param realm the realm presented to the client + * @param opaque string to user for opaque value + * @param response reply to send; should contain the "access denied" + * body; note that this function will set the "WWW Authenticate" + * header and that the caller should not do this; the NULL is tolerated + * @param signal_stale #MHD_YES if the nonce is stale to add + * 'stale=true' to the authentication header + * @param algo digest algorithm to use + * @return #MHD_YES on success, #MHD_NO otherwise + * @note Available since #MHD_VERSION 0x00096200 + * @deprecated use MHD_queue_auth_required_response3() + * @ingroup authentication + */ +_MHD_EXTERN enum MHD_Result +MHD_queue_auth_fail_response2 (struct MHD_Connection *connection, + const char *realm, + const char *opaque, + struct MHD_Response *response, + int signal_stale, + enum MHD_DigestAuthAlgorithm algo); + + +/** + * Queues a response to request authentication from the client. + * For now uses MD5 (for backwards-compatibility). Still, if you + * need to be sure, use #MHD_queue_auth_fail_response2(). + * + * This function modifies provided @a response. The @a response must not be + * reused and should be destroyed after call of this function. + * + * @param connection The MHD connection structure + * @param realm the realm presented to the client + * @param opaque string to user for opaque value + * @param response reply to send; should contain the "access denied" + * body; note that this function will set the "WWW Authenticate" + * header and that the caller should not do this; the NULL is tolerated + * @param signal_stale #MHD_YES if the nonce is stale to add + * 'stale=true' to the authentication header + * @return #MHD_YES on success, #MHD_NO otherwise + * @deprecated use MHD_queue_auth_required_response3() + * @ingroup authentication + */ +_MHD_EXTERN enum MHD_Result +MHD_queue_auth_fail_response (struct MHD_Connection *connection, + const char *realm, + const char *opaque, + struct MHD_Response *response, + int signal_stale); + + +/* ********************* Basic Authentication functions *************** */ + + +/** + * Information decoded from Basic Authentication client's header. + * + * The username and the password are technically allowed to have binary zeros, + * username_len and password_len could be used to detect such situations. + * + * The buffers pointed by username and password members are freed + * when #MHD_free() is called for pointer to this structure. + * + * Application may modify buffers as needed until #MHD_free() is called for + * pointer to this structure + */ +struct MHD_BasicAuthInfo +{ + /** + * The username, cannot be NULL. + * The buffer pointed by the @a username becomes invalid when the pointer + * to the structure is freed by #MHD_free(). + */ + char *username; + + /** + * The length of the @a username, not including zero-termination + */ + size_t username_len; + + /** + * The password, may be NULL if password is not encoded by the client. + * The buffer pointed by the @a password becomes invalid when the pointer + * to the structure is freed by #MHD_free(). + */ + char *password; + + /** + * The length of the @a password, not including zero-termination; + * when the @a password is NULL, the length is always zero. + */ + size_t password_len; +}; + +/** + * Get the username and password from the Basic Authorisation header + * sent by the client + * + * @param connection the MHD connection structure + * @return NULL if no valid Basic Authentication header is present in + * current request, or + * pointer to structure with username and password, which must be + * freed by #MHD_free(). + * @note Available since #MHD_VERSION 0x00097701 + * @ingroup authentication + */ +_MHD_EXTERN struct MHD_BasicAuthInfo * +MHD_basic_auth_get_username_password3 (struct MHD_Connection *connection); + +/** + * Queues a response to request basic authentication from the client. + * + * The given response object is expected to include the payload for + * the response; the "WWW-Authenticate" header will be added and the + * response queued with the 'UNAUTHORIZED' status code. + * + * See RFC 7617#section-2 for details. + * + * The @a response is modified by this function. The modified response object + * can be used to respond subsequent requests by #MHD_queue_response() + * function with status code #MHD_HTTP_UNAUTHORIZED and must not be used again + * with MHD_queue_basic_auth_required_response3() function. The response could + * be destroyed right after call of this function. + * + * @param connection the MHD connection structure + * @param realm the realm presented to the client + * @param prefer_utf8 if not set to #MHD_NO, parameter'charset="UTF-8"' will + * be added, indicating for client that UTF-8 encoding + * is preferred + * @param response the response object to modify and queue; the NULL + * is tolerated + * @return #MHD_YES on success, #MHD_NO otherwise + * @note Available since #MHD_VERSION 0x00097704 + * @ingroup authentication + */ +_MHD_EXTERN enum MHD_Result +MHD_queue_basic_auth_required_response3 (struct MHD_Connection *connection, + const char *realm, + int prefer_utf8, + struct MHD_Response *response); + +/** + * Get the username and password from the basic authorization header sent by the client + * + * @param connection The MHD connection structure + * @param[out] password a pointer for the password, free using #MHD_free(). + * @return NULL if no username could be found, a pointer + * to the username if found, free using #MHD_free(). + * @deprecated use #MHD_basic_auth_get_username_password3() + * @ingroup authentication + */ +_MHD_EXTERN char * +MHD_basic_auth_get_username_password (struct MHD_Connection *connection, + char **password); + + +/** + * Queues a response to request basic authentication from the client + * The given response object is expected to include the payload for + * the response; the "WWW-Authenticate" header will be added and the + * response queued with the 'UNAUTHORIZED' status code. + * + * @param connection The MHD connection structure + * @param realm the realm presented to the client + * @param response response object to modify and queue; the NULL is tolerated + * @return #MHD_YES on success, #MHD_NO otherwise + * @deprecated use MHD_queue_basic_auth_required_response3() + * @ingroup authentication + */ +_MHD_EXTERN enum MHD_Result +MHD_queue_basic_auth_fail_response (struct MHD_Connection *connection, + const char *realm, + struct MHD_Response *response); + +/* ********************** generic query functions ********************** */ + + +/** + * Obtain information about the given connection. + * The returned pointer is invalidated with the next call of this function or + * when the connection is closed. + * + * @param connection what connection to get information about + * @param info_type what information is desired? + * @param ... depends on @a info_type + * @return NULL if this information is not available + * (or if the @a info_type is unknown) + * @ingroup specialized + */ +_MHD_EXTERN const union MHD_ConnectionInfo * +MHD_get_connection_info (struct MHD_Connection *connection, + enum MHD_ConnectionInfoType info_type, + ...); + + +/** + * MHD connection options. Given to #MHD_set_connection_option to + * set custom options for a particular connection. + */ +enum MHD_CONNECTION_OPTION +{ + + /** + * Set a custom timeout for the given connection. Specified + * as the number of seconds, given as an `unsigned int`. Use + * zero for no timeout. + * If timeout was set to zero (or unset) before, setup of new value by + * MHD_set_connection_option() will reset timeout timer. + * Values larger than (UINT64_MAX / 2000 - 1) will + * be clipped to this number. + */ + MHD_CONNECTION_OPTION_TIMEOUT + +} _MHD_FIXED_ENUM; + + +/** + * Set a custom option for the given connection, overriding defaults. + * + * @param connection connection to modify + * @param option option to set + * @param ... arguments to the option, depending on the option type + * @return #MHD_YES on success, #MHD_NO if setting the option failed + * @ingroup specialized + */ +_MHD_EXTERN enum MHD_Result +MHD_set_connection_option (struct MHD_Connection *connection, + enum MHD_CONNECTION_OPTION option, + ...); + + +/** + * Information about an MHD daemon. + */ +union MHD_DaemonInfo +{ + /** + * Size of the key, no longer supported. + * @deprecated + */ + size_t key_size; + + /** + * Size of the mac key, no longer supported. + * @deprecated + */ + size_t mac_key_size; + + /** + * Socket, returned for #MHD_DAEMON_INFO_LISTEN_FD. + */ + MHD_socket listen_fd; + + /** + * Bind port number, returned for #MHD_DAEMON_INFO_BIND_PORT. + */ + uint16_t port; + + /** + * epoll FD, returned for #MHD_DAEMON_INFO_EPOLL_FD. + */ + int epoll_fd; + + /** + * Number of active connections, for #MHD_DAEMON_INFO_CURRENT_CONNECTIONS. + */ + unsigned int num_connections; + + /** + * Combination of #MHD_FLAG values, for #MHD_DAEMON_INFO_FLAGS. + * This value is actually a bitfield. + * Note: flags may differ from original 'flags' specified for + * daemon, especially if #MHD_USE_AUTO was set. + */ + enum MHD_FLAG flags; +}; + + +/** + * Obtain information about the given daemon. + * The returned pointer is invalidated with the next call of this function or + * when the daemon is stopped. + * + * @param daemon what daemon to get information about + * @param info_type what information is desired? + * @param ... depends on @a info_type + * @return NULL if this information is not available + * (or if the @a info_type is unknown) + * @ingroup specialized + */ +_MHD_EXTERN const union MHD_DaemonInfo * +MHD_get_daemon_info (struct MHD_Daemon *daemon, + enum MHD_DaemonInfoType info_type, + ...); + + +/** + * Obtain the version of this library + * + * @return static version string, e.g. "0.9.9" + * @ingroup specialized + */ +_MHD_EXTERN const char * +MHD_get_version (void); + + +/** + * Obtain the version of this library as a binary value. + * + * @return version binary value, e.g. "0x00090900" (#MHD_VERSION of + * compiled MHD binary) + * @note Available since #MHD_VERSION 0x00097601 + * @ingroup specialized + */ +_MHD_EXTERN uint32_t +MHD_get_version_bin (void); + + +/** + * Types of information about MHD features, + * used by #MHD_is_feature_supported(). + */ +enum MHD_FEATURE +{ + /** + * Get whether messages are supported. If supported then in debug + * mode messages can be printed to stderr or to external logger. + */ + MHD_FEATURE_MESSAGES = 1, + + /** + * Get whether HTTPS is supported. If supported then flag + * #MHD_USE_TLS and options #MHD_OPTION_HTTPS_MEM_KEY, + * #MHD_OPTION_HTTPS_MEM_CERT, #MHD_OPTION_HTTPS_MEM_TRUST, + * #MHD_OPTION_HTTPS_MEM_DHPARAMS, #MHD_OPTION_HTTPS_CRED_TYPE, + * #MHD_OPTION_HTTPS_PRIORITIES can be used. + */ + MHD_FEATURE_TLS = 2, + MHD_FEATURE_SSL = 2, + + /** + * Get whether option #MHD_OPTION_HTTPS_CERT_CALLBACK is + * supported. + */ + MHD_FEATURE_HTTPS_CERT_CALLBACK = 3, + + /** + * Get whether IPv6 is supported. If supported then flag + * #MHD_USE_IPv6 can be used. + */ + MHD_FEATURE_IPv6 = 4, + + /** + * Get whether IPv6 without IPv4 is supported. If not supported + * then IPv4 is always enabled in IPv6 sockets and + * flag #MHD_USE_DUAL_STACK is always used when #MHD_USE_IPv6 is + * specified. + */ + MHD_FEATURE_IPv6_ONLY = 5, + + /** + * Get whether `poll()` is supported. If supported then flag + * #MHD_USE_POLL can be used. + */ + MHD_FEATURE_POLL = 6, + + /** + * Get whether `epoll()` is supported. If supported then Flags + * #MHD_USE_EPOLL and + * #MHD_USE_EPOLL_INTERNAL_THREAD can be used. + */ + MHD_FEATURE_EPOLL = 7, + + /** + * Get whether shutdown on listen socket to signal other + * threads is supported. If not supported flag + * #MHD_USE_ITC is automatically forced. + */ + MHD_FEATURE_SHUTDOWN_LISTEN_SOCKET = 8, + + /** + * Get whether socketpair is used internally instead of pipe to + * signal other threads. + */ + MHD_FEATURE_SOCKETPAIR = 9, + + /** + * Get whether TCP Fast Open is supported. If supported then + * flag #MHD_USE_TCP_FASTOPEN and option + * #MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE can be used. + */ + MHD_FEATURE_TCP_FASTOPEN = 10, + + /** + * Get whether HTTP Basic authorization is supported. If supported + * then functions #MHD_basic_auth_get_username_password and + * #MHD_queue_basic_auth_fail_response can be used. + */ + MHD_FEATURE_BASIC_AUTH = 11, + + /** + * Get whether HTTP Digest authorization is supported. If + * supported then options #MHD_OPTION_DIGEST_AUTH_RANDOM, + * #MHD_OPTION_NONCE_NC_SIZE and + * #MHD_digest_auth_check() can be used. + */ + MHD_FEATURE_DIGEST_AUTH = 12, + + /** + * Get whether postprocessor is supported. If supported then + * functions #MHD_create_post_processor(), #MHD_post_process() and + * #MHD_destroy_post_processor() can + * be used. + */ + MHD_FEATURE_POSTPROCESSOR = 13, + + /** + * Get whether password encrypted private key for HTTPS daemon is + * supported. If supported then option + * ::MHD_OPTION_HTTPS_KEY_PASSWORD can be used. + */ + MHD_FEATURE_HTTPS_KEY_PASSWORD = 14, + + /** + * Get whether reading files beyond 2 GiB boundary is supported. + * If supported then #MHD_create_response_from_fd(), + * #MHD_create_response_from_fd64 #MHD_create_response_from_fd_at_offset() + * and #MHD_create_response_from_fd_at_offset64() can be used with sizes and + * offsets larger than 2 GiB. If not supported value of size+offset is + * limited to 2 GiB. + */ + MHD_FEATURE_LARGE_FILE = 15, + + /** + * Get whether MHD set names on generated threads. + */ + MHD_FEATURE_THREAD_NAMES = 16, + MHD_THREAD_NAMES = 16, + + /** + * Get whether HTTP "Upgrade" is supported. + * If supported then #MHD_ALLOW_UPGRADE, #MHD_upgrade_action() and + * #MHD_create_response_for_upgrade() can be used. + */ + MHD_FEATURE_UPGRADE = 17, + + /** + * Get whether it's safe to use same FD for multiple calls of + * #MHD_create_response_from_fd() and whether it's safe to use single + * response generated by #MHD_create_response_from_fd() with multiple + * connections at same time. + * If #MHD_is_feature_supported() return #MHD_NO for this feature then + * usage of responses with same file FD in multiple parallel threads may + * results in incorrect data sent to remote client. + * It's always safe to use same file FD in multiple responses if MHD + * is run in any single thread mode. + */ + MHD_FEATURE_RESPONSES_SHARED_FD = 18, + + /** + * Get whether MHD support automatic detection of bind port number. + * @sa #MHD_DAEMON_INFO_BIND_PORT + */ + MHD_FEATURE_AUTODETECT_BIND_PORT = 19, + + /** + * Get whether MHD supports automatic SIGPIPE suppression. + * If SIGPIPE suppression is not supported, application must handle + * SIGPIPE signal by itself. + */ + MHD_FEATURE_AUTOSUPPRESS_SIGPIPE = 20, + + /** + * Get whether MHD use system's sendfile() function to send + * file-FD based responses over non-TLS connections. + * @note Since v0.9.56 + */ + MHD_FEATURE_SENDFILE = 21, + + /** + * Get whether MHD supports threads. + */ + MHD_FEATURE_THREADS = 22, + + /** + * Get whether option #MHD_OPTION_HTTPS_CERT_CALLBACK2 is + * supported. + */ + MHD_FEATURE_HTTPS_CERT_CALLBACK2 = 23, + + /** + * Get whether automatic parsing of HTTP Cookie header is supported. + * If disabled, no MHD_COOKIE_KIND will be generated by MHD. + * MHD versions before 0x00097701 always support cookie parsing. + * @note Available since #MHD_VERSION 0x01000200 + */ + MHD_FEATURE_COOKIE_PARSING = 24, + + /** + * Get whether the early version the Digest Authorization (RFC 2069) is + * supported (digest authorisation without QOP parameter). + * Since #MHD_VERSION 0x00097701 it is always supported if Digest Auth + * module is built. + * @note Available since #MHD_VERSION 0x00097701 + */ + MHD_FEATURE_DIGEST_AUTH_RFC2069 = 25, + + /** + * Get whether the MD5-based hashing algorithms are supported for Digest + * Authorization. + * Currently it is always supported if Digest Auth module is built + * unless manually disabled in a custom build. + * @note Available since #MHD_VERSION 0x00097701 + */ + MHD_FEATURE_DIGEST_AUTH_MD5 = 26, + + /** + * Get whether the SHA-256-based hashing algorithms are supported for Digest + * Authorization. + * It is always supported since #MHD_VERSION 0x00096200 if Digest Auth + * module is built unless manually disabled in a custom build. + * @note Available since #MHD_VERSION 0x00097701 + */ + MHD_FEATURE_DIGEST_AUTH_SHA256 = 27, + + /** + * Get whether the SHA-512/256-based hashing algorithms are supported + * for Digest Authorization. + * It it always supported since #MHD_VERSION 0x00097701 if Digest Auth + * module is built unless manually disabled in a custom build. + * @note Available since #MHD_VERSION 0x00097701 + */ + MHD_FEATURE_DIGEST_AUTH_SHA512_256 = 28, + + /** + * Get whether QOP with value 'auth-int' (authentication with integrity + * protection) is supported for Digest Authorization. + * Currently it is always not supported. + * @note Available since #MHD_VERSION 0x00097701 + */ + MHD_FEATURE_DIGEST_AUTH_AUTH_INT = 29, + + /** + * Get whether 'session' algorithms (like 'MD5-sess') are supported for Digest + * Authorization. + * Currently it is always not supported. + * @note Available since #MHD_VERSION 0x00097701 + */ + MHD_FEATURE_DIGEST_AUTH_ALGO_SESSION = 30, + + /** + * Get whether 'userhash' is supported for Digest Authorization. + * It is always supported since #MHD_VERSION 0x00097701 if Digest Auth + * module is built. + * @note Available since #MHD_VERSION 0x00097701 + */ + MHD_FEATURE_DIGEST_AUTH_USERHASH = 31, + + /** + * Get whether any of hashing algorithms is implemented by external + * function (like TLS library) and may fail due to external conditions, + * like "out-of-memory". + * + * If result is #MHD_YES then functions which use hash calculations + * like #MHD_digest_auth_calc_userhash(), #MHD_digest_auth_check3() and others + * potentially may fail even with valid input because of out-of-memory error + * or crypto accelerator device failure, however in practice such fails are + * unlikely. + * @note Available since #MHD_VERSION 0x00097701 + */ + MHD_FEATURE_EXTERN_HASH = 32, + + /** + * Get whether MHD was built with asserts enabled. + * For debug builds the error log is always enabled even if #MHD_USE_ERROR_LOG + * is not specified for daemon. + * @note Available since #MHD_VERSION 0x00097701 + */ + MHD_FEATURE_DEBUG_BUILD = 33, + + /** + * Get whether MHD was build with support for overridable FD_SETSIZE. + * This feature should be always available when the relevant platform ability + * is detected. + * @sa #MHD_OPTION_APP_FD_SETSIZE + * @note Available since #MHD_VERSION 0x00097705 + */ + MHD_FEATURE_FLEXIBLE_FD_SETSIZE = 34 +}; + +#define MHD_FEATURE_HTTPS_COOKIE_PARSING _MHD_DEPR_IN_MACRO ( \ + "Value MHD_FEATURE_HTTPS_COOKIE_PARSING is deprecated, use MHD_FEATURE_COOKIE_PARSING" \ + ) MHD_FEATURE_COOKIE_PARSING + +/** + * Get information about supported MHD features. + * Indicate that MHD was compiled with or without support for + * particular feature. Some features require additional support + * by kernel. Kernel support is not checked by this function. + * + * @param feature type of requested information + * @return #MHD_YES if feature is supported by MHD, #MHD_NO if + * feature is not supported or feature is unknown. + * @ingroup specialized + */ +_MHD_EXTERN enum MHD_Result +MHD_is_feature_supported (enum MHD_FEATURE feature); + + +MHD_C_DECLRATIONS_FINISH_HERE_ + +#endif diff --git a/vendor/libmicrohttpd/lib/libmicrohttpd.a b/vendor/libmicrohttpd/lib/libmicrohttpd.a new file mode 100644 index 0000000000000000000000000000000000000000..298fac14fffa2ac198a5ce084212b87b944cc3c7 GIT binary patch literal 1101442 zcmeFa3w%`7wLg9)2`~wS6BGdz>xi)?DwwFXL=iKP$Qhkz6i|E-LNYOtBok-OKzuSV zGlbLWRJ1DIwklq0#p`XgwM9UMfSRE7s$lE0wbWa$ImWk@mrDNMwe~(|&Lji+^S1pz zKL02)`?>boYp>T{d!IAMOsfwyG*2%$*^~KK=E#b)^V8!wt-Snn(PTk^qA05r<&f+C zq5tyUxLcur!w$XmU-~aUu|jeFE12}D@{Rue>;a?|7x_Vx`tqTd!RvY3AWeOx3&fw>e>Qr z!O*pJ3RPYe(47tDUgWFmsMnk8+OyRzu5XP5!UwLAy~3F=xz|Ce7+z~IxG2)$M8((4xAA)?hf$C}!uV<6==7>1eFi19h$SVZE*%gjw98OKLdUH`li}wg&1# zf%?Y5!^o;7p%y(bxQ^!D(%z!C)VJ1!bsA=Hi$F)PwY5&-Ft}2JZo$x8Mc|rs9fZNs zEv#=?6wbPAE$vM~yS-x)!46t>uDK=>h|qMx9l`dn08VR<`Gvt49nGQoaGKn19j+yaN*LQ$0j^(azbhfc^(p%aB!H9nPX@g4!=TAQ^&D^q6T?;n~MKJwPu&pi} zXoW0^`3@?y8!oAD(X9-BUlVBwgc|~NjrEW`u^eGN*pZp959zX?ZgD+#1OM1%TtLer zV1UQuic{I*Kqzdjvm;-(utf~k60U0s)a#K@01ML55e(@8!PLa547mv@rEb>wb7wO5 z)-?xOI|89P(h%H6R5b=D52QLnMqv~*$?s~8;0_AY}X=z;2MQIc|F#tC_^%T3Ivn)$X2S~dm%4AC#6tDml z)9+-;QBnEnvdAt$7tzQrnJNol7lqIewa}(HAmF64b=PqxR8YMod_?b#1_*ATA=n53 z)I%-ErDx!*gqCfAL>!H#T%6@X z-PE}tXjBFj25{jigDE+R3G-zlJG%QL_ z(uU9s_ah)|at7q4AQn@UV>QwvI@*&~90VtA-3C=KW*HrzN=P?boG9=c)C+6DNI zE7L*}nH6fFtwR?Rls+5#*V5&∓%LXo$cww%TL`1y|H+!1dDV+l#}6E$tvA^QjFy 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 z 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 z

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 G@c=ijc7^j1C6IjV~k7oV8n#M)H8t5Qvgh% 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

p7)H5z=;7eoLMcg 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 XY57%kJf236cK!y)KSiCOcD?@rJhqu^ literal 0 HcmV?d00001 diff --git a/vendor/libmicrohttpd/share/info/dir b/vendor/libmicrohttpd/share/info/dir new file mode 100644 index 0000000..bcc1897 --- /dev/null +++ b/vendor/libmicrohttpd/share/info/dir @@ -0,0 +1,21 @@ +This is the file .../info/dir, which contains the +topmost node of the Info hierarchy, called (dir)Top. +The first time you invoke Info you start off looking at this node. + +File: dir, Node: Top This is the top of the INFO tree + + This (the Directory node) gives a menu of major topics. + Typing "q" exits, "H" lists all Info commands, "d" returns here, + "h" gives a primer for first-timers, + "mEmacs" visits the Emacs manual, etc. + + In Emacs, you can click mouse button 2 on a menu item or cross reference + to select it. + +* Menu: + +Software libraries +* libmicrohttpd: (libmicrohttpd). + Embedded HTTP server library. +* libmicrohttpdtutorial: (libmicrohttpd-tutorial). + A tutorial for GNU libmicrohttpd. diff --git a/vendor/libmicrohttpd/share/info/libmicrohttpd-tutorial.info b/vendor/libmicrohttpd/share/info/libmicrohttpd-tutorial.info new file mode 100644 index 0000000..775de2f --- /dev/null +++ b/vendor/libmicrohttpd/share/info/libmicrohttpd-tutorial.info @@ -0,0 +1,5752 @@ +This is libmicrohttpd-tutorial.info, produced by makeinfo version 6.8 +from libmicrohttpd-tutorial.texi. + +This tutorial documents GNU libmicrohttpd version 0.9.48, last updated 2 +April 2016. + + Copyright (c) 2008 Sebastian Gerhardt. + + Copyright (c) 2010, 2011, 2012, 2013, 2016, 2021 Christian Grothoff. + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation License, + Version 1.3 or any later version published by the Free Software + Foundation; with no Invariant Sections, no Front-Cover Texts, and + no Back-Cover Texts. A copy of the license is included in the + section entitled "GNU Free Documentation License". +INFO-DIR-SECTION Software libraries +START-INFO-DIR-ENTRY +* libmicrohttpdtutorial: (libmicrohttpd-tutorial). A tutorial for GNU libmicrohttpd. +END-INFO-DIR-ENTRY + + +File: libmicrohttpd-tutorial.info, Node: Top, Next: Introduction, Up: (dir) + +A Tutorial for GNU libmicrohttpd +******************************** + +This tutorial documents GNU libmicrohttpd version 0.9.48, last updated 2 +April 2016. + + Copyright (c) 2008 Sebastian Gerhardt. + + Copyright (c) 2010, 2011, 2012, 2013, 2016, 2021 Christian Grothoff. + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation License, + Version 1.3 or any later version published by the Free Software + Foundation; with no Invariant Sections, no Front-Cover Texts, and + no Back-Cover Texts. A copy of the license is included in the + section entitled "GNU Free Documentation License". + +* Menu: + +* Introduction:: +* Hello browser example:: +* Exploring requests:: +* Response headers:: +* Supporting basic authentication:: +* Processing POST data:: +* Improved processing of POST data:: +* Session management:: +* Adding a layer of security:: +* Websockets:: +* Bibliography:: +* License text:: +* Example programs:: + + +File: libmicrohttpd-tutorial.info, Node: Introduction, Next: Hello browser example, Prev: Top, Up: Top + +1 Introduction +************** + +This tutorial is for developers who want to learn how they can add HTTP +serving capabilities to their applications with the _GNU libmicrohttpd_ +library, abbreviated _MHD_. The reader will learn how to implement basic +HTTP functions from simple executable sample programs that implement +various features. + + The text is supposed to be a supplement to the API reference manual +of _GNU libmicrohttpd_ and for that reason does not explain many of the +parameters. Therefore, the reader should always consult the manual to +find the exact meaning of the functions used in the tutorial. +Furthermore, the reader is encouraged to study the relevant _RFCs_, +which document the HTTP standard. + + _GNU libmicrohttpd_ is assumed to be already installed. This +tutorial is written for version 0.9.48. At the time being, this +tutorial has only been tested on _GNU/Linux_ machines even though +efforts were made not to rely on anything that would prevent the samples +from being built on similar systems. + +1.1 History +=========== + +This tutorial was originally written by Sebastian Gerhardt for MHD +0.4.0. It was slightly polished and updated to MHD 0.9.0 by Christian +Grothoff. + + +File: libmicrohttpd-tutorial.info, Node: Hello browser example, Next: Exploring requests, Prev: Introduction, Up: Top + +2 Hello browser example +*********************** + +The most basic task for a HTTP server is to deliver a static text +message to any client connecting to it. Given that this is also easy to +implement, it is an excellent problem to start with. + + For now, the particular URI the client asks for shall have no effect +on the message that will be returned. In addition, the server shall end +the connection after the message has been sent so that the client will +know there is nothing more to expect. + + The C program 'hellobrowser.c', which is to be found in the examples +section, does just that. If you are very eager, you can compile and +start it right away but it is advisable to type the lines in by yourself +as they will be discussed and explained in detail. + + After the necessary includes and the definition of the port which our +server should listen on +#include +#include +#include +#include + +#define PORT 8888 + + +the desired behaviour of our server when HTTP request arrive has to be +implemented. We already have agreed that it should not care about the +particular details of the request, such as who is requesting what. The +server will respond merely with the same small HTML page to every +request. + + The function we are going to write now will be called by _GNU +libmicrohttpd_ every time an appropriate request comes in. While the +name of this callback function is arbitrary, its parameter list has to +follow a certain layout. So please, ignore the lot of parameters for +now, they will be explained at the point they are needed. We have to +use only one of them, 'struct MHD_Connection *connection', for the +minimalistic functionality we want to achieve at the moment. + + This parameter is set by the _libmicrohttpd_ daemon and holds the +necessary information to relate the call with a certain connection. +Keep in mind that a server might have to satisfy hundreds of concurrent +connections and we have to make sure that the correct data is sent to +the destined client. Therefore, this variable is a means to refer to a +particular connection if we ask the daemon to sent the reply. + + Talking about the reply, it is defined as a string right after the +function header +int answer_to_connection (void *cls, struct MHD_Connection *connection, + const char *url, + const char *method, const char *version, + const char *upload_data, + size_t *upload_data_size, void **req_cls) +{ + const char *page = "Hello, browser!"; + + +HTTP is a rather strict protocol and the client would certainly consider +it "inappropriate" if we just sent the answer string "as is". Instead, +it has to be wrapped with additional information stored in so-called +headers and footers. Most of the work in this area is done by the +library for us--we just have to ask. Our reply string packed in the +necessary layers will be called a "response". To obtain such a response +we hand our data (the reply-string) and its size over to the +'MHD_create_response_from_buffer' function. The last two parameters +basically tell _MHD_ that we do not want it to dispose the message data +for us when it has been sent and there also needs no internal copy to be +done because the _constant_ string won't change anyway. + + struct MHD_Response *response; + int ret; + + response = MHD_create_response_from_buffer (strlen (page), + (void*) page, MHD_RESPMEM_PERSISTENT); + + +Now that the the response has been laced up, it is ready for delivery +and can be queued for sending. This is done by passing it to another +_GNU libmicrohttpd_ function. As all our work was done in the scope of +one function, the recipient is without doubt the one associated with the +local variable 'connection' and consequently this variable is given to +the queue function. Every HTTP response is accompanied by a status +code, here "OK", so that the client knows this response is the intended +result of his request and not due to some error or malfunction. + + Finally, the packet is destroyed and the return value from the queue +returned, already being set at this point to either MHD_YES or MHD_NO in +case of success or failure. + + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + MHD_destroy_response (response); + + return ret; +} + + +With the primary task of our server implemented, we can start the actual +server daemon which will listen on 'PORT' for connections. This is done +in the main function. +int main () +{ + struct MHD_Daemon *daemon; + + daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD, PORT, NULL, NULL, + &answer_to_connection, NULL, MHD_OPTION_END); + if (NULL == daemon) return 1; + + +The first parameter is one of three possible modes of operation. Here +we want the daemon to run in a separate thread and to manage all +incoming connections in the same thread. This means that while +producing the response for one connection, the other connections will be +put on hold. In this example, where the reply is already known and +therefore the request is served quickly, this poses no problem. + + We will allow all clients to connect regardless of their name or +location, therefore we do not check them on connection and set the third +and fourth parameter to NULL. + + Parameter five is the address of the function we want to be called +whenever a new connection has been established. Our +'answer_to_connection' knows best what the client wants and needs no +additional information (which could be passed via the next parameter) so +the next (sixth) parameter is NULL. Likewise, we do not need to pass +extra options to the daemon so we just write the MHD_OPTION_END as the +last parameter. + + As the server daemon runs in the background in its own thread, the +execution flow in our main function will continue right after the call. +Because of this, we must delay the execution flow in the main thread or +else the program will terminate prematurely. We let it pause in a +processing-time friendly manner by waiting for the enter key to be +pressed. In the end, we stop the daemon so it can do its cleanup tasks. + getchar (); + + MHD_stop_daemon (daemon); + return 0; +} + + +The first example is now complete. + + Compile it with +cc hellobrowser.c -o hellobrowser -I$PATH_TO_LIBMHD_INCLUDES + -L$PATH_TO_LIBMHD_LIBS -lmicrohttpd + with the two paths set accordingly and run it. + + Now open your favorite Internet browser and go to the address +'http://localhost:8888/', provided that 8888 is the port you chose. If +everything works as expected, the browser will present the message of +the static HTML page it got from our minimal server. + +Remarks +======= + +To keep this first example as small as possible, some drastic shortcuts +were taken and are to be discussed now. + + Firstly, there is no distinction made between the kinds of requests a +client could send. We implied that the client sends a GET request, that +means, that he actually asked for some data. Even when it is not +intended to accept POST requests, a good server should at least +recognize that this request does not constitute a legal request and +answer with an error code. This can be easily implemented by checking +if the parameter 'method' equals the string "GET" and returning a +'MHD_NO' if not so. + + Secondly, the above practice of queuing a response upon the first +call of the callback function brings with it some limitations. This is +because the content of the message body will not be received if a +response is queued in the first iteration. Furthermore, the connection +will be closed right after the response has been transferred then. This +is typically not what you want as it disables HTTP pipelining. The +correct approach is to simply not queue a message on the first callback +unless there is an error. The 'void**' argument to the callback +provides a location for storing information about the history of the +connection; for the first call, the pointer will point to NULL. A +simplistic way to differentiate the first call from others is to check +if the pointer is NULL and set it to a non-NULL value during the first +call. + + Both of these issues you will find addressed in the official +'minimal_example.c' residing in the 'src/examples' directory of the +_MHD_ package. The source code of this program should look very +familiar to you by now and easy to understand. + + For our example, we create the response from a static (persistent) +buffer in memory and thus pass 'MHD_RESPMEM_PERSISTENT' to the response +construction function. In the usual case, responses are not transmitted +immediately after being queued. For example, there might be other data +on the system that needs to be sent with a higher priority. +Nevertheless, the queue function will return successfully--raising the +problem that the data we have pointed to may be invalid by the time it +is about being sent. This is not an issue here because we can expect +the 'page' string, which is a constant _string literal_ here, to be +static. That means it will be present and unchanged for as long as the +program runs. For dynamic data, one could choose to either have _MHD_ +free the memory 'page' points to itself when it is not longer needed (by +passing 'MHD_RESPMEM_MUST_FREE') or, alternatively, have the library to +make and manage its own copy of it (by passing 'MHD_RESPMEM_MUST_COPY'). +Naturally, this last option is the most expensive. + +Exercises +========= + + * While the server is running, use a program like 'telnet' or + 'netcat' to connect to it. Try to form a valid HTTP 1.1 request + yourself like + GET /dontcare HTTP/1.1 + Host: itsme + + and see what the server returns to you. + + * Also, try other requests, like POST, and see how our server does + not mind and why. How far in malforming a request can you go + before the builtin functionality of _MHD_ intervenes and an altered + response is sent? Make sure you read about the status codes in the + _RFC_. + + * Add the option 'MHD_USE_PEDANTIC_CHECKS' to the start function of + the daemon in 'main'. Mind the special format of the parameter + list here which is described in the manual. How indulgent is the + server now to your input? + + * Let the main function take a string as the first command line + argument and pass 'argv[1]' to the 'MHD_start_daemon' function as + the sixth parameter. The address of this string will be passed to + the callback function via the 'cls' variable. Decorate the text + given at the command line when the server is started with proper + HTML tags and send it as the response instead of the former static + string. + + * _Demanding:_ Write a separate function returning a string + containing some useful information, for example, the time. Pass + the function's address as the sixth parameter and evaluate this + function on every request anew in 'answer_to_connection'. Remember + to free the memory of the string every time after satisfying the + request. + + +File: libmicrohttpd-tutorial.info, Node: Exploring requests, Next: Response headers, Prev: Hello browser example, Up: Top + +3 Exploring requests +******************** + +This chapter will deal with the information which the client sends to +the server at every request. We are going to examine the most useful +fields of such an request and print them out in a readable manner. This +could be useful for logging facilities. + + The starting point is the _hellobrowser_ program with the former +response removed. + + This time, we just want to collect information in the callback +function, thus we will just return MHD_NO after we have probed the +request. This way, the connection is closed without much ado by the +server. + +static int +answer_to_connection (void *cls, struct MHD_Connection *connection, + const char *url, + const char *method, const char *version, + const char *upload_data, + size_t *upload_data_size, void **req_cls) +{ + ... + return MHD_NO; +} +The ellipsis marks the position where the following instructions shall +be inserted. + + We begin with the most obvious information available to the server, +the request line. You should already have noted that a request consists +of a command (or "HTTP method") and a URI (e.g. a filename). It also +contains a string for the version of the protocol which can be found in +'version'. To call it a "new request" is justified because we return +only 'MHD_NO', thus ensuring the function will not be called again for +this connection. +printf ("New %s request for %s using version %s\n", method, url, version); + + The rest of the information is a bit more hidden. Nevertheless, +there is lot of it sent from common Internet browsers. It is stored in +"key-value" pairs and we want to list what we find in the header. As +there is no mandatory set of keys a client has to send, each key-value +pair is printed out one by one until there are no more left. We do this +by writing a separate function which will be called for each pair just +like the above function is called for each HTTP request. It can then +print out the content of this pair. +int print_out_key (void *cls, enum MHD_ValueKind kind, + const char *key, const char *value) +{ + printf ("%s: %s\n", key, value); + return MHD_YES; +} + + To start the iteration process that calls our new function for every +key, the line +MHD_get_connection_values (connection, MHD_HEADER_KIND, &print_out_key, NULL); +needs to be inserted in the connection callback function too. The +second parameter tells the function that we are only interested in keys +from the general HTTP header of the request. Our iterating function +'print_out_key' does not rely on any additional information to fulfill +its duties so the last parameter can be NULL. + + All in all, this constitutes the complete 'logging.c' program for +this chapter which can be found in the 'examples' section. + + Connecting with any modern Internet browser should yield a handful of +keys. You should try to interpret them with the aid of _RFC 2616_. +Especially worth mentioning is the "Host" key which is often used to +serve several different websites hosted under one single IP address but +reachable by different domain names (this is called virtual hosting). + +Conclusion +========== + +The introduced capabilities to itemize the content of a simple GET +request--especially the URI--should already allow the server to satisfy +clients' requests for small specific resources (e.g. files) or even +induce alteration of server state. However, the latter is not +recommended as the GET method (including its header data) is by +convention considered a "safe" operation, which should not change the +server's state in a significant way. By convention, GET operations can +thus be performed by crawlers and other automatic software. Naturally +actions like searching for a passed string are fine. + + Of course, no transmission can occur while the return value is still +set to 'MHD_NO' in the callback function. + +Exercises +========= + + * By parsing the 'url' string and delivering responses accordingly, + implement a small server for "virtual" files. When asked for + '/index.htm{l}', let the response consist of a HTML page containing + a link to '/another.html' page which is also to be created "on the + fly" in case of being requested. If neither of these two pages are + requested, 'MHD_HTTP_NOT_FOUND' shall be returned accompanied by an + informative message. + + * A very interesting information has still been ignored by our + logger--the client's IP address. Implement a callback function + static int on_client_connect (void *cls, + const struct sockaddr *addr, + socklen_t addrlen) + that prints out the IP address in an appropriate format. You might + want to use the POSIX function 'inet_ntoa' but bear in mind that + 'addr' is actually just a structure containing other substructures + and is _not_ the variable this function expects. Make sure to + return 'MHD_YES' so that the library knows the client is allowed to + connect (and to then process the request). If one wanted to limit + access basing on IP addresses, this would be the place to do it. + The address of your 'on_client_connect' function must be passed as + the third parameter to the 'MHD_start_daemon' call. + + +File: libmicrohttpd-tutorial.info, Node: Response headers, Next: Supporting basic authentication, Prev: Exploring requests, Up: Top + +4 Response headers +****************** + +Now that we are able to inspect the incoming request in great detail, +this chapter discusses the means to enrich the outgoing responses +likewise. + + As you have learned in the _Hello, Browser_ chapter, some obligatory +header fields are added and set automatically for simple responses by +the library itself but if more advanced features are desired, additional +fields have to be created. One of the possible fields is the content +type field and an example will be developed around it. This will lead +to an application capable of correctly serving different types of files. + + When we responded with HTML page packed in the static string +previously, the client had no choice but guessing about how to handle +the response, because the server had not told him. What if we had sent +a picture or a sound file? Would the message have been understood or +merely been displayed as an endless stream of random characters in the +browser? This is what the mime content types are for. The header of +the response is extended by certain information about how the data is to +be interpreted. + + To introduce the concept, a picture of the format _PNG_ will be sent +to the client and labeled accordingly with 'image/png'. Once again, we +can base the new example on the 'hellobrowser' program. + +#define FILENAME "picture.png" +#define MIMETYPE "image/png" + +static int +answer_to_connection (void *cls, struct MHD_Connection *connection, + const char *url, + const char *method, const char *version, + const char *upload_data, + size_t *upload_data_size, void **req_cls) +{ + unsigned char *buffer = NULL; + struct MHD_Response *response; + + We want the program to open the file for reading and determine its +size: + int fd; + int ret; + struct stat sbuf; + + if (0 != strcmp (method, "GET")) + return MHD_NO; + if ( (-1 == (fd = open (FILENAME, O_RDONLY))) || + (0 != fstat (fd, &sbuf)) ) + { + /* error accessing file */ + /* ... (see below) */ + } + /* ... (see below) */ + + When dealing with files, there is a lot that could go wrong on the +server side and if so, the client should be informed with +'MHD_HTTP_INTERNAL_SERVER_ERROR'. + + /* error accessing file */ + if (fd != -1) close (fd); + const char *errorstr = + "An internal server error has occurred!\ + "; + response = + MHD_create_response_from_buffer (strlen (errorstr), + (void *) errorstr, + MHD_RESPMEM_PERSISTENT); + if (response) + { + ret = + MHD_queue_response (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, + response); + MHD_destroy_response (response); + + return MHD_YES; + } + else + return MHD_NO; + if (!ret) + { + const char *errorstr = "An internal server error has occurred!\ + "; + + if (buffer) free(buffer); + + response = MHD_create_response_from_buffer (strlen(errorstr), (void*) errorstr, + MHD_RESPMEM_PERSISTENT); + + if (response) + { + ret = MHD_queue_response (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + response); + MHD_destroy_response (response); + + return MHD_YES; + } + else return MHD_NO; + } + + Note that we nevertheless have to create a response object even for +sending a simple error code. Otherwise, the connection would just be +closed without comment, leaving the client curious about what has +happened. + + But in the case of success a response will be constructed directly +from the file descriptor: + + /* error accessing file */ + /* ... (see above) */ + } + + response = + MHD_create_response_from_fd_at_offset (sbuf.st_size, fd, 0); + MHD_add_response_header (response, "Content-Type", MIMETYPE); + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + MHD_destroy_response (response); + + Note that the response object will take care of closing the file +descriptor for us. + + Up to this point, there was little new. The actual novelty is that +we enhance the header with the meta data about the content. Aware of +the field's name we want to add, it is as easy as that: +MHD_add_response_header(response, "Content-Type", MIMETYPE); +We do not have to append a colon expected by the protocol behind the +first field--_GNU libhttpdmicro_ will take care of this. + + The function finishes with the well-known lines + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + MHD_destroy_response (response); + return ret; +} + + The complete program 'responseheaders.c' is in the 'examples' section +as usual. Find a _PNG_ file you like and save it to the directory the +example is run from under the name 'picture.png'. You should find the +image displayed on your browser if everything worked well. + +Remarks +======= + +The include file of the _MHD_ library comes with the header types +mentioned in _RFC 2616_ already defined as macros. Thus, we could have +written 'MHD_HTTP_HEADER_CONTENT_TYPE' instead of '"Content-Type"' as +well. However, one is not limited to these standard headers and could +add custom response headers without violating the protocol. Whether, +and how, the client would react to these custom header is up to the +receiver. Likewise, the client is allowed to send custom request +headers to the server as well, opening up yet more possibilities how +client and server could communicate with each other. + + The method of creating the response from a file on disk only works +for static content. Serving dynamically created responses will be a +topic of a future chapter. + +Exercises +========= + + * Remember that the original program was written under a few + assumptions--a static response using a local file being one of + them. In order to simulate a very large or hard to reach file that + cannot be provided instantly, postpone the queuing in the callback + with the 'sleep' function for 30 seconds _if_ the file '/big.png' + is requested (but deliver the same as above). A request for + '/picture.png' should provide just the same but without any + artificial delays. + + Now start two instances of your browser (or even use two machines) + and see how the second client is put on hold while the first waits + for his request on the slow file to be fulfilled. + + Finally, change the sourcecode to use + 'MHD_USE_THREAD_PER_CONNECTION' when the daemon is started and try + again. + + * Did you succeed in implementing the clock exercise yet? This time, + let the server save the program's start time 't' and implement a + response simulating a countdown that reaches 0 at 't+60'. + Returning a message saying on which point the countdown is, the + response should ultimately be to reply "Done" if the program has + been running long enough, + + An unofficial, but widely understood, response header line is + 'Refresh: DELAY; url=URL' with the uppercase words substituted to + tell the client it should request the given resource after the + given delay again. Improve your program in that the browser (any + modern browser should work) automatically reconnects and asks for + the status again every 5 seconds or so. The URL would have to be + composed so that it begins with "http://", followed by the _URI_ + the server is reachable from the client's point of view. + + Maybe you want also to visualize the countdown as a status bar by + creating a '' consisting of one row and 'n' columns whose + fields contain small images of either a red or a green light. + + +File: libmicrohttpd-tutorial.info, Node: Supporting basic authentication, Next: Processing POST data, Prev: Response headers, Up: Top + +5 Supporting basic authentication +********************************* + +With the small exception of IP address based access control, requests +from all connecting clients where served equally until now. This +chapter discusses a first method of client's authentication and its +limits. + + A very simple approach feasible with the means already discussed +would be to expect the password in the _URI_ string before granting +access to the secured areas. The password could be separated from the +actual resource identifier by a certain character, thus the request line +might look like +GET /picture.png?mypassword + + In the rare situation where the client is customized enough and the +connection occurs through secured lines (e.g., a embedded device +directly attached to another via wire) and where the ability to embed a +password in the URI or to pass on a URI with a password are desired, +this can be a reasonable choice. + + But when it is assumed that the user connecting does so with an +ordinary Internet browser, this implementation brings some problems +about. For example, the URI including the password stays in the address +field or at least in the history of the browser for anybody near enough +to see. It will also be inconvenient to add the password manually to +any new URI when the browser does not know how to compose this +automatically. + + At least the convenience issue can be addressed by employing the +simplest built-in password facilities of HTTP compliant browsers, hence +we want to start there. It will, however, turn out to have still severe +weaknesses in terms of security which need consideration. + + Before we will start implementing _Basic Authentication_ as described +in _RFC 2617_, we will also abandon the simplistic and generally +problematic practice of responding every request the first time our +callback is called for a given connection. Queuing a response upon the +first request is akin to generating an error response (even if it is a +"200 OK" reply!). The reason is that MHD usually calls the callback in +three phases: + + 1. First, to initially tell the application about the connection and + inquire whether it is OK to proceed. This call typically happens + before the client could upload the request body, and can be used to + tell the client to not proceed with the upload (if the client + requested "Expect: 100 Continue"). Applications may queue a reply + at this point, but it will force the connection to be closed and + thus prevent keep-alive / pipelining, which is generally a bad + idea. Applications wanting to proceed with the request throughout + the other phases should just return "MHD_YES" and not queue any + response. Note that when an application suspends a connection in + this callback, the phase does not advance and the application will + be called again in this first phase. + 2. Next, to tell the application about upload data provided by the + client. In this phase, the application may not queue replies, and + trying to do so will result in MHD returning an error code from + 'MHD_queue_response'. If there is no upload data, this phase is + skipped. + 3. Finally, to obtain a regular response from the application. This + can be almost any type of response, including ones indicating + failures. The one exception is a "100 Continue" response, which + applications must never generate: MHD generates that response + automatically when necessary in the first phase. If the + application does not queue a response, MHD may call the callback + repeatedly (depending a bit on the threading model, the application + should suspend the connection). + + But how can we tell whether the callback has been called before for +the particular request? Initially, the pointer this parameter +references is set by _MHD_ in the callback. But it will also be +"remembered" on the next call (for the same request). Thus, we can use +the 'req_cls' location to keep track of the request state. For now, we +will simply generate no response until the parameter is +non-null--implying the callback was called before at least once. We do +not need to share information between different calls of the callback, +so we can set the parameter to any address that is assured to be not +null. The pointer to the 'connection' structure will be pointing to a +legal address, so we take this. + + The first time 'answer_to_connection' is called, we will not even +look at the headers. + +static int +answer_to_connection (void *cls, struct MHD_Connection *connection, + const char *url, const char *method, const char *version, + const char *upload_data, size_t *upload_data_size, + void **req_cls) +{ + if (0 != strcmp(method, "GET")) return MHD_NO; + if (NULL == *req_cls) {*req_cls = connection; return MHD_YES;} + + ... + /* else respond accordingly */ + ... +} + + Note how we lop off the connection on the first condition (no "GET" +request), but return asking for more on the other one with 'MHD_YES'. +With this minor change, we can proceed to implement the actual +authentication process. + +Request for authentication +========================== + +Let us assume we had only files not intended to be handed out without +the correct username/password, so every "GET" request will be +challenged. _RFC 7617_ describes how the server shall ask for +authentication by adding a _WWW-Authenticate_ response header with the +name of the _realm_ protected. MHD can generate and queue such a +failure response for you using the 'MHD_queue_basic_auth_fail_response' +API. The only thing you need to do is construct a response with the +error page to be shown to the user if he aborts basic authentication. +But first, you should check if the proper credentials were already +supplied using the 'MHD_basic_auth_get_username_password' call. + + Your code would then look like this: +static enum MHD_Result +answer_to_connection (void *cls, struct MHD_Connection *connection, + const char *url, const char *method, + const char *version, const char *upload_data, + size_t *upload_data_size, void **req_cls) +{ + struct MHD_BasicAuthInfo *auth_info; + enum MHD_Result ret; + struct MHD_Response *response; + + if (0 != strcmp (method, "GET")) + return MHD_NO; + if (NULL == *req_cls) + { + *req_cls = connection; + return MHD_YES; + } + auth_info = MHD_basic_auth_get_username_password3 (connection); + if (NULL == auth_info) + { + static const char *page = + "Authorization required"; + response = MHD_create_response_from_buffer_static (strlen (page), page); + ret = MHD_queue_basic_auth_fail_response3 (connection, + "admins", + MHD_YES, + response); + } + else if ((strlen ("root") != auth_info->username_len) || + (0 != memcmp (auth_info->username, "root", + auth_info->username_len)) || + /* The next check against NULL is optional, + * if 'password' is NULL then 'password_len' is always zero. */ + (NULL == auth_info->password) || + (strlen ("pa$$w0rd") != auth_info->password_len) || + (0 != memcmp (auth_info->password, "pa$$w0rd", + auth_info->password_len))) + { + static const char *page = + "Wrong username or password"; + response = MHD_create_response_from_buffer_static (strlen (page), page); + ret = MHD_queue_basic_auth_fail_response3 (connection, + "admins", + MHD_YES, + response); + } + else + { + static const char *page = "A secret."; + response = MHD_create_response_from_buffer_static (strlen (page), page); + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + } + if (NULL != auth_info) + MHD_free (auth_info); + MHD_destroy_response (response); + return ret; +} + + See the 'examples' directory for the complete example file. + +Remarks +======= + +For a proper server, the conditional statements leading to a return of +'MHD_NO' should yield a response with a more precise status code instead +of silently closing the connection. For example, failures of memory +allocation are best reported as _internal server error_ and unexpected +authentication methods as _400 bad request_. + +Exercises +========= + + * Make the server respond to wrong credentials (but otherwise + well-formed requests) with the recommended _401 unauthorized_ + status code. If the client still does not authenticate correctly + within the same connection, close it and store the client's IP + address for a certain time. (It is OK to check for expiration not + until the main thread wakes up again on the next connection.) If + the client fails authenticating three times during this period, add + it to another list for which the 'AcceptPolicyCallback' function + denies connection (temporally). + + * With the network utility 'netcat' connect and log the response of a + "GET" request as you did in the exercise of the first example, this + time to a file. Now stop the server and let _netcat_ listen on the + same port the server used to listen on and have it fake being the + proper server by giving the file's content as the response (e.g. + 'cat log | nc -l -p 8888'). Pretending to think your were + connecting to the actual server, browse to the eavesdropper and + give the correct credentials. + + Copy and paste the encoded string you see in 'netcat''s output to + some of the Base64 decode tools available online and see how both + the user's name and password could be completely restored. + + +File: libmicrohttpd-tutorial.info, Node: Processing POST data, Next: Improved processing of POST data, Prev: Supporting basic authentication, Up: Top + +6 Processing POST data +********************** + +The previous chapters already have demonstrated a variety of +possibilities to send information to the HTTP server, but it is not +recommended that the _GET_ method is used to alter the way the server +operates. To induce changes on the server, the _POST_ method is +preferred over and is much more powerful than _GET_ and will be +introduced in this chapter. + + We are going to write an application that asks for the visitor's name +and, after the user has posted it, composes an individual response text. +Even though it was not mandatory to use the _POST_ method here, as there +is no permanent change caused by the POST, it is an illustrative example +on how to share data between different functions for the same +connection. Furthermore, the reader should be able to extend it easily. + +GET request +=========== + +When the first _GET_ request arrives, the server shall respond with a +HTML page containing an edit field for the name. + +const char* askpage = "\ + What's your name, Sir?
\ + \ + \ + "; + + The 'action' entry is the _URI_ to be called by the browser when +posting, and the 'name' will be used later to be sure it is the +editbox's content that has been posted. + + We also prepare the answer page, where the name is to be filled in +later, and an error page as the response for anything but proper _GET_ +and _POST_ requests: + +const char* greatingpage="

Welcome, %s!

"; + +const char* errorpage="This doesn't seem to be right."; + + Whenever we need to send a page, we use an extra function 'int +send_page(struct MHD_Connection *connection, const char* page)' for +this, which does not contain anything new and whose implementation is +therefore not discussed further in the tutorial. + +POST request +============ + +Posted data can be of arbitrary and considerable size; for example, if a +user uploads a big image to the server. Similar to the case of the +header fields, there may also be different streams of posted data, such +as one containing the text of an editbox and another the state of a +button. Likewise, we will have to register an iterator function that is +going to be called maybe several times not only if there are different +POSTs but also if one POST has only been received partly yet and needs +processing before another chunk can be received. + + Such an iterator function is called by a _postprocessor_, which must +be created upon arriving of the post request. We want the iterator +function to read the first post data which is tagged 'name' and to +create an individual greeting string based on the template and the name. +But in order to pass this string to other functions and still be able to +differentiate different connections, we must first define a structure to +share the information, holding the most import entries. + +struct connection_info_struct +{ + int connectiontype; + char *answerstring; + struct MHD_PostProcessor *postprocessor; +}; + + With these information available to the iterator function, it is able +to fulfill its task. Once it has composed the greeting string, it +returns 'MHD_NO' to inform the post processor that it does not need to +be called again. Note that this function does not handle processing of +data for the same 'key'. If we were to expect that the name will be +posted in several chunks, we had to expand the namestring dynamically as +additional parts of it with the same 'key' came in. But in this +example, the name is assumed to fit entirely inside one single packet. + +static int +iterate_post (void *coninfo_cls, enum MHD_ValueKind kind, const char *key, + const char *filename, const char *content_type, + const char *transfer_encoding, const char *data, + uint64_t off, size_t size) +{ + struct connection_info_struct *con_info = coninfo_cls; + + if (0 == strcmp (key, "name")) + { + if ((size > 0) && (size <= MAXNAMESIZE)) + { + char *answerstring; + answerstring = malloc (MAXANSWERSIZE); + if (!answerstring) return MHD_NO; + + snprintf (answerstring, MAXANSWERSIZE, greatingpage, data); + con_info->answerstring = answerstring; + } + else con_info->answerstring = NULL; + + return MHD_NO; + } + + return MHD_YES; +} + + Once a connection has been established, it can be terminated for many +reasons. As these reasons include unexpected events, we have to +register another function that cleans up any resources that might have +been allocated for that connection by us, namely the post processor and +the greetings string. This cleanup function must take into account that +it will also be called for finished requests other than _POST_ requests. + +void request_completed (void *cls, struct MHD_Connection *connection, + void **req_cls, + enum MHD_RequestTerminationCode toe) +{ + struct connection_info_struct *con_info = *req_cls; + + if (NULL == con_info) return; + if (con_info->connectiontype == POST) + { + MHD_destroy_post_processor (con_info->postprocessor); + if (con_info->answerstring) free (con_info->answerstring); + } + + free (con_info); + *req_cls = NULL; +} + + _GNU libmicrohttpd_ is informed that it shall call the above function +when the daemon is started in the main function. + +... +daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD, PORT, NULL, NULL, + &answer_to_connection, NULL, + MHD_OPTION_NOTIFY_COMPLETED, &request_completed, NULL, + MHD_OPTION_END); +... + +Request handling +================ + +With all other functions prepared, we can now discuss the actual request +handling. + + On the first iteration for a new request, we start by allocating a +new instance of a 'struct connection_info_struct' structure, which will +store all necessary information for later iterations and other +functions. + +static int +answer_to_connection (void *cls, struct MHD_Connection *connection, + const char *url, + const char *method, const char *version, + const char *upload_data, + size_t *upload_data_size, void **req_cls) +{ + if(NULL == *req_cls) + { + struct connection_info_struct *con_info; + + con_info = malloc (sizeof (struct connection_info_struct)); + if (NULL == con_info) return MHD_NO; + con_info->answerstring = NULL; + + If the new request is a _POST_, the postprocessor must be created +now. In addition, the type of the request is stored for convenience. + if (0 == strcmp (method, "POST")) + { + con_info->postprocessor + = MHD_create_post_processor (connection, POSTBUFFERSIZE, + iterate_post, (void*) con_info); + + if (NULL == con_info->postprocessor) + { + free (con_info); + return MHD_NO; + } + con_info->connectiontype = POST; + } + else con_info->connectiontype = GET; + + The address of our structure will both serve as the indicator for +successive iterations and to remember the particular details about the +connection. + *req_cls = (void*) con_info; + return MHD_YES; + } + + The rest of the function will not be executed on the first iteration. +A _GET_ request is easily satisfied by sending the question form. + if (0 == strcmp (method, "GET")) + { + return send_page (connection, askpage); + } + + In case of _POST_, we invoke the post processor for as long as data +keeps incoming, setting '*upload_data_size' to zero in order to indicate +that we have processed--or at least have considered--all of it. + if (0 == strcmp (method, "POST")) + { + struct connection_info_struct *con_info = *req_cls; + + if (*upload_data_size != 0) + { + MHD_post_process (con_info->postprocessor, upload_data, + *upload_data_size); + *upload_data_size = 0; + + return MHD_YES; + } + else if (NULL != con_info->answerstring) + return send_page (connection, con_info->answerstring); + } + + Finally, if they are neither _GET_ nor _POST_ requests, the error +page is returned. + return send_page(connection, errorpage); +} + + These were the important parts of the program 'simplepost.c'. + + +File: libmicrohttpd-tutorial.info, Node: Improved processing of POST data, Next: Session management, Prev: Processing POST data, Up: Top + +7 Improved processing of POST data +********************************** + +The previous chapter introduced a way to upload data to the server, but +the developed example program has some shortcomings, such as not being +able to handle larger chunks of data. In this chapter, we are going to +discuss a more advanced server program that allows clients to upload a +file in order to have it stored on the server's filesystem. The server +shall also watch and limit the number of clients concurrently uploading, +responding with a proper busy message if necessary. + +Prepared answers +================ + +We choose to operate the server with the 'SELECT_INTERNALLY' method. +This makes it easier to synchronize the global states at the cost of +possible delays for other connections if the processing of a request is +too slow. One of these variables that needs to be shared for all +connections is the total number of clients that are uploading. + +#define MAXCLIENTS 2 +static unsigned int nr_of_uploading_clients = 0; + + If there are too many clients uploading, we want the server to +respond to all requests with a busy message. +const char* busypage = + "This server is busy, please try again later."; + + Otherwise, the server will send a _form_ that informs the user of the +current number of uploading clients, and ask her to pick a file on her +local filesystem which is to be uploaded. +const char* askpage = "\n\ + Upload a file, please!
\n\ + There are %u clients uploading at the moment.
\n\ + \n\ + \n\ + \n\ + "; + + If the upload has succeeded, the server will respond with a message +saying so. +const char* completepage = "The upload has been completed."; + + We want the server to report internal errors, such as memory shortage +or file access problems, adequately. +const char* servererrorpage + = "An internal server error has occurred."; +const char* fileexistspage + = "This file already exists."; + + It would be tolerable to send all these responses undifferentiated +with a '200 HTTP_OK' status code but in order to improve the 'HTTP' +conformance of our server a bit, we extend the 'send_page' function so +that it accepts individual status codes. + +static int +send_page (struct MHD_Connection *connection, + const char* page, int status_code) +{ + int ret; + struct MHD_Response *response; + + response = MHD_create_response_from_buffer (strlen (page), (void*) page, + MHD_RESPMEM_MUST_COPY); + if (!response) return MHD_NO; + + ret = MHD_queue_response (connection, status_code, response); + MHD_destroy_response (response); + + return ret; +} + + Note how we ask _MHD_ to make its own copy of the message data. The +reason behind this will become clear later. + +Connection cycle +================ + +The decision whether the server is busy or not is made right at the +beginning of the connection. To do that at this stage is especially +important for _POST_ requests because if no response is queued at this +point, and 'MHD_YES' returned, _MHD_ will not sent any queued messages +until a postprocessor has been created and the post iterator is called +at least once. + +static int +answer_to_connection (void *cls, struct MHD_Connection *connection, + const char *url, + const char *method, const char *version, + const char *upload_data, + size_t *upload_data_size, void **req_cls) +{ + if (NULL == *req_cls) + { + struct connection_info_struct *con_info; + + if (nr_of_uploading_clients >= MAXCLIENTS) + return send_page(connection, busypage, MHD_HTTP_SERVICE_UNAVAILABLE); + + If the server is not busy, the 'connection_info' structure is +initialized as usual, with the addition of a filepointer for each +connection. + + con_info = malloc (sizeof (struct connection_info_struct)); + if (NULL == con_info) return MHD_NO; + con_info->fp = 0; + + if (0 == strcmp (method, "POST")) + { + ... + } + else con_info->connectiontype = GET; + + *req_cls = (void*) con_info; + + return MHD_YES; + } + + For _POST_ requests, the postprocessor is created and we register a +new uploading client. From this point on, there are many possible +places for errors to occur that make it necessary to interrupt the +uploading process. We need a means of having the proper response +message ready at all times. Therefore, the 'connection_info' structure +is extended to hold the most current response message so that whenever a +response is sent, the client will get the most informative message. +Here, the structure is initialized to "no error". + if (0 == strcmp (method, "POST")) + { + con_info->postprocessor + = MHD_create_post_processor (connection, POSTBUFFERSIZE, + iterate_post, (void*) con_info); + + if (NULL == con_info->postprocessor) + { + free (con_info); + return MHD_NO; + } + + nr_of_uploading_clients++; + + con_info->connectiontype = POST; + con_info->answercode = MHD_HTTP_OK; + con_info->answerstring = completepage; + } + else con_info->connectiontype = GET; + + If the connection handler is called for the second time, _GET_ +requests will be answered with the _form_. We can keep the buffer under +function scope, because we asked _MHD_ to make its own copy of it for as +long as it is needed. + if (0 == strcmp (method, "GET")) + { + int ret; + char buffer[1024]; + + sprintf (buffer, askpage, nr_of_uploading_clients); + return send_page (connection, buffer, MHD_HTTP_OK); + } + + The rest of the 'answer_to_connection' function is very similar to +the 'simplepost.c' example, except the more flexible content of the +responses. The _POST_ data is processed until there is none left and +the execution falls through to return an error page if the connection +constituted no expected request method. + if (0 == strcmp (method, "POST")) + { + struct connection_info_struct *con_info = *req_cls; + + if (0 != *upload_data_size) + { + MHD_post_process (con_info->postprocessor, + upload_data, *upload_data_size); + *upload_data_size = 0; + + return MHD_YES; + } + else + return send_page (connection, con_info->answerstring, + con_info->answercode); + } + + return send_page(connection, errorpage, MHD_HTTP_BAD_REQUEST); +} + +Storing to data +=============== + +Unlike the 'simplepost.c' example, here it is to be expected that post +iterator will be called several times now. This means that for any +given connection (there might be several concurrent of them) the posted +data has to be written to the correct file. That is why we store a file +handle in every 'connection_info', so that the it is preserved between +successive iterations. +static int +iterate_post (void *coninfo_cls, enum MHD_ValueKind kind, + const char *key, + const char *filename, const char *content_type, + const char *transfer_encoding, const char *data, + uint64_t off, size_t size) +{ + struct connection_info_struct *con_info = coninfo_cls; + + Because the following actions depend heavily on correct file +processing, which might be error prone, we default to reporting internal +errors in case anything will go wrong. + +con_info->answerstring = servererrorpage; +con_info->answercode = MHD_HTTP_INTERNAL_SERVER_ERROR; + + In the "askpage" _form_, we told the client to label its post data +with the "file" key. Anything else would be an error. + + if (0 != strcmp (key, "file")) return MHD_NO; + + If the iterator is called for the first time, no file will have been +opened yet. The 'filename' string contains the name of the file +(without any paths) the user selected on his system. We want to take +this as the name the file will be stored on the server and make sure no +file of that name exists (or is being uploaded) before we create one +(note that the code below technically contains a race between the two +"fopen" calls, but we will overlook this for portability sake). + if (!con_info->fp) + { + if (NULL != (fp = fopen (filename, "rb")) ) + { + fclose (fp); + con_info->answerstring = fileexistspage; + con_info->answercode = MHD_HTTP_FORBIDDEN; + return MHD_NO; + } + + con_info->fp = fopen (filename, "ab"); + if (!con_info->fp) return MHD_NO; + } + + Occasionally, the iterator function will be called even when there +are 0 new bytes to process. The server only needs to write data to the +file if there is some. +if (size > 0) + { + if (!fwrite (data, size, sizeof(char), con_info->fp)) + return MHD_NO; + } + + If this point has been reached, everything worked well for this +iteration and the response can be set to success again. If the upload +has finished, this iterator function will not be called again. + con_info->answerstring = completepage; + con_info->answercode = MHD_HTTP_OK; + + return MHD_YES; +} + + The new client was registered when the postprocessor was created. +Likewise, we unregister the client on destroying the postprocessor when +the request is completed. +void request_completed (void *cls, struct MHD_Connection *connection, + void **req_cls, + enum MHD_RequestTerminationCode toe) +{ + struct connection_info_struct *con_info = *req_cls; + + if (NULL == con_info) return; + + if (con_info->connectiontype == POST) + { + if (NULL != con_info->postprocessor) + { + MHD_destroy_post_processor (con_info->postprocessor); + nr_of_uploading_clients--; + } + + if (con_info->fp) fclose (con_info->fp); + } + + free (con_info); + *req_cls = NULL; +} + + This is essentially the whole example 'largepost.c'. + +Remarks +======= + +Now that the clients are able to create files on the server, security +aspects are becoming even more important than before. Aside from proper +client authentication, the server should always make sure explicitly +that no files will be created outside of a dedicated upload directory. +In particular, filenames must be checked to not contain strings like +"../". + + +File: libmicrohttpd-tutorial.info, Node: Session management, Next: Adding a layer of security, Prev: Improved processing of POST data, Up: Top + +8 Session management +******************** + +This chapter discusses how one should manage sessions, that is, share +state between multiple HTTP requests from the same user. We use a +simple example where the user submits multiple forms and the server is +supposed to accumulate state from all of these forms. Naturally, as +this is a network protocol, our session mechanism must support having +many users with many concurrent sessions at the same time. + + In order to track users, we use a simple session cookie. A session +cookie expires when the user closes the browser. Changing from session +cookies to persistent cookies only requires adding an expiration time to +the cookie. The server creates a fresh session cookie whenever a +request without a cookie is received, or if the supplied session cookie +is not known to the server. + +Looking up the cookie +===================== + +Since MHD parses the HTTP cookie header for us, looking up an existing +cookie is straightforward: + +const char *value; + +value = MHD_lookup_connection_value (connection, + MHD_COOKIE_KIND, + "KEY"); + + Here, "KEY" is the name we chose for our session cookie. + +Setting the cookie header +========================= + +MHD requires the user to provide the full cookie format string in order +to set cookies. In order to generate a unique cookie, our example +creates a random 64-character text string to be used as the value of the +cookie: + +char value[128]; +char raw_value[65]; + +for (unsigned int i=0;i openssl genrsa -out server.key 1024 + + In addition to the key, a certificate describing the server in human +readable tokens is also needed. This certificate will be attested with +our aforementioned key. In this way, we obtain a self-signed +certificate, valid for one year. + +> openssl req -days 365 -out server.pem -new -x509 -key server.key + + To avoid unnecessary error messages in the browser, the certificate +needs to have a name that matches the _URI_, for example, "localhost" or +the domain. If you plan to have a publicly reachable server, you will +need to ask a trusted third party, called _Certificate Authority_, or +_CA_, to attest the certificate for you. This way, any visitor can make +sure the server's identity is real. + + Whether the server's certificate is signed by us or a third party, +once it has been accepted by the client, both sides will be +communicating over encrypted channels. From this point on, it is the +client's turn to authenticate itself. But this has already been +implemented in the basic authentication scheme. + +Changing the source code +======================== + +We merely have to extend the server program so that it loads the two +files into memory, + +int +main () +{ + struct MHD_Daemon *daemon; + char *key_pem; + char *cert_pem; + + key_pem = load_file (SERVERKEYFILE); + cert_pem = load_file (SERVERCERTFILE); + + if ((key_pem == NULL) || (cert_pem == NULL)) + { + printf ("The key/certificate files could not be read.\n"); + return 1; + } + + and then we point the _MHD_ daemon to it upon initialization. + + daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_SSL, + PORT, NULL, NULL, + &answer_to_connection, NULL, + MHD_OPTION_HTTPS_MEM_KEY, key_pem, + MHD_OPTION_HTTPS_MEM_CERT, cert_pem, + MHD_OPTION_END); + + if (NULL == daemon) + { + printf ("%s\n", cert_pem); + + free (key_pem); + free (cert_pem); + + return 1; + } + + The rest consists of little new besides some additional memory +cleanups. + + getchar (); + + MHD_stop_daemon (daemon); + free (key_pem); + free (cert_pem); + + return 0; +} + + The rather unexciting file loader can be found in the complete +example 'tlsauthentication.c'. + +Remarks +======= + + * While the standard _HTTP_ port is 80, it is 443 for _HTTPS_. The + common internet browsers assume standard _HTTP_ if they are asked + to access other ports than these. Therefore, you will have to type + 'https://localhost:8888' explicitly when you test the example, or + the browser will not know how to handle the answer properly. + + * The remaining weak point is the question how the server will be + trusted initially. Either a _CA_ signs the certificate or the + client obtains the key over secure means. Anyway, the clients have + to be aware (or configured) that they should not accept + certificates of unknown origin. + + * The introduced method of certificates makes it mandatory to set an + expiration date--making it less feasible to hardcode certificates + in embedded devices. + + * The cryptographic facilities consume memory space and computing + time. For this reason, websites usually consists both of + uncritically _HTTP_ parts and secured _HTTPS_. + +Client authentication +===================== + +You can also use MHD to authenticate the client via SSL/TLS certificates +(as an alternative to using the password-based Basic or Digest +authentication). To do this, you will need to link your application +against _gnutls_. Next, when you start the MHD daemon, you must specify +the root CA that you're willing to trust: + daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_SSL, + PORT, NULL, NULL, + &answer_to_connection, NULL, + MHD_OPTION_HTTPS_MEM_KEY, key_pem, + MHD_OPTION_HTTPS_MEM_CERT, cert_pem, + MHD_OPTION_HTTPS_MEM_TRUST, root_ca_pem, + MHD_OPTION_END); + + With this, you can then obtain client certificates for each session. +In order to obtain the identity of the client, you first need to obtain +the raw GnuTLS session handle from _MHD_ using +'MHD_get_connection_info'. + +#include +#include + +gnutls_session_t tls_session; +union MHD_ConnectionInfo *ci; + +ci = MHD_get_connection_info (connection, + MHD_CONNECTION_INFO_GNUTLS_SESSION); +tls_session = (gnutls_session_t) ci->tls_session; + + You can then extract the client certificate: + +/** + * Get the client's certificate + * + * @param tls_session the TLS session + * @return NULL if no valid client certificate could be found, a pointer + * to the certificate if found + */ +static gnutls_x509_crt_t +get_client_certificate (gnutls_session_t tls_session) +{ + unsigned int listsize; + const gnutls_datum_t * pcert; + gnutls_certificate_status_t client_cert_status; + gnutls_x509_crt_t client_cert; + + if (tls_session == NULL) + return NULL; + if (gnutls_certificate_verify_peers2(tls_session, + &client_cert_status)) + return NULL; + if (0 != client_cert_status) + { + fprintf (stderr, + "Failed client certificate invalid: %d\n", + client_cert_status); + return NULL; + } + pcert = gnutls_certificate_get_peers(tls_session, + &listsize); + if ( (pcert == NULL) || + (listsize == 0)) + { + fprintf (stderr, + "Failed to retrieve client certificate chain\n"); + return NULL; + } + if (gnutls_x509_crt_init(&client_cert)) + { + fprintf (stderr, + "Failed to initialize client certificate\n"); + return NULL; + } + /* Note that by passing values between 0 and listsize here, you + can get access to the CA's certs */ + if (gnutls_x509_crt_import(client_cert, + &pcert[0], + GNUTLS_X509_FMT_DER)) + { + fprintf (stderr, + "Failed to import client certificate\n"); + gnutls_x509_crt_deinit(client_cert); + return NULL; + } + return client_cert; +} + + Using the client certificate, you can then get the client's +distinguished name and alternative names: + +/** + * Get the distinguished name from the client's certificate + * + * @param client_cert the client certificate + * @return NULL if no dn or certificate could be found, a pointer + * to the dn if found + */ +char * +cert_auth_get_dn(gnutls_x509_crt_t client_cert) +{ + char* buf; + size_t lbuf; + + lbuf = 0; + gnutls_x509_crt_get_dn(client_cert, NULL, &lbuf); + buf = malloc(lbuf); + if (buf == NULL) + { + fprintf (stderr, + "Failed to allocate memory for certificate dn\n"); + return NULL; + } + gnutls_x509_crt_get_dn(client_cert, buf, &lbuf); + return buf; +} + + +/** + * Get the alternative name of specified type from the client's certificate + * + * @param client_cert the client certificate + * @param nametype The requested name type + * @param index The position of the alternative name if multiple names are + * matching the requested type, 0 for the first matching name + * @return NULL if no matching alternative name could be found, a pointer + * to the alternative name if found + */ +char * +MHD_cert_auth_get_alt_name(gnutls_x509_crt_t client_cert, + int nametype, + unsigned int index) +{ + char* buf; + size_t lbuf; + unsigned int seq; + unsigned int subseq; + unsigned int type; + int result; + + subseq = 0; + for (seq=0;;seq++) + { + lbuf = 0; + result = gnutls_x509_crt_get_subject_alt_name2(client_cert, seq, NULL, &lbuf, + &type, NULL); + if (result == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + return NULL; + if (nametype != (int) type) + continue; + if (subseq == index) + break; + subseq++; + } + buf = malloc(lbuf); + if (buf == NULL) + { + fprintf (stderr, + "Failed to allocate memory for certificate alt name\n"); + return NULL; + } + result = gnutls_x509_crt_get_subject_alt_name2(client_cert, + seq, + buf, + &lbuf, + NULL, NULL); + if (result != nametype) + { + fprintf (stderr, + "Unexpected return value from gnutls: %d\n", + result); + free (buf); + return NULL; + } + return buf; +} + + Finally, you should release the memory associated with the client +certificate: + +gnutls_x509_crt_deinit (client_cert); + +Using TLS Server Name Indication (SNI) +====================================== + +SNI enables hosting multiple domains under one IP address with TLS. So +SNI is the TLS-equivalent of virtual hosting. To use SNI with MHD, you +need at least GnuTLS 3.0. The main change compared to the simple +hosting of one domain is that you need to provide a callback instead of +the key and certificate. For example, when you start the MHD daemon, +you could do this: + daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_SSL, + PORT, NULL, NULL, + &answer_to_connection, NULL, + MHD_OPTION_HTTPS_CERT_CALLBACK, &sni_callback, + MHD_OPTION_END); + Here, 'sni_callback' is the name of a function that you will have to +implement to retrieve the X.509 certificate for an incoming connection. +The callback has type 'gnutls_certificate_retrieve_function2' and is +documented in the GnuTLS API for the +'gnutls_certificate_set_retrieve_function2' as follows: + + -- Function Pointer: int *gnutls_certificate_retrieve_function2 + (gnutls_session_t, const gnutls_datum_t* req_ca_dn, int nreqs, + const gnutls_pk_algorithm_t* pk_algos, int pk_algos_length, + gnutls_pcert_st** pcert, unsigned int *pcert_length, + gnutls_privkey_t * pkey) + + REQ_CA_CERT + is only used in X.509 certificates. Contains a list with the + CA names that the server considers trusted. Normally we + should send a certificate that is signed by one of these CAs. + These names are DER encoded. To get a more meaningful value + use the function 'gnutls_x509_rdn_get()'. + + PK_ALGOS + contains a list with server’s acceptable signature algorithms. + The certificate returned should support the server’s given + algorithms. + + PCERT + should contain a single certificate and public or a list of + them. + + PCERT_LENGTH + is the size of the previous list. + + PKEY + is the private key. + + A possible implementation of this callback would look like this: + +struct Hosts +{ + struct Hosts *next; + const char *hostname; + gnutls_pcert_st pcrt; + gnutls_privkey_t key; +}; + +static struct Hosts *hosts; + +int +sni_callback (gnutls_session_t session, + const gnutls_datum_t* req_ca_dn, + int nreqs, + const gnutls_pk_algorithm_t* pk_algos, + int pk_algos_length, + gnutls_pcert_st** pcert, + unsigned int *pcert_length, + gnutls_privkey_t * pkey) +{ + char name[256]; + size_t name_len; + struct Hosts *host; + unsigned int type; + + name_len = sizeof (name); + if (GNUTLS_E_SUCCESS != + gnutls_server_name_get (session, + name, + &name_len, + &type, + 0 /* index */)) + return -1; + for (host = hosts; NULL != host; host = host->next) + if (0 == strncmp (name, host->hostname, name_len)) + break; + if (NULL == host) + { + fprintf (stderr, + "Need certificate for %.*s\n", + (int) name_len, + name); + return -1; + } + fprintf (stderr, + "Returning certificate for %.*s\n", + (int) name_len, + name); + *pkey = host->key; + *pcert_length = 1; + *pcert = &host->pcrt; + return 0; +} + + Note that MHD cannot offer passing a closure or any other additional +information to this callback, as the GnuTLS API unfortunately does not +permit this at this point. + + The 'hosts' list can be initialized by loading the private keys and +X.509 certificates from disk as follows: + +static void +load_keys(const char *hostname, + const char *CERT_FILE, + const char *KEY_FILE) +{ + int ret; + gnutls_datum_t data; + struct Hosts *host; + + host = malloc (sizeof (struct Hosts)); + host->hostname = hostname; + host->next = hosts; + hosts = host; + + ret = gnutls_load_file (CERT_FILE, &data); + if (ret < 0) + { + fprintf (stderr, + "*** Error loading certificate file %s.\n", + CERT_FILE); + exit(1); + } + ret = + gnutls_pcert_import_x509_raw (&host->pcrt, &data, GNUTLS_X509_FMT_PEM, + 0); + if (ret < 0) + { + fprintf(stderr, + "*** Error loading certificate file: %s\n", + gnutls_strerror (ret)); + exit(1); + } + gnutls_free (data.data); + + ret = gnutls_load_file (KEY_FILE, &data); + if (ret < 0) + { + fprintf (stderr, + "*** Error loading key file %s.\n", + KEY_FILE); + exit(1); + } + + gnutls_privkey_init (&host->key); + ret = + gnutls_privkey_import_x509_raw (host->key, + &data, GNUTLS_X509_FMT_PEM, + NULL, 0); + if (ret < 0) + { + fprintf (stderr, + "*** Error loading key file: %s\n", + gnutls_strerror (ret)); + exit(1); + } + gnutls_free (data.data); +} + + The code above was largely lifted from GnuTLS. You can find other +methods for initializing certificates and keys in the GnuTLS manual and +source code. + + +File: libmicrohttpd-tutorial.info, Node: Websockets, Next: Bibliography, Prev: Adding a layer of security, Up: Top + +10 Websockets +************* + +Websockets are a genuine way to implement push notifications, where the +server initiates the communication while the client can be idle. +Usually a HTTP communication is half-duplex and always requested by the +client, but websockets are full-duplex and only initialized by the +client. In the further communication both sites can use the websocket +at any time to send data to the other site. + + To initialize a websocket connection the client sends a special HTTP +request to the server and initializes a handshake between client and +server which switches from the HTTP protocol to the websocket protocol. +Thus both the server as well as the client must support websockets. If +proxys are used, they must support websockets too. In this chapter we +take a look on server and client, but with a focus on the server with +_libmicrohttpd_. + + Since version 0.9.52 _libmicrohttpd_ supports upgrading requests, +which is required for switching from the HTTP protocol. Since version +0.9.74 the library _libmicrohttpd_ws_ has been added to support the +websocket protocol. + +Upgrading connections with libmicrohttpd +======================================== + +To support websockets we need to enable upgrading of HTTP connections +first. This is done by passing the flag 'MHD_ALLOW_UPGRADE' to +'MHD_start_daemon()'. + +daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | + MHD_USE_THREAD_PER_CONNECTION | + MHD_ALLOW_UPGRADE | + MHD_USE_ERROR_LOG, + PORT, NULL, NULL, + &access_handler, NULL, + MHD_OPTION_END); + + The next step is to turn a specific request into an upgraded +connection. This done in our 'access_handler' by calling +'MHD_create_response_for_upgrade()'. An 'upgrade_handler' will be +passed to perform the low-level actions on the socket. + + _Please note that the socket here is just a regular socket as +provided by the operating system. To use it as a websocket, some more +steps from the following chapters are required._ + +static enum MHD_Result +access_handler (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, + size_t *upload_data_size, + void **ptr) +{ + /* ... */ + /* some code to decide whether to upgrade or not */ + /* ... */ + + /* create the response for upgrade */ + response = MHD_create_response_for_upgrade (&upgrade_handler, + NULL); + + /* ... */ + /* additional headers, etc. */ + /* ... */ + + ret = MHD_queue_response (connection, + MHD_HTTP_SWITCHING_PROTOCOLS, + response); + MHD_destroy_response (response); + + return ret; +} + + In the 'upgrade_handler' we receive the low-level socket, which is +used for the communication with the specific client. In addition to the +low-level socket we get: + * Some data, which has been read too much while _libmicrohttpd_ was + switching the protocols. This value is usually empty, because it + would mean that the client has sent data before the handshake was + complete. + + * A 'struct MHD_UpgradeResponseHandle' which is used to perform + special actions like closing, corking or uncorking the socket. + These commands are executed by passing the handle to + 'MHD_upgrade_action()'. + + Depending of the flags specified while calling 'MHD_start_deamon()' +our 'upgrade_handler' is either executed in the same thread as our +daemon or in a thread specific for each connection. If it is executed +in the same thread then 'upgrade_handler' is a blocking call for our +webserver and we should finish it as fast as possible (i. e. by +creating a thread and passing the information there). If +'MHD_USE_THREAD_PER_CONNECTION' was passed to 'MHD_start_daemon()' then +a separate thread is used and thus our 'upgrade_handler' needs not to +start a separate thread. + + An 'upgrade_handler', which is called with a separate thread per +connection, could look like this: + +static void +upgrade_handler (void *cls, + struct MHD_Connection *connection, + void *req_cls, + const char *extra_in, + size_t extra_in_size, + MHD_socket fd, + struct MHD_UpgradeResponseHandle *urh) +{ + /* ... */ + /* do something with the socket `fd` like `recv()` or `send()` */ + /* ... */ + + /* close the socket when it is not needed anymore */ + MHD_upgrade_action (urh, + MHD_UPGRADE_ACTION_CLOSE); +} + + This is all you need to know for upgrading connections with +_libmicrohttpd_. The next chapters focus on using the websocket +protocol with _libmicrohttpd_ws_. + +Websocket handshake with libmicrohttpd_ws +========================================= + +To request a websocket connection the client must send the following +information with the HTTP request: + + * A 'GET' request must be sent. + + * The version of the HTTP protocol must be 1.1 or higher. + + * A 'Host' header field must be sent + + * A 'Upgrade' header field containing the keyword "websocket" + (case-insensitive). Please note that the client could pass + multiple protocols separated by comma. + + * A 'Connection' header field that includes the token "Upgrade" + (case-insensitive). Please note that the client could pass + multiple tokens separated by comma. + + * A 'Sec-WebSocket-Key' header field with a base64-encoded value. + The decoded the value is 16 bytes long and has been generated + randomly by the client. + + * A 'Sec-WebSocket-Version' header field with the value "13". + + Optionally the client can also send the following information: + + * A 'Origin' header field can be used to determine the source of the + client (i. e. the website). + + * A 'Sec-WebSocket-Protocol' header field can contain a list of + supported protocols by the client, which can be sent over the + websocket. + + * A 'Sec-WebSocket-Extensions' header field which may contain + extensions to the websocket protocol. The extensions must be + registered by IANA. + + A valid example request from the client could look like this: + +GET /chat HTTP/1.1 +Host: server.example.com +Upgrade: websocket +Connection: Upgrade +Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== +Sec-WebSocket-Version: 13 + + To complete the handshake the server must respond with some specific +response headers: + + * The HTTP response code '101 Switching Protocols' must be answered. + + * An 'Upgrade' header field containing the value "websocket" must be + sent. + + * A 'Connection' header field containing the value "Upgrade" must be + sent. + + * A 'Sec-WebSocket-Accept' header field containing a value, which has + been calculated from the 'Sec-WebSocket-Key' request header field, + must be sent. + + Optionally the server may send following headers: + + * A 'Sec-WebSocket-Protocol' header field containing a protocol of + the list specified in the corresponding request header field. + + * A 'Sec-WebSocket-Extension' header field containing all used + extensions of the list specified in the corresponding request + header field. + + A valid websocket HTTP response could look like this: + +HTTP/1.1 101 Switching Protocols +Upgrade: websocket +Connection: Upgrade +Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= + + To upgrade a connection to a websocket the _libmicrohttpd_ws_ +provides some helper functions for the 'access_handler' callback +function: + + * 'MHD_websocket_check_http_version()' checks whether the HTTP + version is 1.1 or above. + + * 'MHD_websocket_check_connection_header()' checks whether the value + of the 'Connection' request header field contains an "Upgrade" + token (case-insensitive). + + * 'MHD_websocket_check_upgrade_header()' checks whether the value of + the 'Upgrade' request header field contains the "websocket" keyword + (case-insensitive). + + * 'MHD_websocket_check_version_header()' checks whether the value of + the 'Sec-WebSocket-Version' request header field is "13". + + * 'MHD_websocket_create_accept_header()' takes the value from the + 'Sec-WebSocket-Key' request header and calculates the value for the + 'Sec-WebSocket-Accept' response header field. + + The 'access_handler' example of the previous chapter can now be +extended with these helper functions to perform the websocket handshake: + +static enum MHD_Result +access_handler (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, + size_t *upload_data_size, + void **ptr) +{ + static int aptr; + struct MHD_Response *response; + int ret; + + (void) cls; /* Unused. Silent compiler warning. */ + (void) upload_data; /* Unused. Silent compiler warning. */ + (void) upload_data_size; /* Unused. Silent compiler warning. */ + + if (0 != strcmp (method, "GET")) + return MHD_NO; /* unexpected method */ + if (&aptr != *ptr) + { + /* do never respond on first call */ + *ptr = &aptr; + return MHD_YES; + } + *ptr = NULL; /* reset when done */ + + if (0 == strcmp (url, "/")) + { + /* Default page for visiting the server */ + struct MHD_Response *response = MHD_create_response_from_buffer ( + strlen (PAGE), + PAGE, + MHD_RESPMEM_PERSISTENT); + ret = MHD_queue_response (connection, + MHD_HTTP_OK, + response); + MHD_destroy_response (response); + } + else if (0 == strcmp (url, "/chat")) + { + char is_valid = 1; + const char* value = NULL; + char sec_websocket_accept[29]; + + if (0 != MHD_websocket_check_http_version (version)) + { + is_valid = 0; + } + value = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_CONNECTION); + if (0 != MHD_websocket_check_connection_header (value)) + { + is_valid = 0; + } + value = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_UPGRADE); + if (0 != MHD_websocket_check_upgrade_header (value)) + { + is_valid = 0; + } + value = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_SEC_WEBSOCKET_VERSION); + if (0 != MHD_websocket_check_version_header (value)) + { + is_valid = 0; + } + value = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_SEC_WEBSOCKET_KEY); + if (0 != MHD_websocket_create_accept_header (value, sec_websocket_accept)) + { + is_valid = 0; + } + + if (1 == is_valid) + { + /* upgrade the connection */ + response = MHD_create_response_for_upgrade (&upgrade_handler, + NULL); + MHD_add_response_header (response, + MHD_HTTP_HEADER_CONNECTION, + "Upgrade"); + MHD_add_response_header (response, + MHD_HTTP_HEADER_UPGRADE, + "websocket"); + MHD_add_response_header (response, + MHD_HTTP_HEADER_SEC_WEBSOCKET_ACCEPT, + sec_websocket_accept); + ret = MHD_queue_response (connection, + MHD_HTTP_SWITCHING_PROTOCOLS, + response); + MHD_destroy_response (response); + } + else + { + /* return error page */ + struct MHD_Response*response = MHD_create_response_from_buffer ( + strlen (PAGE_INVALID_WEBSOCKET_REQUEST), + PAGE_INVALID_WEBSOCKET_REQUEST, + MHD_RESPMEM_PERSISTENT); + ret = MHD_queue_response (connection, + MHD_HTTP_BAD_REQUEST, + response); + MHD_destroy_response (response); + } + } + else + { + struct MHD_Response*response = MHD_create_response_from_buffer ( + strlen (PAGE_NOT_FOUND), + PAGE_NOT_FOUND, + MHD_RESPMEM_PERSISTENT); + ret = MHD_queue_response (connection, + MHD_HTTP_NOT_FOUND, + response); + MHD_destroy_response (response); + } + + return ret; +} + + Please note that we skipped the check of the Host header field here, +because we don't know the host for this example. + +Decoding/encoding the websocket protocol with libmicrohttpd_ws +============================================================== + +Once the websocket connection is established you can receive/send frame +data with the low-level socket functions 'recv()' and 'send()'. The +frame data which goes over the low-level socket is encoded according to +the websocket protocol. To use received payload data, you need to +decode the frame data first. To send payload data, you need to encode +it into frame data first. + + _libmicrohttpd_ws_ provides several functions for encoding of payload +data and decoding of frame data: + + * 'MHD_websocket_decode()' decodes received frame data. The payload + data may be of any kind, depending upon what the client has sent. + So this decode function is used for all kind of frames and returns + the frame type along with the payload data. + + * 'MHD_websocket_encode_text()' encodes text. The text must be + encoded with UTF-8. + + * 'MHD_websocket_encode_binary()' encodes binary data. + + * 'MHD_websocket_encode_ping()' encodes a ping request to check + whether the websocket is still valid and to test latency. + + * 'MHD_websocket_encode_ping()' encodes a pong response to answer a + received ping request. + + * 'MHD_websocket_encode_close()' encodes a close request. + + * 'MHD_websocket_free()' frees data returned by the encode/decode + functions. + + Since you could receive or send fragmented data (i. e. due to a too +small buffer passed to 'recv') all of these encode/decode functions +require a pointer to a 'struct MHD_WebSocketStream' passed as argument. +In this structure _libmicrohttpd_ws_ stores information about +encoding/decoding of the particular websocket. For each websocket you +need a unique 'struct MHD_WebSocketStream' to encode/decode with this +library. + + To create or destroy 'struct MHD_WebSocketStream' we have additional +functions: + + * 'MHD_websocket_stream_init()' allocates and initializes a new + 'struct MHD_WebSocketStream'. You can specify some options here to + alter the behavior of the websocket stream. + + * 'MHD_websocket_stream_free()' frees a previously allocated 'struct + MHD_WebSocketStream'. + + With these encode/decode functions we can improve our +'upgrade_handler' callback function from an earlier example to a working +websocket: + +static void +upgrade_handler (void *cls, + struct MHD_Connection *connection, + void *req_cls, + const char *extra_in, + size_t extra_in_size, + MHD_socket fd, + struct MHD_UpgradeResponseHandle *urh) +{ + /* make the socket blocking (operating-system-dependent code) */ + make_blocking (fd); + + /* create a websocket stream for this connection */ + struct MHD_WebSocketStream* ws; + int result = MHD_websocket_stream_init (&ws, + 0, + 0); + if (0 != result) + { + /* Couldn't create the websocket stream. + * So we close the socket and leave + */ + MHD_upgrade_action (urh, + MHD_UPGRADE_ACTION_CLOSE); + return; + } + + /* Let's wait for incoming data */ + const size_t buf_len = 256; + char buf[buf_len]; + ssize_t got; + while (MHD_WEBSOCKET_VALIDITY_VALID == MHD_websocket_stream_is_valid (ws)) + { + got = recv (fd, + buf, + buf_len, + 0); + if (0 >= got) + { + /* the TCP/IP socket has been closed */ + break; + } + + /* parse the entire received data */ + size_t buf_offset = 0; + while (buf_offset < (size_t) got) + { + size_t new_offset = 0; + char *frame_data = NULL; + size_t frame_len = 0; + int status = MHD_websocket_decode (ws, + buf + buf_offset, + ((size_t) got) - buf_offset, + &new_offset, + &frame_data, + &frame_len); + if (0 > status) + { + /* an error occurred and the connection must be closed */ + if (NULL != frame_data) + { + MHD_websocket_free (ws, frame_data); + } + break; + } + else + { + buf_offset += new_offset; + if (0 < status) + { + /* the frame is complete */ + switch (status) + { + case MHD_WEBSOCKET_STATUS_TEXT_FRAME: + /* The client has sent some text. + * We will display it and answer with a text frame. + */ + if (NULL != frame_data) + { + printf ("Received message: %s\n", frame_data); + MHD_websocket_free (ws, frame_data); + frame_data = NULL; + } + result = MHD_websocket_encode_text (ws, + "Hello", + 5, /* length of "Hello" */ + 0, + &frame_data, + &frame_len, + NULL); + if (0 == result) + { + send_all (fd, + frame_data, + frame_len); + } + break; + + case MHD_WEBSOCKET_STATUS_CLOSE_FRAME: + /* if we receive a close frame, we will respond with one */ + MHD_websocket_free (ws, + frame_data); + frame_data = NULL; + + result = MHD_websocket_encode_close (ws, + 0, + NULL, + 0, + &frame_data, + &frame_len); + if (0 == result) + { + send_all (fd, + frame_data, + frame_len); + } + break; + + case MHD_WEBSOCKET_STATUS_PING_FRAME: + /* if we receive a ping frame, we will respond */ + /* with the corresponding pong frame */ + { + char *pong = NULL; + size_t pong_len = 0; + result = MHD_websocket_encode_pong (ws, + frame_data, + frame_len, + &pong, + &pong_len); + if (0 == result) + { + send_all (fd, + pong, + pong_len); + } + MHD_websocket_free (ws, + pong); + } + break; + + default: + /* Other frame types are ignored + * in this minimal example. + * This is valid, because they become + * automatically skipped if we receive them unexpectedly + */ + break; + } + } + if (NULL != frame_data) + { + MHD_websocket_free (ws, frame_data); + } + } + } + } + + /* free the websocket stream */ + MHD_websocket_stream_free (ws); + + /* close the socket when it is not needed anymore */ + MHD_upgrade_action (urh, + MHD_UPGRADE_ACTION_CLOSE); +} + +/* This helper function is used for the case that + * we need to resend some data + */ +static void +send_all (MHD_socket fd, + const char *buf, + size_t len) +{ + ssize_t ret; + size_t off; + + for (off = 0; off < len; off += ret) + { + ret = send (fd, + &buf[off], + (int) (len - off), + 0); + if (0 > ret) + { + if (EAGAIN == errno) + { + ret = 0; + continue; + } + break; + } + if (0 == ret) + break; + } +} + +/* This helper function contains operating-system-dependent code and + * is used to make a socket blocking. + */ +static void +make_blocking (MHD_socket fd) +{ +#if defined(MHD_POSIX_SOCKETS) + int flags; + + flags = fcntl (fd, F_GETFL); + if (-1 == flags) + return; + if ((flags & ~O_NONBLOCK) != flags) + if (-1 == fcntl (fd, F_SETFL, flags & ~O_NONBLOCK)) + abort (); +#elif defined(MHD_WINSOCK_SOCKETS) + unsigned long flags = 0; + + ioctlsocket (fd, FIONBIO, &flags); +#endif /* MHD_WINSOCK_SOCKETS */ +} + + + Please note that the websocket in this example is only half-duplex. +It waits until the blocking 'recv()' call returns and only does then +something. In this example all frame types are decoded by +_libmicrohttpd_ws_, but we only do something when a text, ping or close +frame is received. Binary and pong frames are ignored in our code. +This is legit, because the server is only required to implement at least +support for ping frame or close frame (the other frame types could be +skipped in theory, because they don't require an answer). The pong +frame doesn't require an answer and whether text frames or binary frames +get an answer simply belongs to your server application. So this is a +valid minimal example. + + Until this point you've learned everything you need to basically use +websockets with _libmicrohttpd_ and _libmicrohttpd_ws_. These libraries +offer much more functions for some specific cases. + + The further chapters of this tutorial focus on some specific problems +and the client site programming. + +Using full-duplex websockets +============================ + +To use full-duplex websockets you can simply create two threads per +websocket connection. One of these threads is used for receiving data +with a blocking 'recv()' call and the other thread is triggered by the +application internal codes and sends the data. + + A full-duplex websocket example is implemented in the example file +'websocket_chatserver_example.c'. + +Error handling +============== + +The most functions of _libmicrohttpd_ws_ return a value of 'enum +MHD_WEBSOCKET_STATUS'. The values of this enumeration can be converted +into an integer and have an easy interpretation: + + * If the value is less than zero an error occurred and the call has + failed. Check the enumeration values for more specific + information. + + * If the value is equal to zero, the call succeeded. + + * If the value is greater than zero, the call succeeded and the value + specifies the decoded frame type. Currently positive values are + only returned by 'MHD_websocket_decode()' (of the functions with + this return enumeration type). + + A websocket stream can also get broken when invalid frame data is +received. Also the other site could send a close frame which puts the +stream into a state where it may not be used for regular communication. +Whether a stream has become broken, can be checked with +'MHD_websocket_stream_is_valid()'. + +Fragmentation +============= + +In addition to the regular TCP/IP fragmentation the websocket protocol +also supports fragmentation. Fragmentation could be used for continuous +payload data such as video data from a webcam. Whether or not you want +to receive fragmentation is specified upon initialization of the +websocket stream. If you pass 'MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS' in +the flags parameter of 'MHD_websocket_stream_init()' then you can +receive fragments. If you don't pass this flag (in the most cases you +just pass zero as flags) then you don't want to handle fragments on your +own. _libmicrohttpd_ws_ removes then the fragmentation for you in the +background. You only get the completely assembled frames. + + Upon encoding you specify whether or not you want to create a +fragmented frame by passing a flag to the corresponding encode function. +Only 'MHD_websocket_encode_text()' and 'MHD_websocket_encode_binary()' +can be used for fragmentation, because the other frame types may not be +fragmented. Encoding fragmented frames is independent of the +'MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS' flag upon initialization. + +Quick guide to websockets in JavaScript +======================================= + +Websockets are supported in all modern web browsers. You initialize a +websocket connection by creating an instance of the 'WebSocket' class +provided by the web browser. + + There are some simple rules for using websockets in the browser: + + * When you initialize the instance of the websocket class you must + pass an URL. The URL must either start with 'ws://' (for not + encrypted websocket protocol) or 'wss://' (for TLS-encrypted + websocket protocol). + + *IMPORTANT:* If your website is accessed via 'https://' then you + are in a security context, which means that you are only allowed to + access other secure protocols. So you can only use 'wss://' for + websocket connections then. If you try to 'ws://' instead then + your websocket connection will automatically fail. + + * The WebSocket class uses events to handle the receiving of data. + JavaScript is per definition a single-threaded language so the + receiving events will never overlap. Sending is done directly by + calling a method of the instance of the WebSocket class. + + Here is a short example for receiving/sending data to the same host +as the website is running on: + + + + + +Websocket Demo + + + + + + + + +File: libmicrohttpd-tutorial.info, Node: Bibliography, Next: License text, Prev: Websockets, Up: Top + +Appendix A Bibliography +*********************** + +API reference +============= + + * The _GNU libmicrohttpd_ manual by Marco Maggi and Christian + Grothoff 2008 + + * All referenced RFCs can be found on the website of _The Internet + Engineering Task Force_ + + * _RFC 2616_: Fielding, R., Gettys, J., Mogul, J., Frystyk, H., and + T. Berners-Lee, "Hypertext Transfer Protocol - HTTP/1.1", RFC 2016, + January 1997. + + * _RFC 2617_: Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, + S., Leach, P., Luotonen, A., and L. Stewart, "HTTP Authentication: + Basic and Digest Access Authentication", RFC 2617, June 1999. + + * _RFC 6455_: Fette, I., Melnikov, A., "The WebSocket Protocol", RFC + 6455, December 2011. + + * A well-structured _HTML_ reference can be found on + + + For those readers understanding German or French, there is an + excellent document both for learning _HTML_ and for reference, + whose English version unfortunately has been discontinued. + and + + +File: libmicrohttpd-tutorial.info, Node: License text, Next: Example programs, Prev: Bibliography, Up: Top + +Appendix B GNU Free Documentation License +***************************************** + + Version 1.3, 3 November 2008 + + Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. + + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + 0. PREAMBLE + + The purpose of this License is to make a manual, textbook, or other + functional and useful document "free" in the sense of freedom: to + assure everyone the effective freedom to copy and redistribute it, + with or without modifying it, either commercially or + noncommercially. Secondarily, this License preserves for the + author and publisher a way to get credit for their work, while not + being considered responsible for modifications made by others. + + This License is a kind of "copyleft", which means that derivative + works of the document must themselves be free in the same sense. + It complements the GNU General Public License, which is a copyleft + license designed for free software. + + We have designed this License in order to use it for manuals for + free software, because free software needs free documentation: a + free program should come with manuals providing the same freedoms + that the software does. But this License is not limited to + software manuals; it can be used for any textual work, regardless + of subject matter or whether it is published as a printed book. We + recommend this License principally for works whose purpose is + instruction or reference. + + 1. APPLICABILITY AND DEFINITIONS + + This License applies to any manual or other work, in any medium, + that contains a notice placed by the copyright holder saying it can + be distributed under the terms of this License. Such a notice + grants a world-wide, royalty-free license, unlimited in duration, + to use that work under the conditions stated herein. The + "Document", below, refers to any such manual or work. Any member + of the public is a licensee, and is addressed as "you". You accept + the license if you copy, modify or distribute the work in a way + requiring permission under copyright law. + + A "Modified Version" of the Document means any work containing the + Document or a portion of it, either copied verbatim, or with + modifications and/or translated into another language. + + A "Secondary Section" is a named appendix or a front-matter section + of the Document that deals exclusively with the relationship of the + publishers or authors of the Document to the Document's overall + subject (or to related matters) and contains nothing that could + fall directly within that overall subject. (Thus, if the Document + is in part a textbook of mathematics, a Secondary Section may not + explain any mathematics.) The relationship could be a matter of + historical connection with the subject or with related matters, or + of legal, commercial, philosophical, ethical or political position + regarding them. + + The "Invariant Sections" are certain Secondary Sections whose + titles are designated, as being those of Invariant Sections, in the + notice that says that the Document is released under this License. + If a section does not fit the above definition of Secondary then it + is not allowed to be designated as Invariant. The Document may + contain zero Invariant Sections. If the Document does not identify + any Invariant Sections then there are none. + + The "Cover Texts" are certain short passages of text that are + listed, as Front-Cover Texts or Back-Cover Texts, in the notice + that says that the Document is released under this License. A + Front-Cover Text may be at most 5 words, and a Back-Cover Text may + be at most 25 words. + + A "Transparent" copy of the Document means a machine-readable copy, + represented in a format whose specification is available to the + general public, that is suitable for revising the document + straightforwardly with generic text editors or (for images composed + of pixels) generic paint programs or (for drawings) some widely + available drawing editor, and that is suitable for input to text + formatters or for automatic translation to a variety of formats + suitable for input to text formatters. A copy made in an otherwise + Transparent file format whose markup, or absence of markup, has + been arranged to thwart or discourage subsequent modification by + readers is not Transparent. An image format is not Transparent if + used for any substantial amount of text. A copy that is not + "Transparent" is called "Opaque". + + Examples of suitable formats for Transparent copies include plain + ASCII without markup, Texinfo input format, LaTeX input format, + SGML or XML using a publicly available DTD, and standard-conforming + simple HTML, PostScript or PDF designed for human modification. + Examples of transparent image formats include PNG, XCF and JPG. + Opaque formats include proprietary formats that can be read and + edited only by proprietary word processors, SGML or XML for which + the DTD and/or processing tools are not generally available, and + the machine-generated HTML, PostScript or PDF produced by some word + processors for output purposes only. + + The "Title Page" means, for a printed book, the title page itself, + plus such following pages as are needed to hold, legibly, the + material this License requires to appear in the title page. For + works in formats which do not have any title page as such, "Title + Page" means the text near the most prominent appearance of the + work's title, preceding the beginning of the body of the text. + + The "publisher" means any person or entity that distributes copies + of the Document to the public. + + A section "Entitled XYZ" means a named subunit of the Document + whose title either is precisely XYZ or contains XYZ in parentheses + following text that translates XYZ in another language. (Here XYZ + stands for a specific section name mentioned below, such as + "Acknowledgements", "Dedications", "Endorsements", or "History".) + To "Preserve the Title" of such a section when you modify the + Document means that it remains a section "Entitled XYZ" according + to this definition. + + The Document may include Warranty Disclaimers next to the notice + which states that this License applies to the Document. These + Warranty Disclaimers are considered to be included by reference in + this License, but only as regards disclaiming warranties: any other + implication that these Warranty Disclaimers may have is void and + has no effect on the meaning of this License. + + 2. VERBATIM COPYING + + You may copy and distribute the Document in any medium, either + commercially or noncommercially, provided that this License, the + copyright notices, and the license notice saying this License + applies to the Document are reproduced in all copies, and that you + add no other conditions whatsoever to those of this License. You + may not use technical measures to obstruct or control the reading + or further copying of the copies you make or distribute. However, + you may accept compensation in exchange for copies. If you + distribute a large enough number of copies you must also follow the + conditions in section 3. + + You may also lend copies, under the same conditions stated above, + and you may publicly display copies. + + 3. COPYING IN QUANTITY + + If you publish printed copies (or copies in media that commonly + have printed covers) of the Document, numbering more than 100, and + the Document's license notice requires Cover Texts, you must + enclose the copies in covers that carry, clearly and legibly, all + these Cover Texts: Front-Cover Texts on the front cover, and + Back-Cover Texts on the back cover. Both covers must also clearly + and legibly identify you as the publisher of these copies. The + front cover must present the full title with all words of the title + equally prominent and visible. You may add other material on the + covers in addition. Copying with changes limited to the covers, as + long as they preserve the title of the Document and satisfy these + conditions, can be treated as verbatim copying in other respects. + + If the required texts for either cover are too voluminous to fit + legibly, you should put the first ones listed (as many as fit + reasonably) on the actual cover, and continue the rest onto + adjacent pages. + + If you publish or distribute Opaque copies of the Document + numbering more than 100, you must either include a machine-readable + Transparent copy along with each Opaque copy, or state in or with + each Opaque copy a computer-network location from which the general + network-using public has access to download using public-standard + network protocols a complete Transparent copy of the Document, free + of added material. If you use the latter option, you must take + reasonably prudent steps, when you begin distribution of Opaque + copies in quantity, to ensure that this Transparent copy will + remain thus accessible at the stated location until at least one + year after the last time you distribute an Opaque copy (directly or + through your agents or retailers) of that edition to the public. + + It is requested, but not required, that you contact the authors of + the Document well before redistributing any large number of copies, + to give them a chance to provide you with an updated version of the + Document. + + 4. MODIFICATIONS + + You may copy and distribute a Modified Version of the Document + under the conditions of sections 2 and 3 above, provided that you + release the Modified Version under precisely this License, with the + Modified Version filling the role of the Document, thus licensing + distribution and modification of the Modified Version to whoever + possesses a copy of it. In addition, you must do these things in + the Modified Version: + + A. Use in the Title Page (and on the covers, if any) a title + distinct from that of the Document, and from those of previous + versions (which should, if there were any, be listed in the + History section of the Document). You may use the same title + as a previous version if the original publisher of that + version gives permission. + + B. List on the Title Page, as authors, one or more persons or + entities responsible for authorship of the modifications in + the Modified Version, together with at least five of the + principal authors of the Document (all of its principal + authors, if it has fewer than five), unless they release you + from this requirement. + + C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. + + D. Preserve all the copyright notices of the Document. + + E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. + + F. Include, immediately after the copyright notices, a license + notice giving the public permission to use the Modified + Version under the terms of this License, in the form shown in + the Addendum below. + + G. Preserve in that license notice the full lists of Invariant + Sections and required Cover Texts given in the Document's + license notice. + + H. Include an unaltered copy of this License. + + I. Preserve the section Entitled "History", Preserve its Title, + and add to it an item stating at least the title, year, new + authors, and publisher of the Modified Version as given on the + Title Page. If there is no section Entitled "History" in the + Document, create one stating the title, year, authors, and + publisher of the Document as given on its Title Page, then add + an item describing the Modified Version as stated in the + previous sentence. + + J. Preserve the network location, if any, given in the Document + for public access to a Transparent copy of the Document, and + likewise the network locations given in the Document for + previous versions it was based on. These may be placed in the + "History" section. You may omit a network location for a work + that was published at least four years before the Document + itself, or if the original publisher of the version it refers + to gives permission. + + K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section + all the substance and tone of each of the contributor + acknowledgements and/or dedications given therein. + + L. Preserve all the Invariant Sections of the Document, unaltered + in their text and in their titles. Section numbers or the + equivalent are not considered part of the section titles. + + M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. + + N. Do not retitle any existing section to be Entitled + "Endorsements" or to conflict in title with any Invariant + Section. + + O. Preserve any Warranty Disclaimers. + + If the Modified Version includes new front-matter sections or + appendices that qualify as Secondary Sections and contain no + material copied from the Document, you may at your option designate + some or all of these sections as invariant. To do this, add their + titles to the list of Invariant Sections in the Modified Version's + license notice. These titles must be distinct from any other + section titles. + + You may add a section Entitled "Endorsements", provided it contains + nothing but endorsements of your Modified Version by various + parties--for example, statements of peer review or that the text + has been approved by an organization as the authoritative + definition of a standard. + + You may add a passage of up to five words as a Front-Cover Text, + and a passage of up to 25 words as a Back-Cover Text, to the end of + the list of Cover Texts in the Modified Version. Only one passage + of Front-Cover Text and one of Back-Cover Text may be added by (or + through arrangements made by) any one entity. If the Document + already includes a cover text for the same cover, previously added + by you or by arrangement made by the same entity you are acting on + behalf of, you may not add another; but you may replace the old + one, on explicit permission from the previous publisher that added + the old one. + + The author(s) and publisher(s) of the Document do not by this + License give permission to use their names for publicity for or to + assert or imply endorsement of any Modified Version. + + 5. COMBINING DOCUMENTS + + You may combine the Document with other documents released under + this License, under the terms defined in section 4 above for + modified versions, provided that you include in the combination all + of the Invariant Sections of all of the original documents, + unmodified, and list them all as Invariant Sections of your + combined work in its license notice, and that you preserve all + their Warranty Disclaimers. + + The combined work need only contain one copy of this License, and + multiple identical Invariant Sections may be replaced with a single + copy. If there are multiple Invariant Sections with the same name + but different contents, make the title of each such section unique + by adding at the end of it, in parentheses, the name of the + original author or publisher of that section if known, or else a + unique number. Make the same adjustment to the section titles in + the list of Invariant Sections in the license notice of the + combined work. + + In the combination, you must combine any sections Entitled + "History" in the various original documents, forming one section + Entitled "History"; likewise combine any sections Entitled + "Acknowledgements", and any sections Entitled "Dedications". You + must delete all sections Entitled "Endorsements." + + 6. COLLECTIONS OF DOCUMENTS + + You may make a collection consisting of the Document and other + documents released under this License, and replace the individual + copies of this License in the various documents with a single copy + that is included in the collection, provided that you follow the + rules of this License for verbatim copying of each of the documents + in all other respects. + + You may extract a single document from such a collection, and + distribute it individually under this License, provided you insert + a copy of this License into the extracted document, and follow this + License in all other respects regarding verbatim copying of that + document. + + 7. AGGREGATION WITH INDEPENDENT WORKS + + A compilation of the Document or its derivatives with other + separate and independent documents or works, in or on a volume of a + storage or distribution medium, is called an "aggregate" if the + copyright resulting from the compilation is not used to limit the + legal rights of the compilation's users beyond what the individual + works permit. When the Document is included in an aggregate, this + License does not apply to the other works in the aggregate which + are not themselves derivative works of the Document. + + If the Cover Text requirement of section 3 is applicable to these + copies of the Document, then if the Document is less than one half + of the entire aggregate, the Document's Cover Texts may be placed + on covers that bracket the Document within the aggregate, or the + electronic equivalent of covers if the Document is in electronic + form. Otherwise they must appear on printed covers that bracket + the whole aggregate. + + 8. TRANSLATION + + Translation is considered a kind of modification, so you may + distribute translations of the Document under the terms of section + 4. Replacing Invariant Sections with translations requires special + permission from their copyright holders, but you may include + translations of some or all Invariant Sections in addition to the + original versions of these Invariant Sections. You may include a + translation of this License, and all the license notices in the + Document, and any Warranty Disclaimers, provided that you also + include the original English version of this License and the + original versions of those notices and disclaimers. In case of a + disagreement between the translation and the original version of + this License or a notice or disclaimer, the original version will + prevail. + + If a section in the Document is Entitled "Acknowledgements", + "Dedications", or "History", the requirement (section 4) to + Preserve its Title (section 1) will typically require changing the + actual title. + + 9. TERMINATION + + You may not copy, modify, sublicense, or distribute the Document + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense, or distribute it is void, + and will automatically terminate your rights under this License. + + However, if you cease all violation of this License, then your + license from a particular copyright holder is reinstated (a) + provisionally, unless and until the copyright holder explicitly and + finally terminates your license, and (b) permanently, if the + copyright holder fails to notify you of the violation by some + reasonable means prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is + reinstated permanently if the copyright holder notifies you of the + violation by some reasonable means, this is the first time you have + received notice of violation of this License (for any work) from + that copyright holder, and you cure the violation prior to 30 days + after your receipt of the notice. + + Termination of your rights under this section does not terminate + the licenses of parties who have received copies or rights from you + under this License. If your rights have been terminated and not + permanently reinstated, receipt of a copy of some or all of the + same material does not give you any rights to use it. + + 10. FUTURE REVISIONS OF THIS LICENSE + + The Free Software Foundation may publish new, revised versions of + the GNU Free Documentation License from time to time. Such new + versions will be similar in spirit to the present version, but may + differ in detail to address new problems or concerns. See + . + + Each version of the License is given a distinguishing version + number. If the Document specifies that a particular numbered + version of this License "or any later version" applies to it, you + have the option of following the terms and conditions either of + that specified version or of any later version that has been + published (not as a draft) by the Free Software Foundation. If the + Document does not specify a version number of this License, you may + choose any version ever published (not as a draft) by the Free + Software Foundation. If the Document specifies that a proxy can + decide which future versions of this License can be used, that + proxy's public statement of acceptance of a version permanently + authorizes you to choose that version for the Document. + + 11. RELICENSING + + "Massive Multiauthor Collaboration Site" (or "MMC Site") means any + World Wide Web server that publishes copyrightable works and also + provides prominent facilities for anybody to edit those works. A + public wiki that anybody can edit is an example of such a server. + A "Massive Multiauthor Collaboration" (or "MMC") contained in the + site means any set of copyrightable works thus published on the MMC + site. + + "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 + license published by Creative Commons Corporation, a not-for-profit + corporation with a principal place of business in San Francisco, + California, as well as future copyleft versions of that license + published by that same organization. + + "Incorporate" means to publish or republish a Document, in whole or + in part, as part of another Document. + + An MMC is "eligible for relicensing" if it is licensed under this + License, and if all works that were first published under this + License somewhere other than this MMC, and subsequently + incorporated in whole or in part into the MMC, (1) had no cover + texts or invariant sections, and (2) were thus incorporated prior + to November 1, 2008. + + The operator of an MMC Site may republish an MMC contained in the + site under CC-BY-SA on the same site at any time before August 1, + 2009, provided the MMC is eligible for relicensing. + +ADDENDUM: How to use this License for your documents +==================================================== + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and license +notices just after the title page: + + Copyright (C) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. A copy of the license is included in the section entitled ``GNU + Free Documentation License''. + + If you have Invariant Sections, Front-Cover Texts and Back-Cover +Texts, replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with + the Front-Cover Texts being LIST, and with the Back-Cover Texts + being LIST. + + If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + + If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of free +software license, such as the GNU General Public License, to permit +their use in free software. + + +File: libmicrohttpd-tutorial.info, Node: Example programs, Prev: License text, Up: Top + +Appendix C Example programs +*************************** + +* Menu: + +* hellobrowser.c:: +* logging.c:: +* responseheaders.c:: +* basicauthentication.c:: +* simplepost.c:: +* largepost.c:: +* sessions.c:: +* tlsauthentication.c:: +* websocket.c:: + + +File: libmicrohttpd-tutorial.info, Node: hellobrowser.c, Next: logging.c, Up: Example programs + +C.1 hellobrowser.c +================== + + /* Feel free to use this example code in any way + you see fit (Public Domain) */ + + #include + #ifndef _WIN32 + #include + #include + #else + #include + #endif + #include + #include + #include + + #define PORT 8888 + + static enum MHD_Result + answer_to_connection (void *cls, struct MHD_Connection *connection, + const char *url, const char *method, + const char *version, const char *upload_data, + size_t *upload_data_size, void **req_cls) + { + const char *page = "Hello, browser!"; + struct MHD_Response *response; + enum MHD_Result ret; + (void) cls; /* Unused. Silent compiler warning. */ + (void) url; /* Unused. Silent compiler warning. */ + (void) method; /* Unused. Silent compiler warning. */ + (void) version; /* Unused. Silent compiler warning. */ + (void) upload_data; /* Unused. Silent compiler warning. */ + (void) upload_data_size; /* Unused. Silent compiler warning. */ + (void) req_cls; /* Unused. Silent compiler warning. */ + + response = MHD_create_response_from_buffer_static (strlen (page), page); + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + MHD_destroy_response (response); + + return ret; + } + + + int + main (void) + { + struct MHD_Daemon *daemon; + + daemon = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD, + PORT, NULL, NULL, + &answer_to_connection, NULL, MHD_OPTION_END); + if (NULL == daemon) + return 1; + + (void) getchar (); + + MHD_stop_daemon (daemon); + return 0; + } + + +File: libmicrohttpd-tutorial.info, Node: logging.c, Next: responseheaders.c, Prev: hellobrowser.c, Up: Example programs + +C.2 logging.c +============= + + /* Feel free to use this example code in any way + you see fit (Public Domain) */ + + #include + #ifndef _WIN32 + #include + #include + #else + #include + #endif + #include + #include + + #define PORT 8888 + + + static enum MHD_Result + print_out_key (void *cls, enum MHD_ValueKind kind, const char *key, + const char *value) + { + (void) cls; /* Unused. Silent compiler warning. */ + (void) kind; /* Unused. Silent compiler warning. */ + printf ("%s: %s\n", key, value); + return MHD_YES; + } + + + static enum MHD_Result + answer_to_connection (void *cls, struct MHD_Connection *connection, + const char *url, const char *method, + const char *version, const char *upload_data, + size_t *upload_data_size, void **req_cls) + { + (void) cls; /* Unused. Silent compiler warning. */ + (void) version; /* Unused. Silent compiler warning. */ + (void) upload_data; /* Unused. Silent compiler warning. */ + (void) upload_data_size; /* Unused. Silent compiler warning. */ + (void) req_cls; /* Unused. Silent compiler warning. */ + printf ("New %s request for %s using version %s\n", method, url, version); + + MHD_get_connection_values (connection, MHD_HEADER_KIND, print_out_key, + NULL); + + return MHD_NO; + } + + + int + main (void) + { + struct MHD_Daemon *daemon; + + daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD, PORT, NULL, NULL, + &answer_to_connection, NULL, MHD_OPTION_END); + if (NULL == daemon) + return 1; + + (void) getchar (); + + MHD_stop_daemon (daemon); + return 0; + } + + +File: libmicrohttpd-tutorial.info, Node: responseheaders.c, Next: basicauthentication.c, Prev: logging.c, Up: Example programs + +C.3 responseheaders.c +===================== + + /* Feel free to use this example code in any way + you see fit (Public Domain) */ + + #include + #ifndef _WIN32 + #include + #include + #else + #include + #endif + #include + #include + #include + #include + #include + #include + + #define PORT 8888 + #define FILENAME "picture.png" + #define MIMETYPE "image/png" + + static enum MHD_Result + answer_to_connection (void *cls, struct MHD_Connection *connection, + const char *url, const char *method, + const char *version, const char *upload_data, + size_t *upload_data_size, void **req_cls) + { + struct MHD_Response *response; + int fd; + enum MHD_Result ret; + struct stat sbuf; + (void) cls; /* Unused. Silent compiler warning. */ + (void) url; /* Unused. Silent compiler warning. */ + (void) version; /* Unused. Silent compiler warning. */ + (void) upload_data; /* Unused. Silent compiler warning. */ + (void) upload_data_size; /* Unused. Silent compiler warning. */ + (void) req_cls; /* Unused. Silent compiler warning. */ + + if (0 != strcmp (method, "GET")) + return MHD_NO; + + if ( (-1 == (fd = open (FILENAME, O_RDONLY))) || + (0 != fstat (fd, &sbuf)) ) + { + const char *errorstr = + "An internal server error has occurred!\ + "; + /* error accessing file */ + if (fd != -1) + (void) close (fd); + response = + MHD_create_response_from_buffer_static (strlen (errorstr), errorstr); + if (NULL != response) + { + ret = + MHD_queue_response (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, + response); + MHD_destroy_response (response); + + return ret; + } + else + return MHD_NO; + } + response = + MHD_create_response_from_fd_at_offset64 ((size_t) sbuf.st_size, + fd, + 0); + if (MHD_YES != + MHD_add_response_header (response, + MHD_HTTP_HEADER_CONTENT_TYPE, + MIMETYPE)) + { + fprintf (stderr, + "Failed to set content type header!\n"); + /* return response without content encoding anyway ... */ + } + ret = MHD_queue_response (connection, + MHD_HTTP_OK, + response); + MHD_destroy_response (response); + + return ret; + } + + + int + main (void) + { + struct MHD_Daemon *daemon; + + daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD, PORT, NULL, NULL, + &answer_to_connection, NULL, MHD_OPTION_END); + if (NULL == daemon) + return 1; + + (void) getchar (); + + MHD_stop_daemon (daemon); + + return 0; + } + + +File: libmicrohttpd-tutorial.info, Node: basicauthentication.c, Next: simplepost.c, Prev: responseheaders.c, Up: Example programs + +C.4 basicauthentication.c +========================= + + /* Feel free to use this example code in any way + you see fit (Public Domain) */ + + #include + #ifndef _WIN32 + #include + #include + #else + #include + #endif + #include + #include + #include + #include + #include + + #define PORT 8888 + + + static enum MHD_Result + answer_to_connection (void *cls, struct MHD_Connection *connection, + const char *url, const char *method, + const char *version, const char *upload_data, + size_t *upload_data_size, void **req_cls) + { + struct MHD_BasicAuthInfo *auth_info; + enum MHD_Result ret; + struct MHD_Response *response; + (void) cls; /* Unused. Silent compiler warning. */ + (void) url; /* Unused. Silent compiler warning. */ + (void) version; /* Unused. Silent compiler warning. */ + (void) upload_data; /* Unused. Silent compiler warning. */ + (void) upload_data_size; /* Unused. Silent compiler warning. */ + + if (0 != strcmp (method, "GET")) + return MHD_NO; + if (NULL == *req_cls) + { + *req_cls = connection; + return MHD_YES; + } + auth_info = MHD_basic_auth_get_username_password3 (connection); + if (NULL == auth_info) + { + static const char *page = + "Authorization required"; + response = MHD_create_response_from_buffer_static (strlen (page), page); + ret = MHD_queue_basic_auth_required_response3 (connection, + "admins", + MHD_YES, + response); + } + else if ((strlen ("root") != auth_info->username_len) || + (0 != memcmp (auth_info->username, "root", + auth_info->username_len)) || + /* The next check against NULL is optional, + * if 'password' is NULL then 'password_len' is always zero. */ + (NULL == auth_info->password) || + (strlen ("pa$$w0rd") != auth_info->password_len) || + (0 != memcmp (auth_info->password, "pa$$w0rd", + auth_info->password_len))) + { + static const char *page = + "Wrong username or password"; + response = MHD_create_response_from_buffer_static (strlen (page), page); + ret = MHD_queue_basic_auth_required_response3 (connection, + "admins", + MHD_YES, + response); + } + else + { + static const char *page = "A secret."; + response = MHD_create_response_from_buffer_static (strlen (page), page); + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + } + if (NULL != auth_info) + MHD_free (auth_info); + MHD_destroy_response (response); + return ret; + } + + + int + main (void) + { + struct MHD_Daemon *daemon; + + daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD, PORT, NULL, NULL, + &answer_to_connection, NULL, MHD_OPTION_END); + if (NULL == daemon) + return 1; + + (void) getchar (); + + MHD_stop_daemon (daemon); + return 0; + } + + +File: libmicrohttpd-tutorial.info, Node: simplepost.c, Next: largepost.c, Prev: basicauthentication.c, Up: Example programs + +C.5 simplepost.c +================ + + /* Feel free to use this example code in any way + you see fit (Public Domain) */ + + #include + #ifndef _WIN32 + #include + #include + #else + #include + #endif + #include + #include + #include + #include + + #if defined(_MSC_VER) && _MSC_VER + 0 <= 1800 + /* Substitution is OK while return value is not used */ + #define snprintf _snprintf + #endif + + #define PORT 8888 + #define POSTBUFFERSIZE 512 + #define MAXNAMESIZE 20 + #define MAXANSWERSIZE 512 + + #define GET 0 + #define POST 1 + + struct connection_info_struct + { + int connectiontype; + char *answerstring; + struct MHD_PostProcessor *postprocessor; + }; + + static const char *askpage = + "\n" + "What's your name, Sir?
\n" + "
\n" + "\n" + "\n" + ""; + + #define GREETINGPAGE \ + "

Welcome, %s!

" + + static const char *errorpage = + "This doesn't seem to be right."; + + + static enum MHD_Result + send_page (struct MHD_Connection *connection, const char *page) + { + enum MHD_Result ret; + struct MHD_Response *response; + + + response = MHD_create_response_from_buffer_static (strlen (page), page); + if (! response) + return MHD_NO; + + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + MHD_destroy_response (response); + + return ret; + } + + + static enum MHD_Result + iterate_post (void *coninfo_cls, enum MHD_ValueKind kind, const char *key, + const char *filename, const char *content_type, + const char *transfer_encoding, const char *data, uint64_t off, + size_t size) + { + struct connection_info_struct *con_info = coninfo_cls; + (void) kind; /* Unused. Silent compiler warning. */ + (void) filename; /* Unused. Silent compiler warning. */ + (void) content_type; /* Unused. Silent compiler warning. */ + (void) transfer_encoding; /* Unused. Silent compiler warning. */ + (void) off; /* Unused. Silent compiler warning. */ + + if (0 == strcmp (key, "name")) + { + if ((size > 0) && (size <= MAXNAMESIZE)) + { + char *answerstring; + answerstring = malloc (MAXANSWERSIZE); + if (! answerstring) + return MHD_NO; + + snprintf (answerstring, MAXANSWERSIZE, GREETINGPAGE, data); + con_info->answerstring = answerstring; + } + else + con_info->answerstring = NULL; + + return MHD_NO; + } + + return MHD_YES; + } + + + static void + request_completed (void *cls, struct MHD_Connection *connection, + void **req_cls, enum MHD_RequestTerminationCode toe) + { + struct connection_info_struct *con_info = *req_cls; + (void) cls; /* Unused. Silent compiler warning. */ + (void) connection; /* Unused. Silent compiler warning. */ + (void) toe; /* Unused. Silent compiler warning. */ + + if (NULL == con_info) + return; + + if (con_info->connectiontype == POST) + { + MHD_destroy_post_processor (con_info->postprocessor); + if (con_info->answerstring) + free (con_info->answerstring); + } + + free (con_info); + *req_cls = NULL; + } + + + static enum MHD_Result + answer_to_connection (void *cls, struct MHD_Connection *connection, + const char *url, const char *method, + const char *version, const char *upload_data, + size_t *upload_data_size, void **req_cls) + { + (void) cls; /* Unused. Silent compiler warning. */ + (void) url; /* Unused. Silent compiler warning. */ + (void) version; /* Unused. Silent compiler warning. */ + + if (NULL == *req_cls) + { + struct connection_info_struct *con_info; + + con_info = malloc (sizeof (struct connection_info_struct)); + if (NULL == con_info) + return MHD_NO; + con_info->answerstring = NULL; + + if (0 == strcmp (method, "POST")) + { + con_info->postprocessor = + MHD_create_post_processor (connection, POSTBUFFERSIZE, + iterate_post, (void *) con_info); + + if (NULL == con_info->postprocessor) + { + free (con_info); + return MHD_NO; + } + + con_info->connectiontype = POST; + } + else + con_info->connectiontype = GET; + + *req_cls = (void *) con_info; + + return MHD_YES; + } + + if (0 == strcmp (method, "GET")) + { + return send_page (connection, askpage); + } + + if (0 == strcmp (method, "POST")) + { + struct connection_info_struct *con_info = *req_cls; + + if (*upload_data_size != 0) + { + if (MHD_YES != + MHD_post_process (con_info->postprocessor, + upload_data, + *upload_data_size)) + return MHD_NO; + *upload_data_size = 0; + + return MHD_YES; + } + else if (NULL != con_info->answerstring) + return send_page (connection, con_info->answerstring); + } + + return send_page (connection, errorpage); + } + + + int + main (void) + { + struct MHD_Daemon *daemon; + + daemon = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD, + PORT, NULL, NULL, + &answer_to_connection, NULL, + MHD_OPTION_NOTIFY_COMPLETED, request_completed, + NULL, MHD_OPTION_END); + if (NULL == daemon) + return 1; + + (void) getchar (); + + MHD_stop_daemon (daemon); + + return 0; + } + + +File: libmicrohttpd-tutorial.info, Node: largepost.c, Next: sessions.c, Prev: simplepost.c, Up: Example programs + +C.6 largepost.c +=============== + + /* Feel free to use this example code in any way + you see fit (Public Domain) */ + + #include + #ifndef _WIN32 + #include + #include + #else + #include + #endif + #include + #include + #include + #include + + #if defined(_MSC_VER) && _MSC_VER + 0 <= 1800 + /* Substitution is OK while return value is not used */ + #define snprintf _snprintf + #endif + + #define PORT 8888 + #define POSTBUFFERSIZE 512 + #define MAXCLIENTS 2 + + enum ConnectionType + { + GET = 0, + POST = 1 + }; + + static unsigned int nr_of_uploading_clients = 0; + + + /** + * Information we keep per connection. + */ + struct connection_info_struct + { + enum ConnectionType connectiontype; + + /** + * Handle to the POST processing state. + */ + struct MHD_PostProcessor *postprocessor; + + /** + * File handle where we write uploaded data. + */ + FILE *fp; + + /** + * HTTP response body we will return, NULL if not yet known. + */ + const char *answerstring; + + /** + * HTTP status code we will return, 0 for undecided. + */ + unsigned int answercode; + }; + + + #define ASKPAGE \ + "\n" \ + "Upload a file, please!
\n" \ + "There are %u clients uploading at the moment.
\n" \ + "
\n" \ + "\n" \ + "\n" \ + "" + static const char *busypage = + "This server is busy, please try again later."; + static const char *completepage = + "The upload has been completed."; + static const char *errorpage = + "This doesn't seem to be right."; + static const char *servererrorpage = + "Invalid request."; + static const char *fileexistspage = + "This file already exists."; + static const char *fileioerror = + "IO error writing to disk."; + static const char *const postprocerror = + "ErrorError processing POST data"; + + + static enum MHD_Result + send_page (struct MHD_Connection *connection, + const char *page, + unsigned int status_code) + { + enum MHD_Result ret; + struct MHD_Response *response; + + response = MHD_create_response_from_buffer_static (strlen (page), page); + if (! response) + return MHD_NO; + if (MHD_YES != + MHD_add_response_header (response, + MHD_HTTP_HEADER_CONTENT_TYPE, + "text/html")) + { + fprintf (stderr, + "Failed to set content type header!\n"); + } + ret = MHD_queue_response (connection, + status_code, + response); + MHD_destroy_response (response); + + return ret; + } + + + static enum MHD_Result + iterate_post (void *coninfo_cls, + enum MHD_ValueKind kind, + const char *key, + const char *filename, + const char *content_type, + const char *transfer_encoding, + const char *data, + uint64_t off, + size_t size) + { + struct connection_info_struct *con_info = coninfo_cls; + FILE *fp; + (void) kind; /* Unused. Silent compiler warning. */ + (void) content_type; /* Unused. Silent compiler warning. */ + (void) transfer_encoding; /* Unused. Silent compiler warning. */ + (void) off; /* Unused. Silent compiler warning. */ + + if (0 != strcmp (key, "file")) + { + con_info->answerstring = servererrorpage; + con_info->answercode = MHD_HTTP_BAD_REQUEST; + return MHD_YES; + } + + if (! con_info->fp) + { + if (0 != con_info->answercode) /* something went wrong */ + return MHD_YES; + if (NULL != (fp = fopen (filename, "rb"))) + { + fclose (fp); + con_info->answerstring = fileexistspage; + con_info->answercode = MHD_HTTP_FORBIDDEN; + return MHD_YES; + } + /* NOTE: This is technically a race with the 'fopen()' above, + but there is no easy fix, short of moving to open(O_EXCL) + instead of using fopen(). For the example, we do not care. */ + con_info->fp = fopen (filename, "ab"); + if (! con_info->fp) + { + con_info->answerstring = fileioerror; + con_info->answercode = MHD_HTTP_INTERNAL_SERVER_ERROR; + return MHD_YES; + } + } + + if (size > 0) + { + if (! fwrite (data, sizeof (char), size, con_info->fp)) + { + con_info->answerstring = fileioerror; + con_info->answercode = MHD_HTTP_INTERNAL_SERVER_ERROR; + return MHD_YES; + } + } + + return MHD_YES; + } + + + static void + request_completed (void *cls, + struct MHD_Connection *connection, + void **req_cls, + enum MHD_RequestTerminationCode toe) + { + struct connection_info_struct *con_info = *req_cls; + (void) cls; /* Unused. Silent compiler warning. */ + (void) connection; /* Unused. Silent compiler warning. */ + (void) toe; /* Unused. Silent compiler warning. */ + + if (NULL == con_info) + return; + + if (con_info->connectiontype == POST) + { + if (NULL != con_info->postprocessor) + { + MHD_destroy_post_processor (con_info->postprocessor); + nr_of_uploading_clients--; + } + + if (con_info->fp) + fclose (con_info->fp); + } + + free (con_info); + *req_cls = NULL; + } + + + static enum MHD_Result + answer_to_connection (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, + size_t *upload_data_size, + void **req_cls) + { + (void) cls; /* Unused. Silent compiler warning. */ + (void) url; /* Unused. Silent compiler warning. */ + (void) version; /* Unused. Silent compiler warning. */ + + if (NULL == *req_cls) + { + /* First call, setup data structures */ + struct connection_info_struct *con_info; + + if (nr_of_uploading_clients >= MAXCLIENTS) + return send_page (connection, + busypage, + MHD_HTTP_SERVICE_UNAVAILABLE); + + con_info = malloc (sizeof (struct connection_info_struct)); + if (NULL == con_info) + return MHD_NO; + con_info->answercode = 0; /* none yet */ + con_info->fp = NULL; + + if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) + { + con_info->postprocessor = + MHD_create_post_processor (connection, + POSTBUFFERSIZE, + &iterate_post, + (void *) con_info); + + if (NULL == con_info->postprocessor) + { + free (con_info); + return MHD_NO; + } + + nr_of_uploading_clients++; + + con_info->connectiontype = POST; + } + else + { + con_info->connectiontype = GET; + } + + *req_cls = (void *) con_info; + + return MHD_YES; + } + + if (0 == strcmp (method, MHD_HTTP_METHOD_GET)) + { + /* We just return the standard form for uploads on all GET requests */ + char buffer[1024]; + + snprintf (buffer, + sizeof (buffer), + ASKPAGE, + nr_of_uploading_clients); + return send_page (connection, + buffer, + MHD_HTTP_OK); + } + + if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) + { + struct connection_info_struct *con_info = *req_cls; + + if (0 != *upload_data_size) + { + /* Upload not yet done */ + if (0 != con_info->answercode) + { + /* we already know the answer, skip rest of upload */ + *upload_data_size = 0; + return MHD_YES; + } + if (MHD_YES != + MHD_post_process (con_info->postprocessor, + upload_data, + *upload_data_size)) + { + con_info->answerstring = postprocerror; + con_info->answercode = MHD_HTTP_INTERNAL_SERVER_ERROR; + } + *upload_data_size = 0; + + return MHD_YES; + } + /* Upload finished */ + if (NULL != con_info->fp) + { + fclose (con_info->fp); + con_info->fp = NULL; + } + if (0 == con_info->answercode) + { + /* No errors encountered, declare success */ + con_info->answerstring = completepage; + con_info->answercode = MHD_HTTP_OK; + } + return send_page (connection, + con_info->answerstring, + con_info->answercode); + } + + /* Note a GET or a POST, generate error */ + return send_page (connection, + errorpage, + MHD_HTTP_BAD_REQUEST); + } + + + int + main (void) + { + struct MHD_Daemon *daemon; + + daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD, + PORT, NULL, NULL, + &answer_to_connection, NULL, + MHD_OPTION_NOTIFY_COMPLETED, &request_completed, + NULL, + MHD_OPTION_END); + if (NULL == daemon) + { + fprintf (stderr, + "Failed to start daemon.\n"); + return 1; + } + (void) getchar (); + MHD_stop_daemon (daemon); + return 0; + } + + +File: libmicrohttpd-tutorial.info, Node: sessions.c, Next: tlsauthentication.c, Prev: largepost.c, Up: Example programs + +C.7 sessions.c +============== + + /* Feel free to use this example code in any way + you see fit (Public Domain) */ + + #include + #include + #include + #include + #include + #include + + /** + * Invalid method page. + */ + #define METHOD_ERROR \ + "Illegal requestGo away." + + /** + * Invalid URL page. + */ + #define NOT_FOUND_ERROR \ + "Not foundGo away." + + /** + * Front page. (/) + */ + #define MAIN_PAGE \ + "Welcome
What is your name? " + + #define FORM_V1 MAIN_PAGE + + /** + * Second page. (/2) + */ + #define SECOND_PAGE \ + "Tell me moreprevious %s, what is your job? " + + #define FORM_V1_V2 SECOND_PAGE + + /** + * Second page (/S) + */ + #define SUBMIT_PAGE \ + "Ready to submit?previous " + + /** + * Last page. + */ + #define LAST_PAGE \ + "Thank youThank you." + + /** + * Name of our cookie. + */ + #define COOKIE_NAME "session" + + + /** + * State we keep for each user/session/browser. + */ + struct Session + { + /** + * We keep all sessions in a linked list. + */ + struct Session *next; + + /** + * Unique ID for this session. + */ + char sid[33]; + + /** + * Reference counter giving the number of connections + * currently using this session. + */ + unsigned int rc; + + /** + * Time when this session was last active. + */ + time_t start; + + /** + * String submitted via form. + */ + char value_1[64]; + + /** + * Another value submitted via form. + */ + char value_2[64]; + + }; + + + /** + * Data kept per request. + */ + struct Request + { + + /** + * Associated session. + */ + struct Session *session; + + /** + * Post processor handling form data (IF this is + * a POST request). + */ + struct MHD_PostProcessor *pp; + + /** + * URL to serve in response to this POST (if this request + * was a 'POST') + */ + const char *post_url; + + }; + + + /** + * Linked list of all active sessions. Yes, O(n) but a + * hash table would be overkill for a simple example... + */ + static struct Session *sessions; + + + /** + * Return the session handle for this connection, or + * create one if this is a new user. + */ + static struct Session * + get_session (struct MHD_Connection *connection) + { + struct Session *ret; + const char *cookie; + + cookie = MHD_lookup_connection_value (connection, + MHD_COOKIE_KIND, + COOKIE_NAME); + if (cookie != NULL) + { + /* find existing session */ + ret = sessions; + while (NULL != ret) + { + if (0 == strcmp (cookie, ret->sid)) + break; + ret = ret->next; + } + if (NULL != ret) + { + ret->rc++; + return ret; + } + } + /* create fresh session */ + ret = calloc (1, sizeof (struct Session)); + if (NULL == ret) + { + fprintf (stderr, "calloc error: %s\n", strerror (errno)); + return NULL; + } + /* not a super-secure way to generate a random session ID, + but should do for a simple example... */ + snprintf (ret->sid, + sizeof (ret->sid), + "%X%X%X%X", + (unsigned int) rand (), + (unsigned int) rand (), + (unsigned int) rand (), + (unsigned int) rand ()); + ret->rc++; + ret->start = time (NULL); + ret->next = sessions; + sessions = ret; + return ret; + } + + + /** + * Type of handler that generates a reply. + * + * @param cls content for the page (handler-specific) + * @param mime mime type to use + * @param session session information + * @param connection connection to process + * @param #MHD_YES on success, #MHD_NO on failure + */ + typedef enum MHD_Result (*PageHandler)(const void *cls, + const char *mime, + struct Session *session, + struct MHD_Connection *connection); + + + /** + * Entry we generate for each page served. + */ + struct Page + { + /** + * Acceptable URL for this page. + */ + const char *url; + + /** + * Mime type to set for the page. + */ + const char *mime; + + /** + * Handler to call to generate response. + */ + PageHandler handler; + + /** + * Extra argument to handler. + */ + const void *handler_cls; + }; + + + /** + * Add header to response to set a session cookie. + * + * @param session session to use + * @param response response to modify + */ + static void + add_session_cookie (struct Session *session, + struct MHD_Response *response) + { + char cstr[256]; + snprintf (cstr, + sizeof (cstr), + "%s=%s", + COOKIE_NAME, + session->sid); + if (MHD_NO == + MHD_add_response_header (response, + MHD_HTTP_HEADER_SET_COOKIE, + cstr)) + { + fprintf (stderr, + "Failed to set session cookie header!\n"); + } + } + + + /** + * Handler that returns a simple static HTTP page that + * is passed in via 'cls'. + * + * @param cls a 'const char *' with the HTML webpage to return + * @param mime mime type to use + * @param session session handle + * @param connection connection to use + */ + static enum MHD_Result + serve_simple_form (const void *cls, + const char *mime, + struct Session *session, + struct MHD_Connection *connection) + { + enum MHD_Result ret; + const char *form = cls; + struct MHD_Response *response; + + /* return static form */ + response = MHD_create_response_from_buffer_static (strlen (form), form); + add_session_cookie (session, response); + if (MHD_YES != + MHD_add_response_header (response, + MHD_HTTP_HEADER_CONTENT_TYPE, + mime)) + { + fprintf (stderr, + "Failed to set content type header!\n"); + /* return response without content type anyway ... */ + } + ret = MHD_queue_response (connection, + MHD_HTTP_OK, + response); + MHD_destroy_response (response); + return ret; + } + + + /** + * Handler that adds the 'v1' value to the given HTML code. + * + * @param cls a 'const char *' with the HTML webpage to return + * @param mime mime type to use + * @param session session handle + * @param connection connection to use + */ + static enum MHD_Result + fill_v1_form (const void *cls, + const char *mime, + struct Session *session, + struct MHD_Connection *connection) + { + enum MHD_Result ret; + char *reply; + struct MHD_Response *response; + int reply_len; + (void) cls; /* Unused */ + + /* Emulate 'asprintf' */ + reply_len = snprintf (NULL, 0, FORM_V1, session->value_1); + if (0 > reply_len) + return MHD_NO; /* Internal error */ + + reply = (char *) malloc ((size_t) ((size_t) reply_len + 1)); + if (NULL == reply) + return MHD_NO; /* Out-of-memory error */ + + if (reply_len != snprintf (reply, + (size_t) (((size_t) reply_len) + 1), + FORM_V1, + session->value_1)) + { + free (reply); + return MHD_NO; /* printf error */ + } + + /* return static form */ + response = + MHD_create_response_from_buffer_with_free_callback ((size_t) reply_len, + (void *) reply, + &free); + if (NULL != response) + { + add_session_cookie (session, response); + if (MHD_YES != + MHD_add_response_header (response, + MHD_HTTP_HEADER_CONTENT_TYPE, + mime)) + { + fprintf (stderr, + "Failed to set content type header!\n"); + /* return response without content type anyway ... */ + } + ret = MHD_queue_response (connection, + MHD_HTTP_OK, + response); + MHD_destroy_response (response); + } + else + { + free (reply); + ret = MHD_NO; + } + return ret; + } + + + /** + * Handler that adds the 'v1' and 'v2' values to the given HTML code. + * + * @param cls a 'const char *' with the HTML webpage to return + * @param mime mime type to use + * @param session session handle + * @param connection connection to use + */ + static enum MHD_Result + fill_v1_v2_form (const void *cls, + const char *mime, + struct Session *session, + struct MHD_Connection *connection) + { + enum MHD_Result ret; + char *reply; + struct MHD_Response *response; + int reply_len; + (void) cls; /* Unused */ + + /* Emulate 'asprintf' */ + reply_len = snprintf (NULL, 0, FORM_V1_V2, session->value_1, + session->value_2); + if (0 > reply_len) + return MHD_NO; /* Internal error */ + + reply = (char *) malloc ((size_t) ((size_t) reply_len + 1)); + if (NULL == reply) + return MHD_NO; /* Out-of-memory error */ + + if (reply_len != snprintf (reply, + (size_t) ((size_t) reply_len + 1), + FORM_V1_V2, + session->value_1, + session->value_2)) + { + free (reply); + return MHD_NO; /* printf error */ + } + + /* return static form */ + response = + MHD_create_response_from_buffer_with_free_callback ((size_t) reply_len, + (void *) reply, + &free); + if (NULL != response) + { + add_session_cookie (session, response); + if (MHD_YES != + MHD_add_response_header (response, + MHD_HTTP_HEADER_CONTENT_TYPE, + mime)) + { + fprintf (stderr, + "Failed to set content type header!\n"); + /* return response without content type anyway ... */ + } + ret = MHD_queue_response (connection, + MHD_HTTP_OK, + response); + MHD_destroy_response (response); + } + else + { + free (reply); + ret = MHD_NO; + } + return ret; + } + + + /** + * Handler used to generate a 404 reply. + * + * @param cls a 'const char *' with the HTML webpage to return + * @param mime mime type to use + * @param session session handle + * @param connection connection to use + */ + static enum MHD_Result + not_found_page (const void *cls, + const char *mime, + struct Session *session, + struct MHD_Connection *connection) + { + enum MHD_Result ret; + struct MHD_Response *response; + (void) cls; /* Unused. Silent compiler warning. */ + (void) session; /* Unused. Silent compiler warning. */ + + /* unsupported HTTP method */ + response = MHD_create_response_from_buffer_static (strlen (NOT_FOUND_ERROR), + NOT_FOUND_ERROR); + ret = MHD_queue_response (connection, + MHD_HTTP_NOT_FOUND, + response); + if (MHD_YES != + MHD_add_response_header (response, + MHD_HTTP_HEADER_CONTENT_TYPE, + mime)) + { + fprintf (stderr, + "Failed to set content type header!\n"); + /* return response without content type anyway ... */ + } + MHD_destroy_response (response); + return ret; + } + + + /** + * List of all pages served by this HTTP server. + */ + static const struct Page pages[] = { + { "/", "text/html", &fill_v1_form, NULL }, + { "/2", "text/html", &fill_v1_v2_form, NULL }, + { "/S", "text/html", &serve_simple_form, SUBMIT_PAGE }, + { "/F", "text/html", &serve_simple_form, LAST_PAGE }, + { NULL, NULL, ¬_found_page, NULL } /* 404 */ + }; + + + /** + * Iterator over key-value pairs where the value + * maybe made available in increments and/or may + * not be zero-terminated. Used for processing + * POST data. + * + * @param cls user-specified closure + * @param kind type of the value + * @param key 0-terminated key for the value + * @param filename name of the uploaded file, NULL if not known + * @param content_type mime-type of the data, NULL if not known + * @param transfer_encoding encoding of the data, NULL if not known + * @param data pointer to size bytes of data at the + * specified offset + * @param off offset of data in the overall value + * @param size number of bytes in data available + * @return #MHD_YES to continue iterating, + * #MHD_NO to abort the iteration + */ + static enum MHD_Result + post_iterator (void *cls, + enum MHD_ValueKind kind, + const char *key, + const char *filename, + const char *content_type, + const char *transfer_encoding, + const char *data, uint64_t off, size_t size) + { + struct Request *request = cls; + struct Session *session = request->session; + (void) kind; /* Unused. Silent compiler warning. */ + (void) filename; /* Unused. Silent compiler warning. */ + (void) content_type; /* Unused. Silent compiler warning. */ + (void) transfer_encoding; /* Unused. Silent compiler warning. */ + + if (0 == strcmp ("DONE", key)) + { + fprintf (stdout, + "Session `%s' submitted `%s', `%s'\n", + session->sid, + session->value_1, + session->value_2); + return MHD_YES; + } + if (0 == strcmp ("v1", key)) + { + if (off >= sizeof(session->value_1) - 1) + return MHD_YES; /* Discard extra data */ + if (size + off >= sizeof(session->value_1)) + size = (size_t) (sizeof (session->value_1) - off - 1); /* crop extra data */ + memcpy (&session->value_1[off], + data, + size); + if (size + off < sizeof (session->value_1)) + session->value_1[size + off] = '\0'; + return MHD_YES; + } + if (0 == strcmp ("v2", key)) + { + if (off >= sizeof(session->value_2) - 1) + return MHD_YES; /* Discard extra data */ + if (size + off >= sizeof(session->value_2)) + size = (size_t) (sizeof (session->value_2) - off - 1); /* crop extra data */ + memcpy (&session->value_2[off], + data, + size); + if (size + off < sizeof (session->value_2)) + session->value_2[size + off] = '\0'; + return MHD_YES; + } + fprintf (stderr, "Unsupported form value `%s'\n", key); + return MHD_YES; + } + + + /** + * Main MHD callback for handling requests. + * + * + * @param cls argument given together with the function + * pointer when the handler was registered with MHD + * @param connection handle to connection which is being processed + * @param url the requested url + * @param method the HTTP method used ("GET", "PUT", etc.) + * @param version the HTTP version string (i.e. "HTTP/1.1") + * @param upload_data the data being uploaded (excluding HEADERS, + * for a POST that fits into memory and that is encoded + * with a supported encoding, the POST data will NOT be + * given in upload_data and is instead available as + * part of MHD_get_connection_values; very large POST + * data *will* be made available incrementally in + * upload_data) + * @param upload_data_size set initially to the size of the + * upload_data provided; the method must update this + * value to the number of bytes NOT processed; + * @param req_cls pointer that the callback can set to some + * address and that will be preserved by MHD for future + * calls for this request; since the access handler may + * be called many times (i.e., for a PUT/POST operation + * with plenty of upload data) this allows the application + * to easily associate some request-specific state. + * If necessary, this state can be cleaned up in the + * global "MHD_RequestCompleted" callback (which + * can be set with the MHD_OPTION_NOTIFY_COMPLETED). + * Initially, *req_cls will be NULL. + * @return MHS_YES if the connection was handled successfully, + * MHS_NO if the socket must be closed due to a serious + * error while handling the request + */ + static enum MHD_Result + create_response (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, + size_t *upload_data_size, + void **req_cls) + { + struct MHD_Response *response; + struct Request *request; + struct Session *session; + enum MHD_Result ret; + unsigned int i; + (void) cls; /* Unused. Silent compiler warning. */ + (void) version; /* Unused. Silent compiler warning. */ + + request = *req_cls; + if (NULL == request) + { + request = calloc (1, sizeof (struct Request)); + if (NULL == request) + { + fprintf (stderr, "calloc error: %s\n", strerror (errno)); + return MHD_NO; + } + *req_cls = request; + if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) + { + request->pp = MHD_create_post_processor (connection, 1024, + &post_iterator, request); + if (NULL == request->pp) + { + fprintf (stderr, "Failed to setup post processor for `%s'\n", + url); + return MHD_NO; /* internal error */ + } + } + return MHD_YES; + } + if (NULL == request->session) + { + request->session = get_session (connection); + if (NULL == request->session) + { + fprintf (stderr, "Failed to setup session for `%s'\n", + url); + return MHD_NO; /* internal error */ + } + } + session = request->session; + session->start = time (NULL); + if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) + { + /* evaluate POST data */ + if (MHD_YES != + MHD_post_process (request->pp, + upload_data, + *upload_data_size)) + return MHD_NO; /* internal error */ + if (0 != *upload_data_size) + { + *upload_data_size = 0; + return MHD_YES; + } + /* done with POST data, serve response */ + MHD_destroy_post_processor (request->pp); + request->pp = NULL; + method = MHD_HTTP_METHOD_GET; /* fake 'GET' */ + if (NULL != request->post_url) + url = request->post_url; + } + + if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) || + (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) ) + { + /* find out which page to serve */ + i = 0; + while ( (pages[i].url != NULL) && + (0 != strcmp (pages[i].url, url)) ) + i++; + ret = pages[i].handler (pages[i].handler_cls, + pages[i].mime, + session, connection); + if (ret != MHD_YES) + fprintf (stderr, "Failed to create page for `%s'\n", + url); + return ret; + } + /* unsupported HTTP method */ + response = MHD_create_response_from_buffer_static (strlen (METHOD_ERROR), + METHOD_ERROR); + ret = MHD_queue_response (connection, + MHD_HTTP_NOT_ACCEPTABLE, + response); + MHD_destroy_response (response); + return ret; + } + + + /** + * Callback called upon completion of a request. + * Decrements session reference counter. + * + * @param cls not used + * @param connection connection that completed + * @param req_cls session handle + * @param toe status code + */ + static void + request_completed_callback (void *cls, + struct MHD_Connection *connection, + void **req_cls, + enum MHD_RequestTerminationCode toe) + { + struct Request *request = *req_cls; + (void) cls; /* Unused. Silent compiler warning. */ + (void) connection; /* Unused. Silent compiler warning. */ + (void) toe; /* Unused. Silent compiler warning. */ + + if (NULL == request) + return; + if (NULL != request->session) + request->session->rc--; + if (NULL != request->pp) + MHD_destroy_post_processor (request->pp); + free (request); + } + + + /** + * Clean up handles of sessions that have been idle for + * too long. + */ + static void + expire_sessions (void) + { + struct Session *pos; + struct Session *prev; + struct Session *next; + time_t now; + + now = time (NULL); + prev = NULL; + pos = sessions; + while (NULL != pos) + { + next = pos->next; + if (now - pos->start > 60 * 60) + { + /* expire sessions after 1h */ + if (NULL == prev) + sessions = pos->next; + else + prev->next = next; + free (pos); + } + else + prev = pos; + pos = next; + } + } + + + /** + * Call with the port number as the only argument. + * Never terminates (other than by signals, such as CTRL-C). + */ + int + main (int argc, char *const *argv) + { + struct MHD_Daemon *d; + struct timeval tv; + struct timeval *tvp; + fd_set rs; + fd_set ws; + fd_set es; + MHD_socket max; + uint64_t mhd_timeout; + unsigned int port; + + if (argc != 2) + { + printf ("%s PORT\n", argv[0]); + return 1; + } + if ( (1 != sscanf (argv[1], "%u", &port)) || + (0 == port) || (65535 < port) ) + { + fprintf (stderr, + "Port must be a number between 1 and 65535.\n"); + return 1; + } + + /* initialize PRNG */ + srand ((unsigned int) time (NULL)); + d = MHD_start_daemon (MHD_USE_ERROR_LOG, + (uint16_t) port, + NULL, NULL, + &create_response, NULL, + MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 15, + MHD_OPTION_NOTIFY_COMPLETED, + &request_completed_callback, NULL, + MHD_OPTION_APP_FD_SETSIZE, (int) FD_SETSIZE, + MHD_OPTION_END); + if (NULL == d) + return 1; + while (1) + { + expire_sessions (); + max = 0; + FD_ZERO (&rs); + FD_ZERO (&ws); + FD_ZERO (&es); + if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) + break; /* fatal internal error */ + if (MHD_get_timeout64 (d, &mhd_timeout) == MHD_YES) + { + #if ! defined(_WIN32) || defined(__CYGWIN__) + tv.tv_sec = (time_t) (mhd_timeout / 1000); + #else /* Native W32 */ + tv.tv_sec = (long) (mhd_timeout / 1000); + #endif /* Native W32 */ + tv.tv_usec = ((long) (mhd_timeout % 1000)) * 1000; + tvp = &tv; + } + else + tvp = NULL; + if (-1 == select ((int) max + 1, &rs, &ws, &es, tvp)) + { + if (EINTR != errno) + fprintf (stderr, + "Aborting due to error during select: %s\n", + strerror (errno)); + break; + } + MHD_run (d); + } + MHD_stop_daemon (d); + return 0; + } + + +File: libmicrohttpd-tutorial.info, Node: tlsauthentication.c, Next: websocket.c, Prev: sessions.c, Up: Example programs + +C.8 tlsauthentication.c +======================= + + /* Feel free to use this example code in any way + you see fit (Public Domain) */ + + #include + #ifndef _WIN32 + #include + #include + #else + #include + #endif + #include + #include + #include + #include + + #define PORT 8888 + + #define REALM "Maintenance" + #define USER "a legitimate user" + #define PASSWORD "and his password" + + #define SERVERKEYFILE "server.key" + #define SERVERCERTFILE "server.pem" + + + static size_t + get_file_size (const char *filename) + { + FILE *fp; + + fp = fopen (filename, "rb"); + if (fp) + { + long size; + + if ((0 != fseek (fp, 0, SEEK_END)) || (-1 == (size = ftell (fp)))) + size = 0; + + fclose (fp); + + return (size_t) size; + } + else + return 0; + } + + + static char * + load_file (const char *filename) + { + FILE *fp; + char *buffer; + size_t size; + + size = get_file_size (filename); + if (0 == size) + return NULL; + + fp = fopen (filename, "rb"); + if (! fp) + return NULL; + + buffer = malloc (size + 1); + if (! buffer) + { + fclose (fp); + return NULL; + } + buffer[size] = '\0'; + + if (size != fread (buffer, 1, size, fp)) + { + free (buffer); + buffer = NULL; + } + + fclose (fp); + return buffer; + } + + + static enum MHD_Result + ask_for_authentication (struct MHD_Connection *connection, const char *realm) + { + enum MHD_Result ret; + struct MHD_Response *response; + + response = MHD_create_response_empty (MHD_RF_NONE); + if (! response) + return MHD_NO; + + ret = MHD_queue_basic_auth_required_response3 (connection, + realm, + MHD_YES, + response); + MHD_destroy_response (response); + return ret; + } + + + static int + is_authenticated (struct MHD_Connection *connection, + const char *username, + const char *password) + { + struct MHD_BasicAuthInfo *auth_info; + int authenticated; + + auth_info = MHD_basic_auth_get_username_password3 (connection); + if (NULL == auth_info) + return 0; + authenticated = + ( (strlen (username) == auth_info->username_len) && + (0 == memcmp (auth_info->username, username, auth_info->username_len)) && + /* The next check against NULL is optional, + * if 'password' is NULL then 'password_len' is always zero. */ + (NULL != auth_info->password) && + (strlen (password) == auth_info->password_len) && + (0 == memcmp (auth_info->password, password, auth_info->password_len)) ); + + MHD_free (auth_info); + + return authenticated; + } + + + static enum MHD_Result + secret_page (struct MHD_Connection *connection) + { + enum MHD_Result ret; + struct MHD_Response *response; + const char *page = "A secret."; + + response = MHD_create_response_from_buffer_static (strlen (page), page); + if (! response) + return MHD_NO; + + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + MHD_destroy_response (response); + + return ret; + } + + + static enum MHD_Result + answer_to_connection (void *cls, struct MHD_Connection *connection, + const char *url, const char *method, + const char *version, const char *upload_data, + size_t *upload_data_size, void **req_cls) + { + (void) cls; /* Unused. Silent compiler warning. */ + (void) url; /* Unused. Silent compiler warning. */ + (void) version; /* Unused. Silent compiler warning. */ + (void) upload_data; /* Unused. Silent compiler warning. */ + (void) upload_data_size; /* Unused. Silent compiler warning. */ + + if (0 != strcmp (method, "GET")) + return MHD_NO; + if (NULL == *req_cls) + { + *req_cls = connection; + return MHD_YES; + } + + if (! is_authenticated (connection, USER, PASSWORD)) + return ask_for_authentication (connection, REALM); + + return secret_page (connection); + } + + + int + main (void) + { + struct MHD_Daemon *daemon; + char *key_pem; + char *cert_pem; + + key_pem = load_file (SERVERKEYFILE); + cert_pem = load_file (SERVERCERTFILE); + + if ((key_pem == NULL) || (cert_pem == NULL)) + { + printf ("The key/certificate files could not be read.\n"); + if (NULL != key_pem) + free (key_pem); + if (NULL != cert_pem) + free (cert_pem); + return 1; + } + + daemon = + MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS, PORT, NULL, + NULL, &answer_to_connection, NULL, + MHD_OPTION_HTTPS_MEM_KEY, key_pem, + MHD_OPTION_HTTPS_MEM_CERT, cert_pem, MHD_OPTION_END); + if (NULL == daemon) + { + printf ("%s\n", cert_pem); + + free (key_pem); + free (cert_pem); + + return 1; + } + + (void) getchar (); + + MHD_stop_daemon (daemon); + free (key_pem); + free (cert_pem); + + return 0; + } + + +File: libmicrohttpd-tutorial.info, Node: websocket.c, Prev: tlsauthentication.c, Up: Example programs + +C.9 websocket.c +=============== + + /* Feel free to use this example code in any way + you see fit (Public Domain) */ + + #include + #ifndef _WIN32 + #include + #include + #include + #else + #include + #endif + #include + #include + #include + #include + #include + #include + #include + + #define PORT 80 + + #define PAGE \ + "\n" \ + "\n" \ + "\n" \ + "\n" \ + "Websocket Demo\n" \ + "\n" \ + "\n" \ + "\n" \ + "\n" \ + "" + + #define PAGE_NOT_FOUND \ + "404 Not Found" + + #define PAGE_INVALID_WEBSOCKET_REQUEST \ + "Invalid WebSocket request!" + + static void + send_all (MHD_socket fd, + const char *buf, + size_t len); + + static void + make_blocking (MHD_socket fd); + + static void + upgrade_handler (void *cls, + struct MHD_Connection *connection, + void *req_cls, + const char *extra_in, + size_t extra_in_size, + MHD_socket fd, + struct MHD_UpgradeResponseHandle *urh) + { + /* make the socket blocking (operating-system-dependent code) */ + make_blocking (fd); + + /* create a websocket stream for this connection */ + struct MHD_WebSocketStream *ws; + int result = MHD_websocket_stream_init (&ws, + 0, + 0); + if (0 != result) + { + /* Couldn't create the websocket stream. + * So we close the socket and leave + */ + MHD_upgrade_action (urh, + MHD_UPGRADE_ACTION_CLOSE); + return; + } + + /* Let's wait for incoming data */ + const size_t buf_len = 256; + char buf[buf_len]; + ssize_t got; + while (MHD_WEBSOCKET_VALIDITY_VALID == MHD_websocket_stream_is_valid (ws)) + { + got = recv (fd, + buf, + buf_len, + 0); + if (0 >= got) + { + /* the TCP/IP socket has been closed */ + break; + } + + /* parse the entire received data */ + size_t buf_offset = 0; + while (buf_offset < (size_t) got) + { + size_t new_offset = 0; + char *frame_data = NULL; + size_t frame_len = 0; + int status = MHD_websocket_decode (ws, + buf + buf_offset, + ((size_t) got) - buf_offset, + &new_offset, + &frame_data, + &frame_len); + if (0 > status) + { + /* an error occurred and the connection must be closed */ + if (NULL != frame_data) + { + MHD_websocket_free (ws, frame_data); + } + break; + } + else + { + buf_offset += new_offset; + if (0 < status) + { + /* the frame is complete */ + switch (status) + { + case MHD_WEBSOCKET_STATUS_TEXT_FRAME: + /* The client has sent some text. + * We will display it and answer with a text frame. + */ + if (NULL != frame_data) + { + printf ("Received message: %s\n", frame_data); + MHD_websocket_free (ws, frame_data); + frame_data = NULL; + } + result = MHD_websocket_encode_text (ws, + "Hello", + 5, /* length of "Hello" */ + 0, + &frame_data, + &frame_len, + NULL); + if (0 == result) + { + send_all (fd, + frame_data, + frame_len); + } + break; + + case MHD_WEBSOCKET_STATUS_CLOSE_FRAME: + /* if we receive a close frame, we will respond with one */ + MHD_websocket_free (ws, + frame_data); + frame_data = NULL; + + result = MHD_websocket_encode_close (ws, + 0, + NULL, + 0, + &frame_data, + &frame_len); + if (0 == result) + { + send_all (fd, + frame_data, + frame_len); + } + break; + + case MHD_WEBSOCKET_STATUS_PING_FRAME: + /* if we receive a ping frame, we will respond */ + /* with the corresponding pong frame */ + { + char *pong = NULL; + size_t pong_len = 0; + result = MHD_websocket_encode_pong (ws, + frame_data, + frame_len, + &pong, + &pong_len); + if (0 == result) + { + send_all (fd, + pong, + pong_len); + } + MHD_websocket_free (ws, + pong); + } + break; + + default: + /* Other frame types are ignored + * in this minimal example. + * This is valid, because they become + * automatically skipped if we receive them unexpectedly + */ + break; + } + } + if (NULL != frame_data) + { + MHD_websocket_free (ws, frame_data); + } + } + } + } + + /* free the websocket stream */ + MHD_websocket_stream_free (ws); + + /* close the socket when it is not needed anymore */ + MHD_upgrade_action (urh, + MHD_UPGRADE_ACTION_CLOSE); + } + + + /* This helper function is used for the case that + * we need to resend some data + */ + static void + send_all (MHD_socket fd, + const char *buf, + size_t len) + { + ssize_t ret; + size_t off; + + for (off = 0; off < len; off += ret) + { + ret = send (fd, + &buf[off], + (int) (len - off), + 0); + if (0 > ret) + { + if (EAGAIN == errno) + { + ret = 0; + continue; + } + break; + } + if (0 == ret) + break; + } + } + + + /* This helper function contains operating-system-dependent code and + * is used to make a socket blocking. + */ + static void + make_blocking (MHD_socket fd) + { + #ifndef _WIN32 + int flags; + + flags = fcntl (fd, F_GETFL); + if (-1 == flags) + abort (); + if ((flags & ~O_NONBLOCK) != flags) + if (-1 == fcntl (fd, F_SETFL, flags & ~O_NONBLOCK)) + abort (); + #else /* _WIN32 */ + unsigned long flags = 0; + + if (0 != ioctlsocket (fd, (int) FIONBIO, &flags)) + abort (); + #endif /* _WIN32 */ + } + + + static enum MHD_Result + access_handler (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, + size_t *upload_data_size, + void **req_cls) + { + static int aptr; + struct MHD_Response *response; + int ret; + + (void) cls; /* Unused. Silent compiler warning. */ + (void) upload_data; /* Unused. Silent compiler warning. */ + (void) upload_data_size; /* Unused. Silent compiler warning. */ + + if (0 != strcmp (method, "GET")) + return MHD_NO; /* unexpected method */ + if (&aptr != *req_cls) + { + /* do never respond on first call */ + *req_cls = &aptr; + return MHD_YES; + } + *req_cls = NULL; /* reset when done */ + + if (0 == strcmp (url, "/")) + { + /* Default page for visiting the server */ + struct MHD_Response *response; + response = MHD_create_response_from_buffer_static (strlen (PAGE), + PAGE); + ret = MHD_queue_response (connection, + MHD_HTTP_OK, + response); + MHD_destroy_response (response); + } + else if (0 == strcmp (url, "/chat")) + { + char is_valid = 1; + const char *value = NULL; + char sec_websocket_accept[29]; + + if (0 != MHD_websocket_check_http_version (version)) + { + is_valid = 0; + } + value = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_CONNECTION); + if (0 != MHD_websocket_check_connection_header (value)) + { + is_valid = 0; + } + value = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_UPGRADE); + if (0 != MHD_websocket_check_upgrade_header (value)) + { + is_valid = 0; + } + value = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_SEC_WEBSOCKET_VERSION); + if (0 != MHD_websocket_check_version_header (value)) + { + is_valid = 0; + } + value = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_SEC_WEBSOCKET_KEY); + if (0 != MHD_websocket_create_accept_header (value, sec_websocket_accept)) + { + is_valid = 0; + } + + if (1 == is_valid) + { + /* upgrade the connection */ + response = MHD_create_response_for_upgrade (&upgrade_handler, + NULL); + MHD_add_response_header (response, + MHD_HTTP_HEADER_UPGRADE, + "websocket"); + MHD_add_response_header (response, + MHD_HTTP_HEADER_SEC_WEBSOCKET_ACCEPT, + sec_websocket_accept); + ret = MHD_queue_response (connection, + MHD_HTTP_SWITCHING_PROTOCOLS, + response); + MHD_destroy_response (response); + } + else + { + /* return error page */ + struct MHD_Response *response; + response = + MHD_create_response_from_buffer_static (strlen ( + PAGE_INVALID_WEBSOCKET_REQUEST), + PAGE_INVALID_WEBSOCKET_REQUEST); + ret = MHD_queue_response (connection, + MHD_HTTP_BAD_REQUEST, + response); + MHD_destroy_response (response); + } + } + else + { + struct MHD_Response *response; + response = + MHD_create_response_from_buffer_static (strlen (PAGE_NOT_FOUND), + PAGE_NOT_FOUND); + ret = MHD_queue_response (connection, + MHD_HTTP_NOT_FOUND, + response); + MHD_destroy_response (response); + } + + return ret; + } + + + int + main (int argc, + char *const *argv) + { + (void) argc; /* Unused. Silent compiler warning. */ + (void) argv; /* Unused. Silent compiler warning. */ + struct MHD_Daemon *daemon; + + daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD + | MHD_USE_THREAD_PER_CONNECTION + | MHD_ALLOW_UPGRADE + | MHD_USE_ERROR_LOG, + PORT, NULL, NULL, + &access_handler, NULL, + MHD_OPTION_END); + + if (NULL == daemon) + return 1; + (void) getc (stdin); + + MHD_stop_daemon (daemon); + + return 0; + } + + + +Tag Table: +Node: Top873 +Node: Introduction1942 +Node: Hello browser example3248 +Node: Exploring requests14504 +Node: Response headers19928 +Node: Supporting basic authentication27861 +Node: Processing POST data37947 +Node: Improved processing of POST data46693 +Node: Session management57511 +Node: Adding a layer of security61025 +Node: Websockets75792 +Node: Bibliography103375 +Node: License text104652 +Node: Example programs129808 +Node: hellobrowser.c130137 +Node: logging.c132268 +Node: responseheaders.c134432 +Node: basicauthentication.c137961 +Node: simplepost.c141899 +Node: largepost.c148653 +Node: sessions.c159825 +Node: tlsauthentication.c187089 +Node: websocket.c193151 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/vendor/libmicrohttpd/share/info/libmicrohttpd.info b/vendor/libmicrohttpd/share/info/libmicrohttpd.info new file mode 100644 index 0000000..1cfd7a6 --- /dev/null +++ b/vendor/libmicrohttpd/share/info/libmicrohttpd.info @@ -0,0 +1,6138 @@ +This is libmicrohttpd.info, produced by makeinfo version 7.1.1 from +libmicrohttpd.texi. + +This manual is for GNU libmicrohttpd (version 1.0.5, 24 September 2024), +a library for embedding an HTTP(S) server into C applications. + + Copyright © 2007-2019 Christian Grothoff + + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation License, + Version 1.3 or any later version published by the Free Software + Foundation; with no Invariant Sections, no Front-Cover Texts, and + no Back-Cover Texts. A copy of the license is included in the + section entitled "GNU Free Documentation License". +INFO-DIR-SECTION Software libraries +START-INFO-DIR-ENTRY +* libmicrohttpd: (libmicrohttpd). Embedded HTTP server library. +END-INFO-DIR-ENTRY + + +File: libmicrohttpd.info, Node: Top, Next: microhttpd-intro, Up: (dir) + +The GNU libmicrohttpd Library +***************************** + +This manual is for GNU libmicrohttpd (version 1.0.5, 24 September 2024), +a library for embedding an HTTP(S) server into C applications. + + Copyright © 2007-2019 Christian Grothoff + + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation License, + Version 1.3 or any later version published by the Free Software + Foundation; with no Invariant Sections, no Front-Cover Texts, and + no Back-Cover Texts. A copy of the license is included in the + section entitled "GNU Free Documentation License". + +* Menu: + +* microhttpd-intro:: Introduction. +* microhttpd-const:: Constants. +* microhttpd-struct:: Structures type definition. +* microhttpd-cb:: Callback functions definition. +* microhttpd-init:: Starting and stopping the server. +* microhttpd-inspect:: Implementing external ‘select’. +* microhttpd-requests:: Handling requests. +* microhttpd-responses:: Building responses to requests. +* microhttpd-flow:: Flow control. +* microhttpd-dauth:: Utilizing Authentication. +* microhttpd-post:: Adding a ‘POST’ processor. +* microhttpd-info:: Obtaining and modifying status information. +* microhttpd-util:: Utilities. +* microhttpd-websocket:: Websockets. + +Appendices + +* GNU-LGPL:: The GNU Lesser General Public License says how you + can copy and share almost all of 'libmicrohttpd'. +* eCos License:: The eCos License says how you can copy and share some parts of 'libmicrohttpd'. +* GNU-GPL:: The GNU General Public License (with eCos extension) says how you can copy and share some parts of 'libmicrohttpd'. +* GNU-FDL:: The GNU Free Documentation License says how you + can copy and share the documentation of 'libmicrohttpd'. + +Indices + +* Concept Index:: Index of concepts and programs. +* Function and Data Index:: Index of functions, variables and data types. +* Type Index:: Index of data types. + + +File: libmicrohttpd.info, Node: microhttpd-intro, Next: microhttpd-const, Prev: Top, Up: Top + +1 Introduction +************** + +All symbols defined in the public API start with ‘MHD_’. MHD is a small +HTTP daemon library. As such, it does not have any API for logging +errors (you can only enable or disable logging to stderr). Also, it may +not support all of the HTTP features directly, where applicable, +portions of HTTP may have to be handled by clients of the library. + + The library is supposed to handle everything that it must handle +(because the API would not allow clients to do this), such as basic +connection management. However, detailed interpretations of headers, +such as range requests, are left to the main application. In +particular, if an application developer wants to support range requests, +he needs to explicitly indicate support in responses and also explicitly +parse the range header and generate a response (for example, using the +‘MHD_create_response_from_fd_at_offset’ call to serve ranges from a +file). MHD does understands headers that control connection management +(specifically, ‘Connection: close’ and ‘Expect: 100 continue’ are +understood and handled automatically). ‘Connection: upgrade’ is +supported by passing control over the socket (or something that behaves +like the real socket in the case of TLS) to the application (after +sending the desired HTTP response header). + + MHD largely ignores the semantics of the different HTTP methods, so +clients are left to handle those. One exception is that MHD does +understand ‘HEAD’ and will only send the headers of the response and not +the body, even if the client supplied a body. (In fact, clients do need +to construct a response with the correct length, even for ‘HEAD’ +request.) + + MHD understands ‘POST’ data and is able to decode certain formats (at +the moment only ‘application/x-www-form-urlencoded’ and +‘multipart/form-data’) using the post processor API. The data stream of +a POST is also provided directly to the main application, so unsupported +encodings could still be processed, just not conveniently by MHD. + + The header file defines various constants used by the HTTP protocol. +This does not mean that MHD actually interprets all of these values. +The provided constants are exported as a convenience for users of the +library. MHD does not verify that transmitted HTTP headers are part of +the standard specification; users of the library are free to define +their own extensions of the HTTP standard and use those with MHD. + + All functions are guaranteed to be completely reentrant and +thread-safe. MHD checks for allocation failures and tries to recover +gracefully (for example, by closing the connection). Additionally, +clients can specify resource limits on the overall number of +connections, number of connections per IP address and memory used per +connection to avoid resource exhaustion. + +1.1 Scope +========= + +MHD is currently used in a wide range of implementations. Examples +based on reports we've received from developers include: + • Embedded HTTP server on a cortex M3 (128 KB code space) + • Large-scale multimedia server (reportedly serving at the simulator + limit of 7.5 GB/s) + • Administrative console (via HTTP/HTTPS) for network appliances + +1.2 Thread modes and event loops +================================ + +MHD supports four basic thread modes and up to three event loop styles. + + The four basic thread modes are external sockets polling (MHD creates +no threads, event loop is fully managed by the application), internal +polling (MHD creates one thread for all connections), polling in thread +pool (MHD creates a thread pool which is used to process all +connections) and thread-per-connection (MHD creates one thread for +listen sockets and then one thread per accepted connection). + + These thread modes are then combined with the evet loop styles +(polling function type). MHD support select, poll and epoll. select is +available on all platforms, epoll and poll may not be available on some +platforms. Note that it is possible to combine MHD using epoll with an +external select-based event loop. + + The default (if no other option is passed) is "external select". The +highest performance can typically be obtained with a thread pool using +‘epoll’. Apache Benchmark (ab) was used to compare the performance of +‘select’ and ‘epoll’ when using a thread pool and a large number of +connections. *note Figure 1.1: fig:performance. shows the resulting +plot from the ‘benchmark.c’ example, which measures the latency between +an incoming request and the completion of the transmission of the +response. In this setting, the ‘epoll’ thread pool with four threads +was able to handle more than 45,000 connections per second on loopback +(with Apache Benchmark running three processes on the same machine). + +[image src="libmicrohttpd_performance_data.png" alt="Data"] + + +Figure 1.1: Performance measurements for select vs. epoll (with +thread-pool). + + Not all combinations of thread modes and event loop styles are +supported. This is partially to keep the API simple, and partially +because some combinations simply make no sense as others are strictly +superior. Note that the choice of style depends first of all on the +application logic, and then on the performance requirements. +Applications that perform a blocking operation while handling a request +within the callbacks from MHD must use a thread per connection. This is +typically rather costly. Applications that do not support threads or +that must run on embedded devices without thread-support must use the +external mode. Using ‘epoll’ is only supported on some platform, thus +portable applications must at least have a fallback option available. +*note Table 1.1: tbl:supported. lists the sane combinations. + + select poll epoll +external yes no yes +internal yes yes yes +thread pool yes yes yes +thread-per-connection yes yes no + +Table 1.1: Supported combinations of event styles and thread modes. + +1.3 Compiling GNU libmicrohttpd +=============================== + +MHD uses the standard GNU system where the usual build process involves +running +$ ./configure +$ make +$ make install + + MHD supports various options to be given to configure to tailor the +binary to a specific situation. Note that some of these options will +remove portions of the MHD code that are required for +binary-compatibility. They should only be used on embedded systems with +tight resource constraints and no concerns about library versioning. +Standard distributions including MHD are expected to always ship with +all features enabled, otherwise unexpected incompatibilities can arise! + + Here is a list of MHD-specific options that can be given to configure +(canonical configure options such as "-prefix" are also supported, for a +full list of options run "./configure -help"): + +‘``--disable-curl''’ + disable running testcases using libcurl + +‘``--disable-largefile''’ + disable support for 64-bit files + +‘``--disable-messages''’ + disable logging of error messages (smaller binary size, not so much + fun for debugging) + +‘``--disable-https''’ + disable HTTPS support, even if GNUtls is found; this option must be + used if eCOS license is desired as an option (in all cases the + resulting binary falls under a GNU LGPL-only license) + +‘``--disable-postprocessor''’ + do not include the post processor API (results in binary + incompatibility) + +‘``--disable-dauth''’ + do not include the authentication APIs (results in binary + incompatibility) + +‘``--disable-httpupgrade''’ + do not build code for HTTP "Upgrade" (smaller binary size, binary + incompatible library) + +‘``--disable-epoll''’ + do not include epoll support, even if it supported (minimally + smaller binary size, good for portability testing) + +‘``--enable-coverage''’ + set flags for analysis of code-coverage with gcc/gcov (results in + slow, large binaries) + +‘``--with-threads=posix,w32,none,auto''’ + sets threading library to use. With use "none" to not support + threads. In this case, MHD will only support the "external" + threading modes and not perform any locking of data structures! + Use ‘MHD_is_feature_supported(MHD_FEATURE_THREADS)’ to test if + threads are available. Default is "auto". + +‘``--with-gcrypt=PATH''’ + specifies path to libgcrypt installation + +‘``--with-gnutls=PATH''’ + specifies path to libgnutls installation + + To cross-compile MHD for Android, install the Android NDK and use: +./configure --target=arm-linux-androideabi --host=arm-linux-androideabi --disable-doc --disable-examples +make + + Similar build commands should work for cross-compilation to other +platforms. Note that you may have to first cross-compile GnuTLS to get +MHD with TLS support. + +1.4 Validity of pointers +======================== + +MHD will give applications access to its internal data structures via +pointers via arguments and return values from its API. This creates the +question as to how long those pointers are assured to stay valid. + + Most MHD data structures are associated with the connection of an +HTTP client. Thus, pointers associated with a connection are typically +valid until the connection is finished, at which point MHD will call the +‘MHD_RequestCompletedCallback’ if one is registered. Applications that +have such a callback registered may assume that keys and values from the +‘MHD_KeyValueIterator’, return values from ‘MHD_lookup_connection_value’ +and the ‘url’, ‘method’ and ‘version’ arguments to the +‘MHD_AccessHandlerCallback’ will remain valid until the respective +‘MHD_RequestCompletedCallback’ is invoked. + + In contrast, the ‘upload_data’ argument of +‘MHD_RequestCompletedCallback’ as well as all pointers from the +‘MHD_PostDataIterator’ are only valid for the duration of the callback. + + Pointers returned from ‘MHD_get_response_header’ are valid as long as +the response itself is valid. + +1.5 Including the microhttpd.h header +===================================== + +Ideally, before including "microhttpd.h" you should add the necessary +includes to define the ‘va_list’, ‘size_t’, ‘ssize_t’, ‘intptr_t’, +‘off_t’, ‘uint8_t’, ‘uint16_t’, ‘int32_t’, ‘uint32_t’, ‘int64_t’, +‘uint64_t’, ‘fd_set’, ‘socklen_t’ and ‘struct sockaddr’ data types. +Which specific headers are needed may depend on your platform and your +build system might include some tests to provide you with the necessary +conditional operations. For possible suggestions consult ‘platform.h’ +and ‘configure.ac’ in the MHD distribution. + + Once you have ensured that you manually (!) included the right +headers for your platform before "microhttpd.h", you should also add a +line with ‘#define MHD_PLATFORM_H’ which will prevent the "microhttpd.h" +header from trying (and, depending on your platform, failing) to include +the right headers. + + If you do not define MHD_PLATFORM_H, the "microhttpd.h" header will +automatically include headers needed on GNU/Linux systems (possibly +causing problems when porting to other platforms). + +1.6 SIGPIPE +=========== + +MHD does not install a signal handler for SIGPIPE. On platforms where +this is possible (such as GNU/Linux), it disables SIGPIPE for its I/O +operations (by passing MSG_NOSIGNAL or similar). On other platforms, +SIGPIPE signals may be generated from network operations by MHD and will +cause the process to die unless the developer explicitly installs a +signal handler for SIGPIPE. + + Hence portable code using MHD must install a SIGPIPE handler or +explicitly block the SIGPIPE signal. MHD does not do so in order to +avoid messing with other parts of the application that may need to +handle SIGPIPE in a particular way. You can make your application +handle SIGPIPE by calling the following function in ‘main’: + +static void +catcher (int sig) +{ +} + +static void +ignore_sigpipe () +{ + struct sigaction oldsig; + struct sigaction sig; + + sig.sa_handler = &catcher; + sigemptyset (&sig.sa_mask); +#ifdef SA_INTERRUPT + sig.sa_flags = SA_INTERRUPT; /* SunOS */ +#else + sig.sa_flags = SA_RESTART; +#endif + if (0 != sigaction (SIGPIPE, &sig, &oldsig)) + fprintf (stderr, + "Failed to install SIGPIPE handler: %s\n", strerror (errno)); +} + +1.7 MHD_UNSIGNED_LONG_LONG +========================== + +Some platforms do not support ‘long long’. Hence MHD defines a macro +‘MHD_UNSIGNED LONG_LONG’ which will default to ‘unsigned long long’. +For standard desktop operating systems, this is all you need to know. + + However, if your platform does not support ‘unsigned long long’, you +should change "platform.h" to define ‘MHD_LONG_LONG’ and +‘MHD_UNSIGNED_LONG_LONG’ to an appropriate alternative type and also +define ‘MHD_LONG_LONG_PRINTF’ and ‘MHD_UNSIGNED_LONG_LONG_PRINTF’ to the +corresponding format string for printing such a data type. Note that +the "signed" versions are deprecated. Also, for historical reasons, +‘MHD_LONG_LONG_PRINTF’ is without the percent sign, whereas +‘MHD_UNSIGNED_LONG_LONG_PRINTF’ is with the percent sign. Newly written +code should only use the unsigned versions. However, you need to define +both in "platform.h" if you need to change the definition for the +specific platform. + +1.8 Portability to W32 +====================== + +libmicrohttpd in general ported well to W32. Most libmicrohttpd +features are supported. W32 do not support some functions, like epoll +and corresponding MHD features are not available on W32. + +1.9 Portability to z/OS +======================= + +To compile MHD on z/OS, extract the archive and run + +iconv -f UTF-8 -t IBM-1047 contrib/ascebc > /tmp/ascebc.sh +chmod +x /tmp/ascebc.sh +for n in `find * -type f` +do + /tmp/ascebc.sh $n +done + to convert all source files to EBCDIC. Note that you must run +‘configure’ from the directory where the configure script is located. +Otherwise, configure will fail to find the ‘contrib/xcc’ script (which +is a wrapper around the z/OS c89 compiler). + + +File: libmicrohttpd.info, Node: microhttpd-const, Next: microhttpd-struct, Prev: microhttpd-intro, Up: Top + +2 Constants +*********** + + -- Enumeration: MHD_FLAG + Options for the MHD daemon. + + Note that MHD will run automatically in background thread(s) only + if ‘MHD_USE_INTERNAL_POLLING_THREAD’ is used. Otherwise caller + (application) must use ‘MHD_run’ or ‘MHD_run_from_select’ to have + MHD processed network connections and data. + + Starting the daemon may also fail if a particular option is not + implemented or not supported on the target platform (i.e. no + support for TLS, threads or IPv6). TLS support generally depends + on options given during MHD compilation. + + ‘MHD_NO_FLAG’ + No options selected. + + ‘MHD_USE_ERROR_LOG’ + If this flag is used, the library should print error messages + and warnings to stderr (or to custom error printer if it's + specified by options). Note that for this run-time option to + have any effect, MHD needs to be compiled with messages + enabled. This is done by default except you ran configure + with the ‘--disable-messages’ flag set. + + ‘MHD_USE_DEBUG’ + Currently the same as ‘MHD_USE_ERROR_LOG’. + + ‘MHD_USE_TLS’ + Run in HTTPS-mode. If you specify ‘MHD_USE_TLS’ and MHD was + compiled without SSL support, ‘MHD_start_daemon’ will return + NULL. + + ‘MHD_USE_THREAD_PER_CONNECTION’ + Run using one thread per connection. + + ‘MHD_USE_INTERNAL_POLLING_THREAD’ + Run using an internal thread doing ‘SELECT’. + + ‘MHD_USE_IPv6’ + Run using the IPv6 protocol (otherwise, MHD will just support + IPv4). If you specify ‘MHD_USE_IPV6’ and the local platform + does not support it, ‘MHD_start_daemon’ will return NULL. + + If you want MHD to support IPv4 and IPv6 using a single + socket, pass MHD_USE_DUAL_STACK, otherwise, if you only pass + this option, MHD will try to bind to IPv6-only (resulting in + no IPv4 support). + + ‘MHD_USE_DUAL_STACK’ + Use a single socket for IPv4 and IPv6. Note that this will + mean that IPv4 addresses are returned by MHD in the + IPv6-mapped format (the 'struct sockaddr_in6' format will be + used for IPv4 and IPv6). + + ‘MHD_USE_PEDANTIC_CHECKS’ + Deprecated (use ‘MHD_OPTION_STRICT_FOR_CLIENT’). Be pedantic + about the protocol. Specifically, at the moment, this flag + causes MHD to reject HTTP 1.1 connections without a ‘Host’ + header. This is required by the standard, but of course in + violation of the "be as liberal as possible in what you + accept" norm. It is recommended to turn this *ON* if you are + testing clients against MHD, and *OFF* in production. + + ‘MHD_USE_POLL’ + Use ‘poll()’ instead of ‘select()’. This allows sockets with + descriptors ‘>= FD_SETSIZE’. This option currently only works + in conjunction with ‘MHD_USE_INTERNAL_POLLING_THREAD’ (at this + point). If you specify ‘MHD_USE_POLL’ and the local platform + does not support it, ‘MHD_start_daemon’ will return NULL. + + ‘MHD_USE_EPOLL’ + Use ‘epoll()’ instead of ‘poll()’ or ‘select()’. This allows + sockets with descriptors ‘>= FD_SETSIZE’. This option is only + available on some systems and does not work in conjunction + with ‘MHD_USE_THREAD_PER_CONNECTION’ (at this point). If you + specify ‘MHD_USE_EPOLL’ and the local platform does not + support it, ‘MHD_start_daemon’ will return NULL. Using + ‘epoll()’ instead of ‘select()’ or ‘poll()’ can in some + situations result in significantly higher performance as the + system call has fundamentally lower complexity (O(1) for + ‘epoll()’ vs. O(n) for ‘select()’/‘poll()’ where n is the + number of open connections). + + ‘MHD_USE_TURBO’ + Enable optimizations to aggressively improve performance. + + Currently, the optimizations this option enables are based on + opportunistic reads and writes. Basically, MHD will simply + try to read or write or accept on a socket before checking + that the socket is ready for IO using the event loop + mechanism. As the sockets are non-blocking, this may fail (at + a loss of performance), but generally MHD does this in + situations where the operation is likely to succeed, in which + case performance is improved. Setting the flag should + generally be safe (even though the code is slightly more + experimental). You may want to benchmark your application to + see if this makes any difference for you. + + ‘MHD_USE_SUPPRESS_DATE_NO_CLOCK’ + Suppress (automatically) adding the 'Date:' header to HTTP + responses. This option should ONLY be used on systems that do + not have a clock and that DO provide other mechanisms for + cache control. See also RFC 2616, section 14.18 (exception + 3). + + ‘MHD_USE_NO_LISTEN_SOCKET’ + Run the HTTP server without any listen socket. This option + only makes sense if ‘MHD_add_connection’ is going to be used + exclusively to connect HTTP clients to the HTTP server. This + option is incompatible with using a thread pool; if it is + used, ‘MHD_OPTION_THREAD_POOL_SIZE’ is ignored. + + ‘MHD_USE_ITC’ + Force MHD to use a signal inter-thread communication channel + to notify the event loop (of threads) of our shutdown and + other events. This is required if an application uses + ‘MHD_USE_INTERNAL_POLLING_THREAD’ and then performs + ‘MHD_quiesce_daemon’ (which eliminates our ability to signal + termination via the listen socket). In these modes, + ‘MHD_quiesce_daemon’ will fail if this option was not set. + Also, use of this option is automatic (as in, you do not even + have to specify it), if ‘MHD_USE_NO_LISTEN_SOCKET’ is + specified. In "external" select mode, this option is always + simply ignored. + + Using this option also guarantees that MHD will not call + ‘shutdown()’ on the listen socket, which means a parent + process can continue to use the socket. + + ‘MHD_ALLOW_SUSPEND_RESUME’ + Enables using ‘MHD_suspend_connection’ and + ‘MHD_resume_connection’, as performing these calls requires + some additional inter-thred communication channels to be + created, and code not using these calls should not pay the + cost. + + ‘MHD_USE_TCP_FASTOPEN’ + Enable TCP_FASTOPEN on the listen socket. TCP_FASTOPEN is + currently supported on Linux >= 3.6. On other systems using + this option with cause ‘MHD_start_daemon’ to fail. + + ‘MHD_ALLOW_UPGRADE’ + This option must be set if you want to upgrade connections + (via "101 Switching Protocols" responses). This requires MHD + to allocate additional resources, and hence we require this + special flag so we only use the resources that are really + needed. + + ‘MHD_USE_AUTO’ + Automatically select best event loop style (polling function) + depending on requested mode by other MHD flags and functions + available on platform. If application doesn't have + requirements for any specific polling function, it's + recommended to use this flag. This flag is very convenient + for multiplatform applications. + + ‘MHD_USE_POST_HANDSHAKE_AUTH_SUPPORT’ + Tell the TLS library to support post handshake client + authentication. Only useful in combination with + ‘MHD_USE_TLS’. + + This option will only work if the underlying TLS library + supports it (i.e. GnuTLS after 3.6.3). If the TLS library + does not support it, MHD may ignore the option and proceed + without supporting this features. + + ‘MHD_USE_INSECURE_TLS_EARLY_DATA’ + Tell the TLS library to support TLS v1.3 early data (0-RTT) + with the resulting security drawbacks. Only enable this if + you really know what you are doing. MHD currently does NOT + enforce that this only affects GET requests! You have been + warned. + + This option will only work if the underlying TLS library + supports it (i.e. GnuTLS after 3.6.3). If the TLS library + does not support it, MHD may ignore the option and proceed + without supporting this features. + + -- Enumeration: MHD_OPTION + MHD options. Passed in the varargs portion of + ‘MHD_start_daemon()’. + + ‘MHD_OPTION_END’ + No more options / last option. This is used to terminate the + VARARGs list. + + ‘MHD_OPTION_CONNECTION_MEMORY_LIMIT’ + Maximum memory size per connection (followed by a ‘size_t’). + The default is 32 kB (32*1024 bytes) as defined by the + internal constant ‘MHD_POOL_SIZE_DEFAULT’. Values above 128k + are unlikely to result in much benefit, as half of the memory + will be typically used for IO, and TCP buffers are unlikely to + support window sizes above 64k on most systems. + + ‘MHD_OPTION_CONNECTION_MEMORY_INCREMENT’ + Increment to use for growing the read buffer (followed by a + ‘size_t’). The default is 1024 (bytes). Increasing this + value will make MHD use memory for reading more aggressively, + which can reduce the number of ‘recvfrom’ calls but may + increase the number of ‘sendto’ calls. The given value must + fit within MHD_OPTION_CONNECTION_MEMORY_LIMIT. + + ‘MHD_OPTION_CONNECTION_LIMIT’ + Maximum number of concurrent connections to accept (followed + by an ‘unsigned int’). The default is ‘FD_SETSIZE - 4’ (the + maximum number of file descriptors supported by ‘select’ minus + four for ‘stdin’, ‘stdout’, ‘stderr’ and the server socket). + In other words, the default is as large as possible. + + If the connection limit is reached, MHD's behavior depends a + bit on other options. If ‘MHD_USE_ITC’ was given, MHD will + stop accepting connections on the listen socket. This will + cause the operating system to queue connections (up to the + ‘listen()’ limit) above the connection limit. Those + connections will be held until MHD is done processing at least + one of the active connections. If ‘MHD_USE_ITC’ is not set, + then MHD will continue to ‘accept()’ and immediately ‘close()’ + these connections. + + Note that if you set a low connection limit, you can easily + get into trouble with browsers doing request pipelining. For + example, if your connection limit is "1", a browser may open a + first connection to access your "index.html" file, keep it + open but use a second connection to retrieve CSS files, images + and the like. In fact, modern browsers are typically by + default configured for up to 15 parallel connections to a + single server. If this happens, MHD will refuse to even + accept the second connection until the first connection is + closed -- which does not happen until timeout. As a result, + the browser will fail to render the page and seem to hang. If + you expect your server to operate close to the connection + limit, you should first consider using a lower timeout value + and also possibly add a "Connection: close" header to your + response to ensure that request pipelining is not used and + connections are closed immediately after the request has + completed: + MHD_add_response_header (response, + MHD_HTTP_HEADER_CONNECTION, + "close"); + + ‘MHD_OPTION_CONNECTION_TIMEOUT’ + After how many seconds of inactivity should a connection + automatically be timed out? (followed by an ‘unsigned int’; + use zero for no timeout). The default is zero (no timeout). + + ‘MHD_OPTION_NOTIFY_COMPLETED’ + Register a function that should be called whenever a request + has been completed (this can be used for application-specific + clean up). Requests that have never been presented to the + application (via ‘MHD_AccessHandlerCallback()’) will not + result in notifications. + + This option should be followed by *TWO* pointers. First a + pointer to a function of type ‘MHD_RequestCompletedCallback()’ + and second a pointer to a closure to pass to the request + completed callback. The second pointer maybe ‘NULL’. + + ‘MHD_OPTION_NOTIFY_CONNECTION’ + Register a function that should be called when the TCP + connection to a client is opened or closed. The registered + callback is called twice per TCP connection, with + ‘MHD_CONNECTION_NOTIFY_STARTED’ and + ‘MHD_CONNECTION_NOTIFY_CLOSED’ respectively. An additional + argument can be used to store TCP connection specific + information, which can be retrieved using + ‘MHD_CONNECTION_INFO_SOCKET_CONTEXT’ during the lifetime of + the TCP connection. Note ‘MHD_OPTION_NOTIFY_COMPLETED’ and + the ‘req_cls’ argument to the ‘MHD_AccessHandlerCallback’ are + per HTTP request (and there can be multiple HTTP requests per + TCP connection). + + This option should be followed by *TWO* pointers. First a + pointer to a function of type ‘MHD_NotifyConnectionCallback()’ + and second a pointer to a closure to pass to the request + completed callback. The second pointer maybe ‘NULL’. + + ‘MHD_OPTION_PER_IP_CONNECTION_LIMIT’ + Limit on the number of (concurrent) connections made to the + server from the same IP address. Can be used to prevent one + IP from taking over all of the allowed connections. If the + same IP tries to establish more than the specified number of + connections, they will be immediately rejected. The option + should be followed by an ‘unsigned int’. The default is zero, + which means no limit on the number of connections from the + same IP address. + + ‘MHD_OPTION_LISTEN_BACKLOG_SIZE’ + Set the size of the ‘listen()’ back log queue of the TCP + socket. Takes an ‘unsigned int’ as the argument. Default is + the platform-specific value of ‘SOMAXCONN’. + + ‘MHD_OPTION_STRICT_FOR_CLIENT’ + Specify how strict we should enforce the HTTP protocol. Takes + an ‘int’ as the argument. Default is zero. + + If set to 1, MHD will be strict about the protocol. + Specifically, at the moment, this flag uses MHD to reject HTTP + 1.1 connections without a "Host" header. This is required by + the standard, but of course in violation of the "be as liberal + as possible in what you accept" norm. It is recommended to + set this to 1 if you are testing clients against MHD, and 0 in + production. + + If set to -1 MHD will be permissive about the protocol, + allowing slight deviations that are technically not allowed by + the RFC. Specifically, at the moment, this flag causes MHD to + allow spaces in header field names. This is disallowed by the + standard. + + It is not recommended to set it to -1 on publicly available + servers as it may potentially lower level of protection. + + ‘MHD_OPTION_SERVER_INSANITY’ + Allows the application to disable certain sanity precautions + in MHD. With these, the client can break the HTTP protocol, so + this should never be used in production. The options are, + however, useful for testing HTTP clients against "broken" + server implementations. This argument must be followed by an + ‘unsigned int’, corresponding to an ‘enum + MHD_DisableSanityCheck’. + + Right now, no sanity checks can be disabled. + + ‘MHD_OPTION_SOCK_ADDR’ + Bind daemon to the supplied socket address. This option + should be followed by a ‘struct sockaddr *’. If + ‘MHD_USE_IPv6’ is specified, the ‘struct sockaddr*’ should + point to a ‘struct sockaddr_in6’, otherwise to a ‘struct + sockaddr_in’. If this option is not specified, the daemon + will listen to incoming connections from anywhere. If you use + this option, the 'port' argument from ‘MHD_start_daemon’ is + ignored and the port from the given ‘struct sockaddr *’ will + be used instead. + + ‘MHD_OPTION_URI_LOG_CALLBACK’ + Specify a function that should be called before parsing the + URI from the client. The specified callback function can be + used for processing the URI (including the options) before it + is parsed. The URI after parsing will no longer contain the + options, which maybe inconvenient for logging. This option + should be followed by two arguments, the first one must be of + the form + void * my_logger(void * cls, const char * uri, struct MHD_Connection *con) + where the return value will be passed as ‘*req_cls’ in calls + to the ‘MHD_AccessHandlerCallback’ when this request is + processed later; returning a value of ‘NULL’ has no special + significance; (however, note that if you return non-‘NULL’, + you can no longer rely on the first call to the access handler + having ‘NULL == *req_cls’ on entry) ‘cls’ will be set to the + second argument following MHD_OPTION_URI_LOG_CALLBACK. + Finally, ‘uri’ will be the 0-terminated URI of the request. + + Note that during the time of this call, most of the + connection's state is not initialized (as we have not yet + parsed he headers). However, information about the connecting + client (IP, socket) is available. + + ‘MHD_OPTION_HTTPS_MEM_KEY’ + Memory pointer to the private key to be used by the HTTPS + daemon. This option should be followed by an "const char*" + argument. This should be used in conjunction with + 'MHD_OPTION_HTTPS_MEM_CERT'. + + ‘MHD_OPTION_HTTPS_KEY_PASSWORD’ + Memory pointer to the password that decrypts the private key + to be used by the HTTPS daemon. This option should be + followed by an "const char*" argument. This should be used in + conjunction with 'MHD_OPTION_HTTPS_MEM_KEY'. + + The password (or passphrase) is only used immediately during + ‘MHD_start_daemon()’. Thus, the application may want to erase + it from memory afterwards for additional security. + + ‘MHD_OPTION_HTTPS_MEM_CERT’ + Memory pointer to the certificate to be used by the HTTPS + daemon. This option should be followed by an "const char*" + argument. This should be used in conjunction with + 'MHD_OPTION_HTTPS_MEM_KEY'. + + ‘MHD_OPTION_HTTPS_MEM_TRUST’ + Memory pointer to the CA certificate to be used by the HTTPS + daemon to authenticate and trust clients certificates. This + option should be followed by an "const char*" argument. The + presence of this option activates the request of certificate + to the client. The request to the client is marked optional, + and it is the responsibility of the server to check the + presence of the certificate if needed. Note that most + browsers will only present a client certificate only if they + have one matching the specified CA, not sending any + certificate otherwise. + + ‘MHD_OPTION_HTTPS_CRED_TYPE’ + Daemon credentials type. Either certificate or anonymous, + this option should be followed by one of the values listed in + "enum gnutls_credentials_type_t". + + ‘MHD_OPTION_HTTPS_PRIORITIES’ + SSL/TLS protocol version and ciphers. This option must be + followed by an "const char *" argument specifying the SSL/TLS + protocol versions and ciphers that are acceptable for the + application. The string is passed unchanged to + gnutls_priority_init. If this option is not specified, + "NORMAL" is used. + + ‘MHD_OPTION_HTTPS_CERT_CALLBACK’ + Use a callback to determine which X.509 certificate should be + used for a given HTTPS connection. This option should be + followed by a argument of type + "gnutls_certificate_retrieve_function2 *". This option + provides an alternative to MHD_OPTION_HTTPS_MEM_KEY and + MHD_OPTION_HTTPS_MEM_CERT. You must use this version if + multiple domains are to be hosted at the same IP address using + TLS's Server Name Indication (SNI) extension. In this case, + the callback is expected to select the correct certificate + based on the SNI information provided. The callback is + expected to access the SNI data using + gnutls_server_name_get(). Using this option requires GnuTLS + 3.0 or higher. + + ‘MHD_OPTION_HTTPS_CERT_CALLBACK2’ + Use a callback to determine which X.509 certificate should be + used for a given HTTPS connection. This option should be + followed by a argument of type + 'gnutls_certificate_retrieve_function3 *'. This option + provides an alternative/extension to + #MHD_OPTION_HTTPS_CERT_CALLBACK. You must use this version if + you want to use OCSP stapling. Using this option requires + GnuTLS 3.6.3 or higher. + + ‘MHD_OPTION_GNUTLS_PSK_CRED_HANDLER’ + Use pre-shared key for TLS credentials. Pass a pointer to + callback of type ‘MHD_PskServerCredentialsCallback’ and a + closure. The function will be called to retrieve the shared + key for a given username. + + ‘MHD_OPTION_DIGEST_AUTH_RANDOM’ + Digest Authentication nonce's seed. + + This option should be followed by two arguments. First an + integer of type "size_t" which specifies the size of the + buffer pointed to by the second argument in bytes. Note that + the application must ensure that the buffer of the second + argument remains allocated and unmodified while the daemon is + running. For security, you SHOULD provide a fresh random + nonce when using MHD with Digest Authentication. + + ‘MHD_OPTION_NONCE_NC_SIZE’ + + Size of an array of nonce and nonce counter map. This option + must be followed by an "unsigned int" argument that have the + size (number of elements) of a map of a nonce and a + nonce-counter. If this option is not specified, a default + value of 4 will be used (which might be too small for servers + handling many requests). If you do not use digest + authentication at all, you can specify a value of zero to save + some memory. + + You should calculate the value of NC_SIZE based on the number + of connections per second multiplied by your expected session + duration plus a factor of about two for hash table collisions. + For example, if you expect 100 digest-authenticated + connections per second and the average user to stay on your + site for 5 minutes, then you likely need a value of about + 60000. On the other hand, if you can only expect only 10 + digest-authenticated connections per second, tolerate browsers + getting a fresh nonce for each request and expect a HTTP + request latency of 250 ms, then a value of about 5 should be + fine. + + ‘MHD_OPTION_LISTEN_SOCKET’ + Listen socket to use. Pass a listen socket for MHD to use + (systemd-style). If this option is used, MHD will not open + its own listen socket(s). The argument passed must be of type + "int" and refer to an existing socket that has been bound to a + port and is listening. + + ‘MHD_OPTION_EXTERNAL_LOGGER’ + Use the given function for logging error messages. This + option must be followed by two arguments; the first must be a + pointer to a function of type 'void fun(void * arg, const char + * fmt, va_list ap)' and the second a pointer of type 'void*' + which will be passed as the "arg" argument to "fun". + + Note that MHD will not generate any log messages without the + MHD_USE_ERROR_LOG flag set and if MHD was compiled with the + "-disable-messages" flag. + + ‘MHD_OPTION_THREAD_POOL_SIZE’ + Number (unsigned int) of threads in thread pool. Enable + thread pooling by setting this value to to something greater + than 1. Currently, thread mode must be + MHD_USE_INTERNAL_POLLING_THREAD if thread pooling is enabled + (‘MHD_start_daemon’ returns ‘NULL’ for an unsupported thread + mode). + + ‘MHD_OPTION_ARRAY’ + This option can be used for initializing MHD using options + from an array. A common use for this is writing an FFI for + MHD. The actual options given are in an array of 'struct + MHD_OptionItem', so this option requires a single argument of + type 'struct MHD_OptionItem'. The array must be terminated + with an entry ‘MHD_OPTION_END’. + + An example for code using MHD_OPTION_ARRAY is: + struct MHD_OptionItem ops[] = { + { MHD_OPTION_CONNECTION_LIMIT, 100, NULL }, + { MHD_OPTION_CONNECTION_TIMEOUT, 10, NULL }, + { MHD_OPTION_END, 0, NULL } + }; + d = MHD_start_daemon(0, 8080, NULL, NULL, dh, NULL, + MHD_OPTION_ARRAY, ops, + MHD_OPTION_END); + For options that expect a single pointer argument, the second + member of the ‘struct MHD_OptionItem’ is ignored. For options + that expect two pointer arguments, the first argument must be + cast to ‘intptr_t’. + + ‘MHD_OPTION_UNESCAPE_CALLBACK’ + + Specify a function that should be called for unescaping escape + sequences in URIs and URI arguments. Note that this function + will NOT be used by the MHD_PostProcessor. If this option is + not specified, the default method will be used which decodes + escape sequences of the form "%HH". This option should be + followed by two arguments, the first one must be of the form + + size_t my_unescaper(void * cls, struct MHD_Connection *c, char *s) + + where the return value must be ‘strlen(s)’ and ‘s’ should be + updated. Note that the unescape function must not lengthen + ‘s’ (the result must be shorter than the input and still be + 0-terminated). ‘cls’ will be set to the second argument + following MHD_OPTION_UNESCAPE_CALLBACK. + + ‘MHD_OPTION_THREAD_STACK_SIZE’ + Maximum stack size for threads created by MHD. This option + must be followed by a ‘size_t’). Not specifying this option + or using a value of zero means using the system default (which + is likely to differ based on your platform). + + ‘MHD_OPTION_TCP_FASTQUEUE_QUEUE_SIZE’ + When the flag ‘MHD_USE_TCP_FASTOPEN’ is used, this option sets + the connection handshake queue size for the TCP FASTOPEN + connections. Note that a TCP FASTOPEN connection handshake + occupies more resources than a TCP handshake as the SYN + packets also contain DATA which is kept in the associate state + until handshake is completed. If this option is not given the + queue size is set to a default value of 10. This option must + be followed by a ‘unsigned int’. + + ‘MHD_OPTION_HTTPS_MEM_DHPARAMS’ + Memory pointer for the Diffie-Hellman parameters (dh.pem) to + be used by the HTTPS daemon for key exchange. This option + must be followed by a ‘const char *’ argument. The argument + would be a zero-terminated string with a PEM encoded PKCS3 DH + parameters structure suitable for passing to + ‘gnutls_dh_parms_import_pkcs3’. + + ‘MHD_OPTION_LISTENING_ADDRESS_REUSE’ + This option must be followed by a ‘unsigned int’ argument. If + this option is present and true (nonzero) parameter is given, + allow reusing the address:port of the listening socket (using + ‘SO_REUSEPORT’ on most platforms, and ‘SO_REUSEADDR’ on + Windows). If a false (zero) parameter is given, disallow + reusing the the address:port of the listening socket (this + usually requires no special action, but ‘SO_EXCLUSIVEADDRUSE’ + is needed on Windows). If this option is not present + ‘SO_REUSEADDR’ is used on all platforms except Windows so + reusing of address:port is disallowed. + + -- C Struct: MHD_OptionItem + Entry in an MHD_OPTION_ARRAY. See the ‘MHD_OPTION_ARRAY’ option + argument for its use. + + The ‘option’ member is used to specify which option is specified in + the array. The other members specify the respective argument. + + Note that for options taking only a single pointer, the ‘ptr_value’ + member should be set. For options taking two pointer arguments, + the first pointer must be cast to ‘intptr_t’ and both the ‘value’ + and the ‘ptr_value’ members should be used to pass the two + pointers. + + -- Enumeration: MHD_ValueKind + The ‘MHD_ValueKind’ specifies the source of the key-value pairs in + the HTTP protocol. + + ‘MHD_HEADER_KIND’ + HTTP header. + + ‘MHD_COOKIE_KIND’ + Cookies. Note that the original HTTP header containing the + cookie(s) will still be available and intact. + + ‘MHD_POSTDATA_KIND’ + ‘POST’ data. This is available only if a content encoding + supported by MHD is used (currently only URL encoding), and + only if the posted content fits within the available memory + pool. Note that in that case, the upload data given to the + ‘MHD_AccessHandlerCallback()’ will be empty (since it has + already been processed). + + ‘MHD_GET_ARGUMENT_KIND’ + ‘GET’ (URI) arguments. + + ‘MHD_FOOTER_KIND’ + HTTP footer (only for http 1.1 chunked encodings). + + -- Enumeration: MHD_RequestTerminationCode + The ‘MHD_RequestTerminationCode’ specifies reasons why a request + has been terminated (or completed). + + ‘MHD_REQUEST_TERMINATED_COMPLETED_OK’ + We finished sending the response. + + ‘MHD_REQUEST_TERMINATED_WITH_ERROR’ + Error handling the connection (resources exhausted, other side + closed connection, application error accepting request, etc.) + + ‘MHD_REQUEST_TERMINATED_TIMEOUT_REACHED’ + No activity on the connection for the number of seconds + specified using ‘MHD_OPTION_CONNECTION_TIMEOUT’. + + ‘MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN’ + We had to close the session since MHD was being shut down. + + -- Enumeration: MHD_ResponseMemoryMode + The ‘MHD_ResponeMemoryMode’ specifies how MHD should treat the + memory buffer given for the response in + ‘MHD_create_response_from_buffer’. + + ‘MHD_RESPMEM_PERSISTENT’ + Buffer is a persistent (static/global) buffer that won't + change for at least the lifetime of the response, MHD should + just use it, not free it, not copy it, just keep an alias to + it. + + ‘MHD_RESPMEM_MUST_FREE’ + Buffer is heap-allocated with ‘malloc’ (or equivalent) and + should be freed by MHD after processing the response has + concluded (response reference counter reaches zero). + + ‘MHD_RESPMEM_MUST_COPY’ + Buffer is in transient memory, but not on the heap (for + example, on the stack or non-malloc allocated) and only valid + during the call to ‘MHD_create_response_from_buffer’. MHD + must make its own private copy of the data for processing. + + -- Enumeration: MHD_ResponseFlags + Response-specific flags. Passed as an argument to + ‘MHD_set_response_options()’. + + ‘MHD_RF_NONE’ + No special handling. + + ‘MHD_RF_HTTP_VERSION_1_0_ONLY’ + Only respond in conservative HTTP 1.0-mode. In particular, do + not (automatically) sent "Connection" headers and always close + the connection after generating the response. + + By default, MHD will respond using the same HTTP version which + was set in the request. You can also set the + ‘MHD_RF_HTTP_VERSION_1_0_RESPONSE’ flag to force version 1.0 + in the response. + + ‘MHD_RF_HTTP_VERSION_1_0_RESPONSE’ + Only respond in HTTP 1.0-mode. Contrary to the + ‘MHD_RF_HTTP_VERSION_1_0_ONLY’ flag, the response's HTTP + version will always be set to 1.0 and "Connection" headers are + still supported. + + You can even combine this option with + MHD_RF_HTTP_VERSION_1_0_ONLY to change the response's HTTP + version while maintaining strict compliance with HTTP 1.0 + regarding connection management. + + This solution is not perfect as this flag is set on the + response which is created after header processing. So MHD + will behave as a HTTP 1.1 server until the response is queued. + It means that an invalid HTTP 1.1 request will fail even if + the response is sent with HTTP 1.0 and the request would be + valid if interpreted with this version. For example, this + request will fail in strict mode: + + GET / HTTP/1.1 + + as the "Host" header is missing and is mandatory in HTTP 1.1, + but it should succeed when interpreted with HTTP 1.0. + + ‘MHD_RF_INSANITY_HEADER_CONTENT_LENGTH’ + Disable sanity check preventing clients from manually setting + the HTTP content length option. + + -- Enumeration: MHD_ResponseOptions + Response-specific options. Passed in the varargs portion of + ‘MHD_set_response_options()’. + + ‘MHD_RO_END’ + No more options / last option. This is used to terminate the + VARARGs list. + + -- Enumeration: MHD_WEBSOCKET_FLAG + Options for the MHD websocket stream. + + This is used for initialization of a websocket stream when calling + ‘MHD_websocket_stream_init’ or ‘MHD_websocket_stream_init2’ and + alters the behavior of the websocket stream. + + Note that websocket streams are only available if you include the + header file ‘microhttpd_ws.h’ and compiled _libmicrohttpd_ with + websockets. + + ‘MHD_WEBSOCKET_FLAG_SERVER’ + The websocket stream is initialized in server mode (default). + Thus all outgoing payload will not be masked. All incoming + payload must be masked. + + This flag cannot be used together with + ‘MHD_WEBSOCKET_FLAG_CLIENT’. + + ‘MHD_WEBSOCKET_FLAG_CLIENT’ + The websocket stream is initialized in client mode. You will + usually never use that mode in combination with + _libmicrohttpd_, because _libmicrohttpd_ provides a server and + not a client. In client mode all outgoing payload will be + masked (XOR-ed with random values). All incoming payload must + be unmasked. If you use this mode, you must always call + ‘MHD_websocket_stream_init2’ instead of + ‘MHD_websocket_stream_init’, because you need to pass a random + number generator callback function for masking. + + This flag cannot be used together with + ‘MHD_WEBSOCKET_FLAG_SERVER’. + + ‘MHD_WEBSOCKET_FLAG_NO_FRAGMENTS’ + You don't want to get fragmented data while decoding + (default). Fragmented frames will be internally put together + until they are complete. Whether or not data is fragmented is + decided by the sender of the data during encoding. + + This cannot be used together with + ‘MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS’. + + ‘MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS’ + You want fragmented data, if it appears while decoding. You + will receive the content of the fragmented frame, but if you + are decoding text, you will never get an unfinished UTF-8 + sequence (if the sequence appears between two fragments). + Instead the text will end before the unfinished UTF-8 + sequence. With the next fragment, which finishes the UTF-8 + sequence, you will get the complete UTF-8 sequence. + + This cannot be used together with + ‘MHD_WEBSOCKET_FLAG_NO_FRAGMENTS’. + + ‘MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR’ + If the websocket stream becomes invalid during decoding due to + protocol errors, a matching close frame will automatically be + generated. The close frame will be returned via the + parameters ‘payload’ and ‘payload_len’ of + ‘MHD_websocket_decode’ and the return value is negative (a + value of ‘enum MHD_WEBSOCKET_STATUS’). + + The generated close frame must be freed by the caller with + ‘MHD_websocket_free’. + + -- Enumeration: MHD_WEBSOCKET_FRAGMENTATION + This enumeration is used to specify the fragmentation behavior when + encoding of data (text/binary) for a websocket stream. This is + used with ‘MHD_websocket_encode_text’ or + ‘MHD_websocket_encode_binary’. + + Note that websocket streams are only available if you include the + header file ‘microhttpd_ws.h’ and compiled _libmicrohttpd_ with + websockets. + + ‘MHD_WEBSOCKET_FRAGMENTATION_NONE’ + You don't want to use fragmentation. The encoded frame + consists of only one frame. + + ‘MHD_WEBSOCKET_FRAGMENTATION_FIRST’ + You want to use fragmentation. The encoded frame is the first + frame of a series of data frames of the same type (text or + binary). You may send control frames (ping, pong or close) + between these data frames. + + ‘MHD_WEBSOCKET_FRAGMENTATION_FOLLOWING’ + You want to use fragmentation. The encoded frame is not the + first frame of the series of data frames, but also not the + last one. You may send control frames (ping, pong or close) + between these data frames. + + ‘MHD_WEBSOCKET_FRAGMENTATION_LAST’ + You want to use fragmentation. The encoded frame is the last + frame of the series of data frames, but also not the first + one. After this frame, you may send all types of frames + again. + + -- Enumeration: MHD_WEBSOCKET_STATUS + This enumeration is used for the return value of almost every + websocket stream function. Errors are negative and values equal to + or above zero mean a success. Positive values are only used by + ‘MHD_websocket_decode’. + + Note that websocket streams are only available if you include the + header file ‘microhttpd_ws.h’ and compiled _libmicrohttpd_ with + websockets. + + ‘MHD_WEBSOCKET_STATUS_OK’ + The call succeeded. Especially for ‘MHD_websocket_decode’ + this means that no error occurred, but also no frame has been + completed yet. For other functions this means simply a + success. + + ‘MHD_WEBSOCKET_STATUS_TEXT_FRAME’ + ‘MHD_websocket_decode’ has decoded a text frame. The + parameters ‘payload’ and ‘payload_len’ are filled with the + decoded text (if any). You must free the returned ‘payload’ + after use with ‘MHD_websocket_free’. + + ‘MHD_WEBSOCKET_STATUS_BINARY_FRAME’ + ‘MHD_websocket_decode’ has decoded a binary frame. The + parameters ‘payload’ and ‘payload_len’ are filled with the + decoded binary data (if any). You must free the returned + ‘payload’ after use with ‘MHD_websocket_free’. + + ‘MHD_WEBSOCKET_STATUS_CLOSE_FRAME’ + ‘MHD_websocket_decode’ has decoded a close frame. This means + you must close the socket using ‘MHD_upgrade_action’ with + ‘MHD_UPGRADE_ACTION_CLOSE’. You may respond with a close + frame before closing. The parameters ‘payload’ and + ‘payload_len’ are filled with the close reason (if any). The + close reason starts with a two byte sequence of close code in + network byte order (see ‘enum MHD_WEBSOCKET_CLOSEREASON’). + After these two bytes a UTF-8 encoded close reason may follow. + You can call ‘MHD_websocket_split_close_reason’ to split that + close reason. You must free the returned ‘payload’ after use + with ‘MHD_websocket_free’. + + ‘MHD_WEBSOCKET_STATUS_PING_FRAME’ + ‘MHD_websocket_decode’ has decoded a ping frame. You should + respond to this with a pong frame. The pong frame must + contain the same binary data as the corresponding ping frame + (if it had any). The parameters ‘payload’ and ‘payload_len’ + are filled with the binary ping data (if any). You must free + the returned ‘payload’ after use with ‘MHD_websocket_free’. + + ‘MHD_WEBSOCKET_STATUS_PONG_FRAME’ + ‘MHD_websocket_decode’ has decoded a pong frame. You should + usually only receive pong frames if you sent a ping frame + before. The binary data should be equal to your ping frame + and can be used to distinguish the response if you sent + multiple ping frames. The parameters ‘payload’ and + ‘payload_len’ are filled with the binary pong data (if any). + You must free the returned ‘payload’ after use with + ‘MHD_websocket_free’. + + ‘MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT’ + ‘MHD_websocket_decode’ has decoded a text frame fragment. The + parameters ‘payload’ and ‘payload_len’ are filled with the + decoded text (if any). This is like + ‘MHD_WEBSOCKET_STATUS_TEXT_FRAME’, but it can only appear if + you specified ‘MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS’ during the + call of ‘MHD_websocket_stream_init’ or + ‘MHD_websocket_stream_init2’. You must free the returned + ‘payload’ after use with ‘MHD_websocket_free’. + + ‘MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT’ + ‘MHD_websocket_decode’ has decoded a binary frame fragment. + The parameters ‘payload’ and ‘payload_len’ are filled with the + decoded binary data (if any). This is like + ‘MHD_WEBSOCKET_STATUS_BINARY_FRAME’, but it can only appear if + you specified ‘MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS’ during the + call of ‘MHD_websocket_stream_init’ or + ‘MHD_websocket_stream_init2’. You must free the returned + ‘payload’ after use with ‘MHD_websocket_free’. + + ‘MHD_WEBSOCKET_STATUS_TEXT_NEXT_FRAGMENT’ + ‘MHD_websocket_decode’ has decoded the next text frame + fragment. The parameters ‘payload’ and ‘payload_len’ are + filled with the decoded text (if any). This is like + ‘MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT’, but it appears + only after the first and before the last fragment of a series + of fragments. It can only appear if you specified + ‘MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS’ during the call of + ‘MHD_websocket_stream_init’ or ‘MHD_websocket_stream_init2’. + You must free the returned ‘payload’ after use with + ‘MHD_websocket_free’. + + ‘MHD_WEBSOCKET_STATUS_BINARY_NEXT_FRAGMENT’ + ‘MHD_websocket_decode’ has decoded the next binary frame + fragment. The parameters ‘payload’ and ‘payload_len’ are + filled with the decoded binary data (if any). This is like + ‘MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT’, but it appears + only after the first and before the last fragment of a series + of fragments. It can only appear if you specified + ‘MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS’ during the call of + ‘MHD_websocket_stream_init’ or ‘MHD_websocket_stream_init2’. + You must free the returned ‘payload’ after use with + ‘MHD_websocket_free’. + + ‘MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT’ + ‘MHD_websocket_decode’ has decoded the last text frame + fragment. The parameters ‘payload’ and ‘payload_len’ are + filled with the decoded text (if any). This is like + ‘MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT’, but it appears + only for the last fragment of a series of fragments. It can + only appear if you specified + ‘MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS’ during the call of + ‘MHD_websocket_stream_init’ or ‘MHD_websocket_stream_init2’. + You must free the returned ‘payload’ after use with + ‘MHD_websocket_free’. + + ‘MHD_WEBSOCKET_STATUS_BINARY_LAST_FRAGMENT’ + ‘MHD_websocket_decode’ has decoded the last binary frame + fragment. The parameters ‘payload’ and ‘payload_len’ are + filled with the decoded binary data (if any). This is like + ‘MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT’, but it appears + only for the last fragment of a series of fragments. It can + only appear if you specified + ‘MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS’ during the call of + ‘MHD_websocket_stream_init’ or ‘MHD_websocket_stream_init2’. + You must free the returned ‘payload’ after use with + ‘MHD_websocket_free’. + + ‘MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR’ + The call failed and the stream is invalid now for decoding. + You must close the websocket now using ‘MHD_upgrade_action’ + with ‘MHD_UPGRADE_ACTION_CLOSE’. You may send a close frame + before closing. This is only used by ‘MHD_websocket_decode’ + and happens if the stream contains errors (i. e. invalid + byte data). + + ‘MHD_WEBSOCKET_STATUS_STREAM_BROKEN’ + You tried to decode something, but the stream has already been + marked invalid. You must close the websocket now using + ‘MHD_upgrade_action’ with ‘MHD_UPGRADE_ACTION_CLOSE’. You may + send a close frame before closing. This is only used by + ‘MHD_websocket_decode’ and happens if you call + ‘MDM_websocket_decode’ again after has been invalidated. You + can call ‘MHD_websocket_stream_is_valid’ at any time to check + whether a stream is invalid or not. + + ‘MHD_WEBSOCKET_STATUS_MEMORY_ERROR’ + A memory allocation failed. The stream remains valid. If + this occurred while decoding, the decoding could be possible + later if enough memory is available. This could happen while + decoding if you received a too big data frame. You could try + to specify max_payload_size during the call of + ‘MHD_websocket_stream_init’ or ‘MHD_websocket_stream_init2’ to + avoid this and close the websocket instead. + + ‘MHD_WEBSOCKET_STATUS_PARAMETER_ERROR’ + You passed invalid parameters during the function call (i. e. + a NULL pointer for a required parameter). The stream remains + valid. + + ‘MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED’ + The maximum payload size has been exceeded. If you got this + return code from ‘MHD_websocket_decode’ then the stream + becomes invalid and the websocket must be closed using + ‘MHD_upgrade_action’ with ‘MHD_UPGRADE_ACTION_CLOSE’. You may + send a close frame before closing. The maximum payload size + is specified during the call of ‘MHD_websocket_stream_init’ or + ‘MHD_websocket_stream_init2’. This can also appear if you + specified 0 as maximum payload size when the message is + greater than the maximum allocatable memory size (i. e. more + than 4 GiB on 32 bit systems). If you got this return code + from ‘MHD_websocket_encode_close’, ‘MHD_websocket_encode_ping’ + or ‘MHD_websocket_encode_pong’ then you passed to much payload + data. The stream remains valid then. + + ‘MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR’ + An UTF-8 sequence is invalid. If you got this return code + from ‘MHD_websocket_decode’ then the stream becomes invalid + and you must close the websocket using ‘MHD_upgrade_action’ + with ‘MHD_UPGRADE_ACTION_CLOSE’. You may send a close frame + before closing. If you got this from + ‘MHD_websocket_encode_text’ or ‘MHD_websocket_encode_close’ + then you passed invalid UTF-8 text. The stream remains valid + then. + + ‘MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER’ + A check routine for the HTTP headers came to the conclusion + that the header value isn't valid for a websocket handshake + request. This value can only be returned from the following + functions: ‘MHD_websocket_check_http_version’, + ‘MHD_websocket_check_connection_header’, + ‘MHD_websocket_check_upgrade_header’, + ‘MHD_websocket_check_version_header’, + ‘MHD_websocket_create_accept_header’ + + -- Enumeration: MHD_WEBSOCKET_CLOSEREASON + Enumeration of possible close reasons for websocket close frames. + + The possible values are specified in RFC 6455 7.4.1 These close + reasons here are the default set specified by RFC 6455, but also + other close reasons could be used. + + The definition is for short: + • 0-999 are never used (if you pass 0 in + ‘MHD_websocket_encode_close’ then no close reason is used). + • 1000-2999 are specified by RFC 6455. + • 3000-3999 are specified by libraries, etc. but must be + registered by IANA. + • 4000-4999 are reserved for private use. + + Note that websocket streams are only available if you include the + header file ‘microhttpd_ws.h’ and compiled _libmicrohttpd_ with + websockets. + + ‘MHD_WEBSOCKET_CLOSEREASON_NO_REASON’ + This value is used as placeholder for + ‘MHD_websocket_encode_close’ to tell that you don't want to + specify any reason. If you use this value then no reason text + may be used. This value cannot be a result of decoding, + because this value is not a valid close reason for the + websocket protocol. + + ‘MHD_WEBSOCKET_CLOSEREASON_REGULAR’ + You close the websocket because it fulfilled its purpose and + shall now be closed in a normal, planned way. + + ‘MHD_WEBSOCKET_CLOSEREASON_GOING_AWAY’ + You close the websocket because you are shutting down the + server or something similar. + + ‘MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR’ + You close the websocket because a protocol error occurred + during decoding (i. e. invalid byte data). + + ‘MHD_WEBSOCKET_CLOSEREASON_UNSUPPORTED_DATATYPE’ + You close the websocket because you received data which you + don't accept. For example if you received a binary frame, but + your application only expects text frames. + + ‘MHD_WEBSOCKET_CLOSEREASON_MALFORMED_UTF8’ + You close the websocket because it contains malformed UTF-8. + The UTF-8 validity is automatically checked by + ‘MHD_websocket_decode’, so you don't need to check it on your + own. UTF-8 is specified in RFC 3629. + + ‘MHD_WEBSOCKET_CLOSEREASON_POLICY_VIOLATED’ + You close the websocket because you received a frame which is + too big to process. You can specify the maximum allowed + payload size during the call of ‘MHD_websocket_stream_init’ or + ‘MHD_websocket_stream_init2’. + + ‘MHD_WEBSOCKET_CLOSEREASON_MISSING_EXTENSION’ + This status code can be sent by the client if it expected a + specific extension, but this extension hasn't been negotiated. + + ‘MHD_WEBSOCKET_CLOSEREASON_UNEXPECTED_CONDITION’ + The server closes the websocket because it encountered an + unexpected condition that prevented it from fulfilling the + request. + + -- Enumeration: MHD_WEBSOCKET_UTF8STEP + Enumeration of possible UTF-8 check steps for websocket functions + + These values are used during the encoding of fragmented text frames + or for error analysis while encoding text frames. Its values + specify the next step of the UTF-8 check. UTF-8 sequences consist + of one to four bytes. This enumeration just says how long the + current UTF-8 sequence is and what is the next expected byte. + + Note that websocket streams are only available if you include the + header file ‘microhttpd_ws.h’ and compiled _libmicrohttpd_ with + websockets. + + ‘MHD_WEBSOCKET_UTF8STEP_NORMAL’ + There is no open UTF-8 sequence. The next byte must be + 0x00-0x7F or 0xC2-0xF4. + + ‘MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1’ + The second byte of a two byte UTF-8 sequence. The first byte + was 0xC2-0xDF. The next byte must be 0x80-0xBF. + + ‘MHD_WEBSOCKET_UTF8STEP_UTF3TAIL1_1OF2’ + The second byte of a three byte UTF-8 sequence. The first + byte was 0xE0. The next byte must be 0xA0-0xBF. + + ‘MHD_WEBSOCKET_UTF8STEP_UTF3TAIL2_1OF2’ + The second byte of a three byte UTF-8 sequence. The first + byte was 0xED. The next byte must by 0x80-0x9F. + + ‘MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_1OF2’ + The second byte of a three byte UTF-8 sequence. The first + byte was 0xE1-0xEC or 0xEE-0xEF. The next byte must be + 0x80-0xBF. + + ‘MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2’ + The third byte of a three byte UTF-8 sequence. The next byte + must be 0x80-0xBF. + + ‘MHD_WEBSOCKET_UTF8STEP_UTF4TAIL1_1OF3’ + The second byte of a four byte UTF-8 sequence. The first byte + was 0xF0. The next byte must be 0x90-0xBF. + + ‘MHD_WEBSOCKET_UTF8STEP_UTF4TAIL2_1OF3’ + The second byte of a four byte UTF-8 sequence. The first byte + was 0xF4. The next byte must be 0x80-0x8F. + + ‘MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_1OF3’ + The second byte of a four byte UTF-8 sequence. The first byte + was 0xF1-0xF3. The next byte must be 0x80-0xBF. + + ‘MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3’ + The third byte of a four byte UTF-8 sequence. The next byte + must be 0x80-0xBF. + + ‘MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_3OF3’ + The fourth byte of a four byte UTF-8 sequence. The next byte + must be 0x80-0xBF. + + -- Enumeration: MHD_WEBSOCKET_VALIDITY + Enumeration of validity values of a websocket stream + + These values are used for ‘MHD_websocket_stream_is_valid’ and + specify the validity status. + + Note that websocket streams are only available if you include the + header file ‘microhttpd_ws.h’ and compiled _libmicrohttpd_ with + websockets. + + ‘MHD_WEBSOCKET_VALIDITY_INVALID’ + The stream is invalid. It cannot be used for decoding + anymore. + + ‘MHD_WEBSOCKET_VALIDITY_VALID’ + The stream is valid. Decoding works as expected. + + ‘MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES’ + The stream has received a close frame and is partly invalid. + You can still use the stream for decoding, but if a data frame + is received an error will be reported. After a close frame + has been sent, no data frames may follow from the sender of + the close frame. + + +File: libmicrohttpd.info, Node: microhttpd-struct, Next: microhttpd-cb, Prev: microhttpd-const, Up: Top + +3 Structures type definition +**************************** + + -- C Struct: MHD_Daemon + Handle for the daemon (listening on a socket for HTTP traffic). + + -- C Struct: MHD_Connection + Handle for a connection / HTTP request. With HTTP/1.1, multiple + requests can be run over the same connection. However, MHD will + only show one request per TCP connection to the client at any given + time. + + -- C Struct: MHD_Response + Handle for a response. + + -- C Struct: MHD_IoVec + An element of an array of memory buffers. + + -- C Struct: MHD_PostProcessor + Handle for ‘POST’ processing. + + -- C Union: MHD_ConnectionInfo + Information about a connection. + + -- C Union: MHD_DaemonInfo + Information about an MHD daemon. + + -- C Struct: MHD_WebSocketStream + Information about a MHD websocket stream. + + +File: libmicrohttpd.info, Node: microhttpd-cb, Next: microhttpd-init, Prev: microhttpd-struct, Up: Top + +4 Callback functions definition +******************************* + + -- Function Pointer: enum MHD_Result *MHD_AcceptPolicyCallback (void + *cls, const struct sockaddr * addr, socklen_t addrlen) + Invoked in the context of a connection to allow or deny a client to + connect. This callback return ‘MHD_YES’ if connection is allowed, + ‘MHD_NO’ if not. + + CLS + custom value selected at callback registration time; + ADDR + address information from the client; + ADDRLEN + length of the address information. + + -- Function Pointer: enum MHD_Result *MHD_AccessHandlerCallback (void + *cls, struct MHD_Connection * connection, const char *url, + const char *method, const char *version, const char + *upload_data, size_t *upload_data_size, void **req_cls) + Invoked in the context of a connection to answer a request from the + client. This callback must call MHD functions (example: the + ‘MHD_Response’ ones) to provide content to give back to the client + and return an HTTP status code (i.e. ‘200’ for OK, ‘404’, etc.). + + *note microhttpd-post::, for details on how to code this callback. + + Must return ‘MHD_YES’ if the connection was handled successfully, + ‘MHD_NO’ if the socket must be closed due to a serious error while + handling the request + + CLS + custom value selected at callback registration time; + + URL + the URL requested by the client; + + METHOD + the HTTP method used by the client (‘GET’, ‘PUT’, ‘DELETE’, + ‘POST’, etc.); + + VERSION + the HTTP version string (i.e. ‘HTTP/1.1’); + + UPLOAD_DATA + the data being uploaded (excluding headers): + + ‘POST’ data *will* be made available incrementally in + UPLOAD_DATA; even if ‘POST’ data is available, the first time + the callback is invoked there won't be upload data, as this is + done just after MHD parses the headers. If supported by the + client and the HTTP version, the application can at this point + queue an error response to possibly avoid the upload entirely. + If no response is generated, MHD will (if required) + automatically send a 100 CONTINUE reply to the client. + + Afterwards, POST data will be passed to the callback to be + processed incrementally by the application. The application + may return ‘MHD_NO’ to forcefully terminate the TCP connection + without generating a proper HTTP response. Once all of the + upload data has been provided to the application, the + application will be called again with 0 bytes of upload data. + At this point, a response should be queued to complete the + handling of the request. + + UPLOAD_DATA_SIZE + set initially to the size of the UPLOAD_DATA provided; this + callback must update this value to the number of bytes *NOT* + processed; unless external select is used, the callback maybe + required to process at least some data. If the callback fails + to process data in multi-threaded or internal-select mode and + if the read-buffer is already at the maximum size that MHD is + willing to use for reading (about half of the maximum amount + of memory allowed for the connection), then MHD will abort + handling the connection and return an internal server error to + the client. In order to avoid this, clients must be able to + process upload data incrementally and reduce the value of + ‘upload_data_size’. + + REQ_CLS + reference to a pointer, initially set to ‘NULL’, that this + callback can set to some address and that will be preserved by + MHD for future calls for this request; + + since the access handler may be called many times (i.e., for a + ‘PUT’/‘POST’ operation with plenty of upload data) this allows + the application to easily associate some request-specific + state; + + if necessary, this state can be cleaned up in the global + ‘MHD_RequestCompletedCallback’ (which can be set with the + ‘MHD_OPTION_NOTIFY_COMPLETED’). + + -- Function Pointer: void *MHD_RequestCompletedCallback (void *cls, + struct MHD_Connectionconnection, void **req_cls, enum + MHD_RequestTerminationCode toe) + Signature of the callback used by MHD to notify the application + about completed requests. + + CLS + custom value selected at callback registration time; + + CONNECTION + connection handle; + + REQ_CLS + value as set by the last call to the + ‘MHD_AccessHandlerCallback’; + + TOE + reason for request termination see + ‘MHD_OPTION_NOTIFY_COMPLETED’. + + -- Function Pointer: enum MHD_Result *MHD_KeyValueIterator (void *cls, + enum MHD_ValueKind kind, const char *key, const char *value, + size_t value_size) + Iterator over key-value pairs. This iterator can be used to + iterate over all of the cookies, headers, or ‘POST’-data fields of + a request, and also to iterate over the headers that have been + added to a response. + + CLS + custom value specified when iteration was triggered; + + KIND + kind of the header we are looking at + + KEY + key for the value, can be an empty string + + VALUE + value corresponding value, can be NULL + + VALUE_SIZE + number of bytes in ‘value’. This argument was introduced in + ‘MHD_VERSION’ 0x00096301 to allow applications to use binary + zeros in values. Applications using this argument must ensure + that they are using a sufficiently recent version of MHD, i.e. + by testing ‘MHD_get_version()’ for values above or equal to + 0.9.64. Applications that do not need zeros in values and + that want to compile without warnings against newer versions + of MHD should not declare this argument and cast the function + pointer argument to ‘MHD_KeyValueIterator’. + + Return ‘MHD_YES’ to continue iterating, ‘MHD_NO’ to abort the + iteration. + + -- Function Pointer: ssize_t *MHD_ContentReaderCallback (void *cls, + uint64_t pos, char *buf, size_t max) + Callback used by MHD in order to obtain content. The callback has + to copy at most MAX bytes of content into BUF. The total number of + bytes that has been placed into BUF should be returned. + + Note that returning zero will cause MHD to try again. Thus, + returning zero should only be used in conjunction with + ‘MHD_suspend_connection()’ to avoid busy waiting. + + While usually the callback simply returns the number of bytes + written into BUF, there are two special return value: + + ‘MHD_CONTENT_READER_END_OF_STREAM’ (-1) should be returned for the + regular end of transmission (with chunked encoding, MHD will then + terminate the chunk and send any HTTP footers that might be + present; without chunked encoding and given an unknown response + size, MHD will simply close the connection; note that while + returning ‘MHD_CONTENT_READER_END_OF_STREAM’ is not technically + legal if a response size was specified, MHD accepts this and treats + it just as ‘MHD_CONTENT_READER_END_WITH_ERROR’. + + ‘MHD_CONTENT_READER_END_WITH_ERROR’ (-2) is used to indicate a + server error generating the response; this will cause MHD to simply + close the connection immediately. If a response size was given or + if chunked encoding is in use, this will indicate an error to the + client. Note, however, that if the client does not know a response + size and chunked encoding is not in use, then clients will not be + able to tell the difference between + ‘MHD_CONTENT_READER_END_WITH_ERROR’ and + ‘MHD_CONTENT_READER_END_OF_STREAM’. This is not a limitation of + MHD but rather of the HTTP protocol. + + CLS + custom value selected at callback registration time; + + POS + position in the datastream to access; note that if an + ‘MHD_Response’ object is re-used, it is possible for the same + content reader to be queried multiple times for the same data; + however, if an ‘MHD_Response’ is not re-used, MHD guarantees + that POS will be the sum of all non-negative return values + obtained from the content reader so far. + + Return ‘-1’ on error (MHD will no longer try to read content and + instead close the connection with the client). + + -- Function Pointer: void *MHD_ContentReaderFreeCallback (void *cls) + This method is called by MHD if we are done with a content reader. + It should be used to free resources associated with the content + reader. + + -- Function Pointer: enum MHD_Result *MHD_PostDataIterator (void *cls, + enum MHD_ValueKind kind, const char *key, const char + *filename, const char *content_type, const char + *transfer_encoding, const char *data, uint64_t off, size_t + size) + Iterator over key-value pairs where the value maybe made available + in increments and/or may not be zero-terminated. Used for + processing ‘POST’ data. + + CLS + custom value selected at callback registration time; + + KIND + type of the value; + + KEY + zero-terminated key for the value; + + FILENAME + name of the uploaded file, ‘NULL’ if not known; + + CONTENT_TYPE + mime-type of the data, ‘NULL’ if not known; + + TRANSFER_ENCODING + encoding of the data, ‘NULL’ if not known; + + DATA + pointer to size bytes of data at the specified offset; + + OFF + offset of data in the overall value; + + SIZE + number of bytes in data available. + + Return ‘MHD_YES’ to continue iterating, ‘MHD_NO’ to abort the + iteration. + + -- Function Pointer: void* *MHD_WebSocketMallocCallback (size_t + buf_len) + This callback function is used internally by many websocket + functions for allocating data. By default ‘malloc’ is used. You + can use your own allocation function with + ‘MHD_websocket_stream_init2’ if you wish to. This can be useful + for operating systems like Windows where ‘malloc’, ‘realloc’ and + ‘free’ are compiler-dependent. You can call the associated + ‘malloc’ callback of a websocket stream with + ‘MHD_websocket_malloc’. + + BUF_LEN + size of the buffer to allocate in bytes. + + Return the pointer of the allocated buffer or ‘NULL’ on failure. + + -- Function Pointer: void* *MHD_WebSocketReallocCallback (void *buf, + size_t new_buf_len) + This callback function is used internally by many websocket + functions for reallocating data. By default ‘realloc’ is used. + You can use your own reallocation function with + ‘MHD_websocket_stream_init2’ if you wish to. This can be useful + for operating systems like Windows where ‘malloc’, ‘realloc’ and + ‘free’ are compiler-dependent. You can call the associated + ‘realloc’ callback of a websocket stream with + ‘MHD_websocket_realloc’. + + BUF + current buffer, may be ‘NULL’; + + NEW_BUF_LEN + new size of the buffer in bytes. + + Return the pointer of the reallocated buffer or ‘NULL’ on failure. + On failure the old pointer must remain valid. + + -- Function Pointer: void *MHD_WebSocketFreeCallback (void *buf) + This callback function is used internally by many websocket + functions for freeing data. By default ‘free’ is used. You can + use your own free function with ‘MHD_websocket_stream_init2’ if you + wish to. This can be useful for operating systems like Windows + where ‘malloc’, ‘realloc’ and ‘free’ are compiler-dependent. You + can call the associated ‘free’ callback of a websocket stream with + ‘MHD_websocket_free’. + + CLS + current buffer to free, this may be ‘NULL’ then nothing + happens. + + -- Function Pointer: size_t *MHD_WebSocketRandomNumberGenerator (void + *cls, void* buf, size_t buf_len) + This callback function is used for generating random numbers for + masking payload data in client mode. If you use websockets in + server mode with _libmicrohttpd_ then you don't need a random + number generator, because the server doesn't mask its outgoing + messages. However if you wish to use a websocket stream in client + mode, you must pass this callback function to + ‘MHD_websocket_stream_init2’. + + CLS + closure specified in ‘MHD_websocket_stream_init2’; + BUF + buffer to fill with random values; + BUF_LEN + size of buffer in bytes. + + Return the number of generated random bytes. The return value + should usually equal to buf_len. + + +File: libmicrohttpd.info, Node: microhttpd-init, Next: microhttpd-inspect, Prev: microhttpd-cb, Up: Top + +5 Starting and stopping the server +********************************** + + -- Function: void MHD_set_panic_func (MHD_PanicCallback cb, void *cls) + Set a handler for fatal errors. + + CB + function to call if MHD encounters a fatal internal error. If + no handler was set explicitly, MHD will call ‘abort’. + + CLS + closure argument for cb; the other arguments are the name of + the source file, line number and a string describing the + nature of the fatal error (which can be ‘NULL’) + + -- Function: struct MHD_Daemon * MHD_start_daemon (unsigned int flags, + unsigned short port, MHD_AcceptPolicyCallback apc, void + *apc_cls, MHD_AccessHandlerCallback dh, void *dh_cls, ...) + Start a webserver on the given port. + + FLAGS + OR-ed combination of ‘MHD_FLAG’ values; + + PORT + port to bind to; + + APC + callback to call to check which clients will be allowed to + connect; you can pass ‘NULL’ in which case connections from + any IP will be accepted; + + APC_CLS + extra argument to APC; + + DH + default handler for all URIs; + + DH_CLS + extra argument to DH. + + Additional arguments are a list of options (type-value pairs, + terminated with ‘MHD_OPTION_END’). It is mandatory to use + ‘MHD_OPTION_END’ as last argument, even when there are no + additional arguments. + + Return ‘NULL’ on error, handle to daemon on success. + + -- Function: MHD_socket MHD_quiesce_daemon (struct MHD_Daemon *daemon) + Stop accepting connections from the listening socket. Allows + clients to continue processing, but stops accepting new + connections. Note that the caller is responsible for closing the + returned socket; however, if MHD is run using threads (anything but + external select mode), it must not be closed until AFTER + ‘MHD_stop_daemon’ has been called (as it is theoretically possible + that an existing thread is still using it). + + This function is useful in the special case that a listen socket is + to be migrated to another process (i.e. a newer version of the + HTTP server) while existing connections should continue to be + processed until they are finished. + + Return ‘-1’ on error (daemon not listening), the handle to the + listen socket otherwise. + + -- Function: void MHD_stop_daemon (struct MHD_Daemon *daemon) + Shutdown an HTTP daemon. + + -- Function: enum MHD_Result MHD_run (struct MHD_Daemon *daemon) + Run webserver operations (without blocking unless in client + callbacks). This method should be called by clients in combination + with ‘MHD_get_fdset()’ if the client-controlled ‘select’-method is + used. + + This function will work for external ‘poll’ and ‘select’ mode. + However, if using external ‘select’ mode, you may want to instead + use ‘MHD_run_from_select’, as it is more efficient. + + DAEMON + daemon to process connections of + + Return ‘MHD_YES’ on success, ‘MHD_NO’ if this daemon was not + started with the right options for this call. + + -- Function: enum MHD_Result MHD_run_from_select (struct MHD_Daemon + *daemon, const fd_set *read_fd_set, const fd_set + *write_fd_set, const fd_set *except_fd_set) + Run webserver operations given sets of ready socket handles. + + This method should be called by clients in combination with + ‘MHD_get_fdset’ if the client-controlled (external) select method + is used. + + You can use this function instead of ‘MHD_run’ if you called + ‘select’ on the result from ‘MHD_get_fdset’. File descriptors in + the sets that are not controlled by MHD will be ignored. Calling + this function instead of ‘MHD_run’ is more efficient as MHD will + not have to call ‘select’ again to determine which operations are + ready. + + DAEMON + daemon to process connections of + READ_FD_SET + set of descriptors that must be ready for reading without + blocking + WRITE_FD_SET + set of descriptors that must be ready for writing without + blocking + EXCEPT_FD_SET + ignored, can be NULL + + Return ‘MHD_YES’ on success, ‘MHD_NO’ on serious internal errors. + + -- Function: void MHD_add_connection (struct MHD_Daemon *daemon, int + client_socket, const struct sockaddr *addr, socklen_t addrlen) + Add another client connection to the set of connections managed by + MHD. This API is usually not needed (since MHD will accept inbound + connections on the server socket). Use this API in special cases, + for example if your HTTP server is behind NAT and needs to connect + out to the HTTP client, or if you are building a proxy. + + If you use this API in conjunction with a internal select or a + thread pool, you must set the option ‘MHD_USE_ITC’ to ensure that + the freshly added connection is immediately processed by MHD. + + The given client socket will be managed (and closed!) by MHD after + this call and must no longer be used directly by the application + afterwards. + + DAEMON + daemon that manages the connection + CLIENT_SOCKET + socket to manage (MHD will expect to receive an HTTP request + from this socket next). + ADDR + IP address of the client + ADDRLEN + number of bytes in addr + + This function will return ‘MHD_YES’ on success, ‘MHD_NO’ if this + daemon could not handle the connection (i.e. malloc failed, etc). + The socket will be closed in any case; 'errno' is set to indicate + further details about the error. + + +File: libmicrohttpd.info, Node: microhttpd-inspect, Next: microhttpd-requests, Prev: microhttpd-init, Up: Top + +6 Implementing external ‘select’ +******************************** + + -- Function: enum MHD_Result MHD_get_fdset (struct MHD_Daemon *daemon, + fd_set * read_fd_set, fd_set * write_fd_set, fd_set * + except_fd_set, int *max_fd) + Obtain the ‘select()’ sets for this daemon. The daemon's socket is + added to READ_FD_SET. The list of currently existent connections + is scanned and their file descriptors added to the correct set. + + When calling this function, FD_SETSIZE is assumed to be platform's + default. If you changed FD_SETSIZE for your application, you + should use ‘MHD_get_fdset2()’ instead. + + This function should only be called in when MHD is configured to + use external select with ‘select()’ or with ‘epoll()’. In the + latter case, it will only add the single ‘epoll()’ file descriptor + used by MHD to the sets. + + After the call completed successfully: the variable referenced by + MAX_FD references the file descriptor with highest integer + identifier. The variable must be set to zero before invoking this + function. + + Return ‘MHD_YES’ on success, ‘MHD_NO’ if: the arguments are invalid + (example: ‘NULL’ pointers); this daemon was not started with the + right options for this call. + + -- Function: enum MHD_Result MHD_get_fdset2 (struct MHD_Daemon *daemon, + fd_set * read_fd_set, fd_set * write_fd_set, fd_set * + except_fd_set, int *max_fd, unsigned int fd_setsize) + Like ‘MHD_get_fdset()’, except that you can manually specify the + value of FD_SETSIZE used by your application. + + -- Function: enum MHD_Result MHD_get_timeout (struct MHD_Daemon + *daemon, unsigned long long *timeout) + Obtain timeout value for select for this daemon (only needed if + connection timeout is used). The returned value is how many + milliseconds ‘select’ should at most block, not the timeout value + set for connections. This function must not be called if the + ‘MHD_USE_THREAD_PER_CONNECTION’ mode is in use (since then it is + not meaningful to ask for a timeout, after all, there is + concurrenct activity). The function must also not be called by + user-code if ‘MHD_USE_INTERNAL_POLLING_THREAD’ is in use. In the + latter case, the behavior is undefined. + + DAEMON + which daemon to obtain the timeout from. + TIMEOUT + will be set to the timeout (in milliseconds). + + Return ‘MHD_YES’ on success, ‘MHD_NO’ if timeouts are not used (or + no connections exist that would necessitate the use of a timeout + right now). + + +File: libmicrohttpd.info, Node: microhttpd-requests, Next: microhttpd-responses, Prev: microhttpd-inspect, Up: Top + +7 Handling requests +******************* + + -- Function: int MHD_get_connection_values (struct MHD_Connection + *connection, enum MHD_ValueKind kind, MHD_KeyValueIterator + iterator, void *iterator_cls) + Get all the headers matching KIND from the request. The KIND + argument can be a bitmask, ORing the various header kinds that are + requested. + + The ITERATOR callback is invoked once for each header, with + ITERATOR_CLS as first argument. After version 0.9.19, the headers + are iterated in the same order as they were received from the + network; previous versions iterated over the headers in reverse + order. + + ‘MHD_get_connection_values’ returns the number of entries iterated + over; this can be less than the number of headers if, while + iterating, ITERATOR returns ‘MHD_NO’. + + ITERATOR can be ‘NULL’: in this case this function just counts and + returns the number of headers. + + In the case of ‘MHD_GET_ARGUMENT_KIND’, the VALUE argument will be + ‘NULL’ if the URL contained a key without an equals operator. For + example, for a HTTP request to the URL "http://foo/bar?key", the + VALUE argument is ‘NULL’; in contrast, a HTTP request to the URL + "http://foo/bar?key=", the VALUE argument is the empty string. The + normal case is that the URL contains "http://foo/bar?key=value" in + which case VALUE would be the string "value" and KEY would contain + the string "key". + + -- Function: enum MHD_Result MHD_set_connection_value (struct + MHD_Connection *connection, enum MHD_ValueKind kind, const + char *key, const char *value) + This function can be used to append an entry to the list of HTTP + headers of a connection (so that the ‘MHD_get_connection_values + function’ will return them - and the MHD PostProcessor will also + see them). This maybe required in certain situations (see Mantis + #1399) where (broken) HTTP implementations fail to supply values + needed by the post processor (or other parts of the application). + + This function MUST only be called from within the + MHD_AccessHandlerCallback (otherwise, access maybe improperly + synchronized). Furthermore, the client must guarantee that the key + and value arguments are 0-terminated strings that are NOT freed + until the connection is closed. (The easiest way to do this is by + passing only arguments to permanently allocated strings.). + + CONNECTION is the connection for which the entry for KEY of the + given KIND should be set to the given VALUE. + + The function returns ‘MHD_NO’ if the operation could not be + performed due to insufficient memory and ‘MHD_YES’ on success. + + -- Function: const char * MHD_lookup_connection_value (struct + MHD_Connection *connection, enum MHD_ValueKind kind, const + char *key) + Get a particular header value. If multiple values match the KIND, + return one of them (the "first", whatever that means). KEY must + reference a zero-terminated ASCII-coded string representing the + header to look for: it is compared against the headers using + (basically) ‘strcasecmp()’, so case is ignored. + + -- Function: const char * MHD_lookup_connection_value_n (struct + MHD_Connection *connection, enum MHD_ValueKind kind, const + char *key, size_t key_size, const char **value_ptr, size_t + *value_size_ptr) + Get a particular header value. If multiple values match the KIND, + return one of them (the "first", whatever that means). KEY must + reference an ASCII-coded string representing the header to look + for: it is compared against the headers using (basically) + ‘strncasecmp()’, so case is ignored. The VALUE_PTR is set to the + address of the value found, and VALUE_SIZE_PTR is set to the number + of bytes in the value. + + +File: libmicrohttpd.info, Node: microhttpd-responses, Next: microhttpd-flow, Prev: microhttpd-requests, Up: Top + +8 Building responses to requests +******************************** + +Response objects handling by MHD is asynchronous with respect to the +application execution flow. Instances of the ‘MHD_Response’ structure +are not associated to a daemon and neither to a client connection: they +are managed with reference counting. + + In the simplest case: we allocate a new ‘MHD_Response’ structure for +each response, we use it once and finally we destroy it. + + MHD allows more efficient resources usages. + + Example: we allocate a new ‘MHD_Response’ structure for each response +*kind*, we use it every time we have to give that response and we +finally destroy it only when the daemon shuts down. + +* Menu: + +* microhttpd-response enqueue:: Enqueuing a response. +* microhttpd-response create:: Creating a response object. +* microhttpd-response headers:: Adding headers to a response. +* microhttpd-response options:: Setting response options. +* microhttpd-response inspect:: Inspecting a response object. +* microhttpd-response upgrade:: Creating a response for protocol upgrades. + + +File: libmicrohttpd.info, Node: microhttpd-response enqueue, Next: microhttpd-response create, Up: microhttpd-responses + +8.1 Enqueuing a response +======================== + + -- Function: enum MHD_Result MHD_queue_response (struct MHD_Connection + *connection, unsigned int status_code, struct MHD_Response + *response) + Queue a response to be transmitted to the client as soon as + possible but only after MHD_AccessHandlerCallback returns. This + function checks that it is legal to queue a response at this time + for the given connection. It also increments the internal + reference counter for the response object (the counter will be + decremented automatically once the response has been transmitted). + + CONNECTION + the connection identifying the client; + + STATUS_CODE + HTTP status code (i.e. ‘200’ for OK); + + RESPONSE + response to transmit. + + Return ‘MHD_YES’ on success or if message has been queued. Return + ‘MHD_NO’: if arguments are invalid (example: ‘NULL’ pointer); on + error (i.e. reply already sent). + + -- Function: void MHD_destroy_response (struct MHD_Response *response) + Destroy a response object and associated resources (decrement the + reference counter). Note that MHD may keep some of the resources + around if the response is still in the queue for some clients, so + the memory may not necessarily be freed immediately. + + An explanation of reference counting(1): + + 1. a ‘MHD_Response’ object is allocated: + + struct MHD_Response * response = MHD_create_response_from_buffer(...); + /* here: reference counter = 1 */ + + 2. the ‘MHD_Response’ object is enqueued in a ‘MHD_Connection’: + + MHD_queue_response(connection, , response); + /* here: reference counter = 2 */ + + 3. the creator of the response object discharges responsibility for + it: + + MHD_destroy_response(response); + /* here: reference counter = 1 */ + + 4. the daemon handles the connection sending the response's data to + the client then decrements the reference counter by calling + ‘MHD_destroy_response()’: the counter's value drops to zero and the + ‘MHD_Response’ object is released. + + ---------- Footnotes ---------- + + (1) Note to readers acquainted to the Tcl API: reference counting on +‘MHD_Connection’ structures is handled in the same way as Tcl handles +‘Tcl_Obj’ structures through ‘Tcl_IncrRefCount()’ and +‘Tcl_DecrRefCount()’. + + +File: libmicrohttpd.info, Node: microhttpd-response create, Next: microhttpd-response headers, Prev: microhttpd-response enqueue, Up: microhttpd-responses + +8.2 Creating a response object +============================== + + -- Function: struct MHD_Response * MHD_create_response_from_callback + (uint64_t size, size_t block_size, MHD_ContentReaderCallback + crc, void *crc_cls, MHD_ContentReaderFreeCallback crfc) + Create a response object. The response object can be extended with + header information and then it can be used any number of times. + + SIZE + size of the data portion of the response, ‘-1’ for unknown; + + BLOCK_SIZE + preferred block size for querying CRC (advisory only, MHD may + still call CRC using smaller chunks); this is essentially the + buffer size used for IO, clients should pick a value that is + appropriate for IO and memory performance requirements; + + CRC + callback to use to obtain response data; + + CRC_CLS + extra argument to CRC; + + CRFC + callback to call to free CRC_CLS resources. + + Return ‘NULL’ on error (i.e. invalid arguments, out of memory). + + -- Function: struct MHD_Response * MHD_create_response_from_fd + (uint64_t size, int fd) + Create a response object. The response object can be extended with + header information and then it can be used any number of times. + + SIZE + size of the data portion of the response (should be smaller or + equal to the size of the file) + + FD + file descriptor referring to a file on disk with the data; + will be closed when response is destroyed; note that 'fd' must + be an actual file descriptor (not a pipe or socket) since MHD + might use 'sendfile' or 'seek' on it. The descriptor should + be in blocking-IO mode. + + Return ‘NULL’ on error (i.e. invalid arguments, out of memory). + + -- Function: struct MHD_Response * MHD_create_response_from_pipe (int + fd) + Create a response object. The response object can be extended with + header information and then it can be used ONLY ONCE. + + FD + file descriptor of the read-end of the pipe; will be closed + when response is destroyed. The descriptor should be in + blocking-IO mode. + + Return ‘NULL’ on error (i.e. out of memory). + + -- Function: struct MHD_Response * + MHD_create_response_from_fd_at_offset (size_t size, int fd, + off_t offset) + Create a response object. The response object can be extended with + header information and then it can be used any number of times. + Note that you need to be a bit careful about ‘off_t’ when writing + this code. Depending on your platform, MHD is likely to have been + compiled with support for 64-bit files. When you compile your own + application, you must make sure that ‘off_t’ is also a 64-bit + value. If not, your compiler may pass a 32-bit value as ‘off_t’, + which will result in 32-bits of garbage. + + If you use the autotools, use the ‘AC_SYS_LARGEFILE’ autoconf macro + and make sure to include the generated ‘config.h’ file before + ‘microhttpd.h’ to avoid problems. If you do not have a build + system and only want to run on a GNU/Linux system, you could also + use + #define _FILE_OFFSET_BITS 64 + #include + #include + #include + #include + to ensure 64-bit ‘off_t’. Note that if your operating system does + not support 64-bit files, MHD will be compiled with a 32-bit + ‘off_t’ (in which case the above would be wrong). + + SIZE + size of the data portion of the response (number of bytes to + transmit from the file starting at offset). + + FD + file descriptor referring to a file on disk with the data; + will be closed when response is destroyed; note that 'fd' must + be an actual file descriptor (not a pipe or socket) since MHD + might use 'sendfile' or 'seek' on it. The descriptor should + be in blocking-IO mode. + + OFFSET + offset to start reading from in the file + + Return ‘NULL’ on error (i.e. invalid arguments, out of memory). + + -- Function: struct MHD_Response * MHD_create_response_from_buffer + (size_t size, void *data, enum MHD_ResponseMemoryMode mode) + Create a response object. The response object can be extended with + header information and then it can be used any number of times. + + SIZE + size of the data portion of the response; + + BUFFER + the data itself; + + MODE + memory management options for buffer; use + MHD_RESPMEM_PERSISTENT if the buffer is static/global memory, + use MHD_RESPMEM_MUST_FREE if the buffer is heap-allocated and + should be freed by MHD and MHD_RESPMEM_MUST_COPY if the buffer + is in transient memory (i.e. on the stack) and must be copied + by MHD; + + Return ‘NULL’ on error (i.e. invalid arguments, out of memory). + + -- Function: struct MHD_Response * + MHD_create_response_from_buffer_with_free_callback (size_t + size, void *data, MHD_ContentReaderFreeCallback crfc) + Create a response object. The buffer at the end must be free'd by + calling the CRFC function. + + SIZE + size of the data portion of the response; + + BUFFER + the data itself; + + CRFC + function to call at the end to free memory allocated at + BUFFER. + + Return ‘NULL’ on error (i.e. invalid arguments, out of memory). + + -- Function: struct MHD_Response * MHD_create_response_from_data + (size_t size, void *data, int must_free, int must_copy) + Create a response object. The response object can be extended with + header information and then it can be used any number of times. + This function is deprecated, use ‘MHD_create_response_from_buffer’ + instead. + + SIZE + size of the data portion of the response; + + DATA + the data itself; + + MUST_FREE + if true: MHD should free data when done; + + MUST_COPY + if true: MHD allocates a block of memory and use it to make a + copy of DATA embedded in the returned ‘MHD_Response’ + structure; handling of the embedded memory is responsibility + of MHD; DATA can be released anytime after this call returns. + + Return ‘NULL’ on error (i.e. invalid arguments, out of memory). + + Example: create a response from a statically allocated string: + + const char * data = "

Error!

"; + + struct MHD_Connection * connection = ...; + struct MHD_Response * response; + + response = MHD_create_response_from_buffer (strlen(data), data, + MHD_RESPMEM_PERSISTENT); + MHD_queue_response(connection, 404, response); + MHD_destroy_response(response); + + -- Function: struct MHD_Response * MHD_create_response_from_iovec + (const struct MHD_IoVec *iov, int iovcnt, + MHD_ContentReaderFreeCallback crfc, void *cls) + Create a response object from an array of memory buffers. The + response object can be extended with header information and then be + used any number of times. + IOV + the array for response data buffers, an internal copy of this + will be made; however, note that the data pointed to by the + IOV is not copied and must be preserved unchanged at the given + locations until the response is no longer in use and the CRFC + is called; + + IOVCNT + the number of elements in IOV; + + CRFC + the callback to call to free resources associated with IOV; + + CLS + the argument to CRFC; + + Return ‘NULL’ on error (i.e. invalid arguments, out of memory). + + +File: libmicrohttpd.info, Node: microhttpd-response headers, Next: microhttpd-response options, Prev: microhttpd-response create, Up: microhttpd-responses + +8.3 Adding headers to a response +================================ + + -- Function: enum MHD_Result MHD_add_response_header (struct + MHD_Response *response, const char *header, const char + *content) + Add a header line to the response. The strings referenced by + HEADER and CONTENT must be zero-terminated and they are duplicated + into memory blocks embedded in RESPONSE. + + Notice that the strings must not hold newlines, carriage returns or + tab chars. + + MHD_add_response_header() prevents applications from setting a + "Transfer-Encoding" header to values other than "identity" or + "chunked" as other transfer encodings are not supported by MHD. + Note that usually MHD will pick the transfer encoding correctly + automatically, but applications can use the header to force a + particular behavior. + + MHD_add_response_header() also prevents applications from setting a + "Content-Length" header. MHD will automatically set a correct + "Content-Length" header if it is possible and allowed. + + Return ‘MHD_NO’ on error (i.e. invalid header or content format or + memory allocation error). + + -- Function: enum MHD_Result MHD_add_response_footer (struct + MHD_Response *response, const char *footer, const char + *content) + Add a footer line to the response. The strings referenced by + FOOTER and CONTENT must be zero-terminated and they are duplicated + into memory blocks embedded in RESPONSE. + + Notice that the strings must not hold newlines, carriage returns or + tab chars. You can add response footers at any time before + signalling the end of the response to MHD (not just before calling + 'MHD_queue_response'). Footers are useful for adding cryptographic + checksums to the reply or to signal errors encountered during data + generation. This call was introduced in MHD 0.9.3. + + Return ‘MHD_NO’ on error (i.e. invalid header or content format or + memory allocation error). + + -- Function: enum MHD_Result MHD_del_response_header (struct + MHD_Response *response, const char *header, const char + *content) + Delete a header (or footer) line from the response. Return + ‘MHD_NO’ on error (arguments are invalid or no such header known). + + +File: libmicrohttpd.info, Node: microhttpd-response options, Next: microhttpd-response inspect, Prev: microhttpd-response headers, Up: microhttpd-responses + +8.4 Setting response options +============================ + + -- Function: enum MHD_Result MHD_set_response_options (struct + MHD_Response *response, enum MHD_ResponseFlags flags, ...) + Set special flags and options for a response. + + Calling this functions sets the given flags and options for the + response. + + RESPONSE + which response should be modified; + + FLAGS + flags to set for the response; + + Additional arguments are a list of options (type-value pairs, + terminated with ‘MHD_RO_END’). It is mandatory to use ‘MHD_RO_END’ + as last argument, even when there are no additional arguments. + + Return ‘MHD_NO’ on error, ‘MHD_YES’ on success. + + +File: libmicrohttpd.info, Node: microhttpd-response inspect, Next: microhttpd-response upgrade, Prev: microhttpd-response options, Up: microhttpd-responses + +8.5 Inspecting a response object +================================ + + -- Function: int MHD_get_response_headers (struct MHD_Response + *response, MHD_KeyValueIterator iterator, void *iterator_cls) + Get all of the headers added to a response. + + Invoke the ITERATOR callback for each header in the response, using + ITERATOR_CLS as first argument. Return number of entries iterated + over. ITERATOR can be ‘NULL’: in this case the function just + counts headers. + + ITERATOR should not modify the its key and value arguments, unless + we know what we are doing. + + -- Function: const char * MHD_get_response_header (struct MHD_Response + *response, const char *key) + Find and return a pointer to the value of a particular header from + the response. KEY must reference a zero-terminated string + representing the header to look for. The search is case sensitive. + Return ‘NULL’ if header does not exist or KEY is ‘NULL’. + + We should not modify the value, unless we know what we are doing. + + +File: libmicrohttpd.info, Node: microhttpd-response upgrade, Prev: microhttpd-response inspect, Up: microhttpd-responses + +8.6 Creating a response for protocol upgrades +============================================= + +With RFC 2817 a mechanism to switch protocols within HTTP was +introduced. Here, a client sends a request with a "Connection: Upgrade" +header. The server responds with a "101 Switching Protocols" response +header, after which the two parties begin to speak a different +(non-HTTP) protocol over the TCP connection. + + This mechanism is used for upgrading HTTP 1.1 connections to HTTP2 or +HTTPS, as well as for implementing WebSockets. Which protocol upgrade +is performed is negotiated between server and client in additional +headers, in particular the "Upgrade" header. + + MHD supports switching protocols using this mechanism only if the +‘MHD_ALLOW_SUSPEND_RESUME’ flag has been set when starting the daemon. +If this flag has been set, applications can upgrade a connection by +queueing a response (using the ‘MHD_HTTP_SWITCHING_PROTOCOLS’ status +code) which must have been created with the following function: + + -- Function: enum MHD_Result MHD_create_response_for_upgrade + (MHD_UpgradeHandler upgrade_handler, void + *upgrade_handler_cls) + Create a response suitable for switching protocols. Returns + ‘MHD_YES’ on success. ‘upgrade_handler’ must not be ‘NULL’. + + When creating this type of response, the "Connection: Upgrade" + header will be set automatically for you. MHD requires that you + additionally set an "Upgrade:" header. The "Upgrade" header must + simply exist, the specific value is completely up to the + application. + + The ‘upgrade_handler’ argument to the above has the following type: + + -- Function Pointer: void *MHD_UpgradeHandler (void *cls, struct + MHD_Connection *connection, const char *extra_in, size_t + extra_in_size, MHD_socket sock, struct + MHD_UpgradeResponseHandle *urh) + This function will be called once MHD has transmitted the header of + the response to the connection that is being upgraded. At this + point, the application is expected to take over the socket ‘sock’ + and speak the non-HTTP protocol to which the connection was + upgraded. MHD will no longer use the socket; this includes + handling timeouts. The application must call ‘MHD_upgrade_action’ + with an upgrade action of ‘MHD_UPGRADE_ACTION_CLOSE’ when it is + done processing the connection to close the socket. The + application must not call ‘MHD_stop_daemon’ on the respective + daemon as long as it is still handling the connection. The + arguments given to the ‘upgrade_handler’ have the following + meaning: + + CLS + matches the ‘upgrade_handler_cls’ that was given to + ‘MHD_create_response_for_upgrade’ + CONNECTION + identifies the connection that is being upgraded; + + REQ_CLS + last value left in '*req_cls' in the + 'MHD_AccessHandlerCallback' + + EXTRA_IN + buffer of bytes MHD read "by accident" from the socket + already. This can happen if the client eagerly transmits more + than just the HTTP request. The application should treat + these as if it had read them from the socket. + + EXTRA_IN_SIZE + number of bytes in ‘extra_in’ + + SOCK + the socket which the application can now use directly for some + bi-directional communication with the client. The application + can henceforth use ‘recv()’ and ‘send()’ or ‘read()’ and + ‘write()’ system calls on the socket. However, ‘ioctl()’ and + ‘setsockopt()’ functions will not work as expected when using + HTTPS. Such operations may be supported in the future via + ‘MHD_upgrade_action’. Most importantly, the application must + never call ‘close()’ on this socket. Closing the socket must + be done using ‘MHD_upgrade_action’. However, while close is + forbidden, the application may call ‘shutdown()’ on the + socket. + + URH + argument for calls to ‘MHD_upgrade_action’. Applications must + eventually use this function to perform the ‘close()’ action + on the socket. + + -- Function: enum MHD_Result MHD_upgrade_action (struct + MHD_UpgradeResponseHandle *urh, enum MHD_UpgradeAction action, + ...) + Perform special operations related to upgraded connections. + + URH + identifies the upgraded connection to perform an action on + + ACTION + specifies the action to perform; further arguments to the + function depend on the specifics of the action. + + -- Enumeration: MHD_UpgradeAction + Set of actions to be performed on upgraded connections. Passed as + an argument to ‘MHD_upgrade_action()’. + + ‘MHD_UPGRADE_ACTION_CLOSE’ + Closes the connection. Must be called once the application is + done with the client. Takes no additional arguments. + ‘MHD_UPGRADE_ACTION_CORK_ON’ + Enable corking on the underlying socket. + ‘MHD_UPGRADE_ACTION_CORK_OFF’ + Disable corking on the underlying socket. + + +File: libmicrohttpd.info, Node: microhttpd-flow, Next: microhttpd-dauth, Prev: microhttpd-responses, Up: Top + +9 Flow control. +*************** + +Sometimes it may be possible that clients upload data faster than an +application can process it, or that an application needs an extended +period of time to generate a response. If +‘MHD_USE_THREAD_PER_CONNECTION’ is used, applications can simply deal +with this by performing their logic within the thread and thus +effectively blocking connection processing by MHD. In all other modes, +blocking logic must not be placed within the callbacks invoked by MHD as +this would also block processing of other requests, as a single thread +may be responsible for tens of thousands of connections. + + Instead, applications using thread modes other than +‘MHD_USE_THREAD_PER_CONNECTION’ should use the following functions to +perform flow control. + + -- Function: enum MHD_Result MHD_suspend_connection (struct + MHD_Connection *connection) + Suspend handling of network data for a given connection. This can + be used to dequeue a connection from MHD's event loop (external + select, internal select or thread pool; not applicable to + thread-per-connection!) for a while. + + If you use this API in conjunction with a internal select or a + thread pool, you must set the option ‘MHD_ALLOW_SUSPEND_RESUME’ to + ensure that a resumed connection is immediately processed by MHD. + + Suspended connections continue to count against the total number of + connections allowed (per daemon, as well as per IP, if such limits + are set). Suspended connections will NOT time out; timeouts will + restart when the connection handling is resumed. While a + connection is suspended, MHD will not detect disconnects by the + client. + + The only safe time to suspend a connection is from the + ‘MHD_AccessHandlerCallback’ or from the respective + ‘MHD_ContentReaderCallback’ (but in this case the response object + must not be shared among multiple connections). + + When suspending from the ‘MHD_AccessHandlerCallback’ you MUST + afterwards return ‘MHD_YES’ from the access handler callback (as + MHD_NO would imply to both close and suspend the connection, which + is not allowed). + + Finally, it is an API violation to call ‘MHD_stop_daemon’ while + having suspended connections (this will at least create memory and + socket leaks or lead to undefined behavior). You must explicitly + resume all connections before stopping the daemon. + + CONNECTION + the connection to suspend + + -- Function: enum MHD_Result MHD_resume_connection (struct + MHD_Connection *connection) + Resume handling of network data for suspended connection. It is + safe to resume a suspended connection at any time. Calling this + function on a connection that was not previously suspended will + result in undefined behavior. + + If you are using this function in "external" select mode, you must + make sure to run ‘MHD_run’ afterwards (before again calling + ‘MHD_get_fdset’), as otherwise the change may not be reflected in + the set returned by ‘MHD_get_fdset’ and you may end up with a + connection that is stuck until the next network activity. + + You can check whether a connection is currently suspended using + ‘MHD_get_connection_info’ by querying for + ‘MHD_CONNECTION_INFO_CONNECTION_SUSPENDED’. + + CONNECTION + the connection to resume + + +File: libmicrohttpd.info, Node: microhttpd-dauth, Next: microhttpd-post, Prev: microhttpd-flow, Up: Top + +10 Utilizing Authentication +*************************** + +MHD support three types of client authentication. + + Basic authentication uses a simple authentication method based on +BASE64 algorithm. Username and password are exchanged in clear between +the client and the server, so this method must only be used for +non-sensitive content or when the session is protected with https. When +using basic authentication MHD will have access to the clear password, +possibly allowing to create a chained authentication toward an external +authentication server. + + Digest authentication uses a one-way authentication method based on +MD5 hash algorithm. Only the hash will transit over the network, hence +protecting the user password. The nonce will prevent replay attacks. +This method is appropriate for general use, especially when https is not +used to encrypt the session. + + Client certificate authentication uses a X.509 certificate from the +client. This is the strongest authentication mechanism but it requires +the use of HTTPS. Client certificate authentication can be used +simultaneously with Basic or Digest Authentication in order to provide a +two levels authentication (like for instance separate machine and user +authentication). A code example for using client certificates is +presented in the MHD tutorial. + +* Menu: + +* microhttpd-dauth basic:: Using Basic Authentication. +* microhttpd-dauth digest:: Using Digest Authentication. + + +File: libmicrohttpd.info, Node: microhttpd-dauth basic, Next: microhttpd-dauth digest, Up: microhttpd-dauth + +10.1 Using Basic Authentication +=============================== + + -- Function: void MHD_free (void *ptr) + Free the memory given at ‘ptr’. Used to free data structures + allocated by MHD. Calls ‘free(ptr)’. + + -- Function: char * MHD_basic_auth_get_username_password3 (struct + MHD_Connection *connection) + Get the username and password from the basic authorization header + sent by the client. Return ‘NULL’ if no Basic Authorization header + set by the client or if Base64 encoding is invalid; a pointer to + the structure with username and password if found values set by the + client. If returned value is not ‘NULL’, the value must be + ‘MHD_free()’'ed. + + -- Function: enum MHD_Result MHD_queue_basic_auth_fail_response3 + (struct MHD_Connection *connection, const char *realm, int + prefer_utf8, struct MHD_Response *response) + Queues a response to request basic authentication from the client. + Return ‘MHD_YES’ if successful, otherwise ‘MHD_NO’. + + REALM must reference to a zero-terminated string representing the + realm. + + PREFER_UTF8 if set to ‘MHD_YES’ then parameter ‘charset’ with value + ‘UTF-8’ will be added to the response authentication header which + indicates that UTF-8 encoding is preferred for username and + password. + + RESPONSE a response structure to specify what shall be presented to + the client with a 401 HTTP status. + + +File: libmicrohttpd.info, Node: microhttpd-dauth digest, Prev: microhttpd-dauth basic, Up: microhttpd-dauth + +10.2 Using Digest Authentication +================================ + +MHD supports MD5 (deprecated by IETF) and SHA-256 hash algorithms for +digest authentication. The ‘MHD_DigestAuthAlgorithm’ enumeration is +used to specify which algorithm should be used. + + -- Enumeration: MHD_DigestAuthAlgorithm + Which digest algorithm should be used. Must be used consistently. + + ‘MHD_DIGEST_ALG_AUTO’ + Have MHD pick an algorithm currently considered secure. For + now defaults to SHA-256. + + ‘MHD_DIGEST_ALG_MD5’ + Force use of (deprecated, ancient, insecure) MD5. + + ‘MHD_DIGEST_ALG_SHA256’ + Force use of SHA-256. + + -- Enumeration: MHD_DigestAuthResult + The result of digest authentication of the client. + + ‘MHD_DAUTH_OK’ + Authentication OK. + + ‘MHD_DAUTH_ERROR’ + General error, like "out of memory". + + ‘MHD_DAUTH_WRONG_HEADER’ + No "Authorization" header or wrong format of the header. + + ‘MHD_DAUTH_WRONG_USERNAME’ + Wrong "username". + + ‘MHD_DAUTH_WRONG_REALM’ + Wrong "realm". + + ‘MHD_DAUTH_WRONG_URI’ + Wrong "URI" (or URI parameters). + + ‘MHD_DAUTH_NONCE_STALE’ + The "nonce" is too old. Suggest the client to retry with the + same username and password to get the fresh "nonce". The + validity of the "nonce" may not be checked. + + ‘MHD_DAUTH_NONCE_WRONG’ + The "nonce" is wrong. May indicate an attack attempt. + + ‘MHD_DAUTH_RESPONSE_WRONG’ + The "response" is wrong. May indicate an attack attempt. + + -- Function: char * MHD_digest_auth_get_username (struct MHD_Connection + *connection) + Find and return a pointer to the username value from the request + header. Return ‘NULL’ if the value is not found or header does not + exist. If returned value is not ‘NULL’, the value must be + ‘MHD_free()’'ed. + + -- Function: enum MHD_DigestAuthResult MHD_digest_auth_check3 (struct + MHD_Connection *connection, const char *realm, const char + *username, const char *password, unsigned int nonce_timeout, + enum MHD_DigestAuthAlgorithm algo) + Checks if the provided values in the WWW-Authenticate header are + valid and sound according to RFC7616. If valid return + ‘MHD_DAUTH_OK’, otherwise return the error code. + + REALM must reference to a zero-terminated string representing the + realm. + + USERNAME must reference to a zero-terminated string representing + the username, it is usually the returned value from + MHD_digest_auth_get_username. + + PASSWORD must reference to a zero-terminated string representing + the password, most probably it will be the result of a lookup of + the username against a local database. + + NONCE_TIMEOUT the nonce validity duration in seconds. Most of the + time it is sound to specify 300 seconds as its values. + + ALGO which digest algorithm should we use. + + -- Function: int MHD_digest_auth_check2 (struct MHD_Connection + *connection, const char *realm, const char *username, const + char *password, unsigned int nonce_timeout, enum + MHD_DigestAuthAlgorithm algo) + Checks if the provided values in the WWW-Authenticate header are + valid and sound according to RFC2716. If valid return ‘MHD_YES’, + otherwise return ‘MHD_NO’. + + REALM must reference to a zero-terminated string representing the + realm. + + USERNAME must reference to a zero-terminated string representing + the username, it is usually the returned value from + MHD_digest_auth_get_username. + + PASSWORD must reference to a zero-terminated string representing + the password, most probably it will be the result of a lookup of + the username against a local database. + + NONCE_TIMEOUT is the amount of time in seconds for a nonce to be + invalid. Most of the time it is sound to specify 300 seconds as + its values. + + ALGO which digest algorithm should we use. + + -- Function: int MHD_digest_auth_check (struct MHD_Connection + *connection, const char *realm, const char *username, const + char *password, unsigned int nonce_timeout) + Checks if the provided values in the WWW-Authenticate header are + valid and sound according to RFC2716. If valid return ‘MHD_YES’, + otherwise return ‘MHD_NO’. Deprecated, use + ‘MHD_digest_auth_check2’ instead. + + REALM must reference to a zero-terminated string representing the + realm. + + USERNAME must reference to a zero-terminated string representing + the username, it is usually the returned value from + MHD_digest_auth_get_username. + + PASSWORD must reference to a zero-terminated string representing + the password, most probably it will be the result of a lookup of + the username against a local database. + + NONCE_TIMEOUT is the amount of time in seconds for a nonce to be + invalid. Most of the time it is sound to specify 300 seconds as + its values. + + -- Function: enum MHD_DigestAuthResult MHD_digest_auth_check_digest3 + (struct MHD_Connection *connection, const char *realm, const + char *username, const uint8_t *digest, unsigned int + nonce_timeout, enum MHD_DigestAuthAlgorithm algo) + Checks if the provided values in the WWW-Authenticate header are + valid and sound according to RFC7616. If valid return + ‘MHD_DAUTH_OK’, otherwise return the error code. + + REALM must reference to a zero-terminated string representing the + realm. + + USERNAME must reference to a zero-terminated string representing + the username, it is usually the returned value from + MHD_digest_auth_get_username. + + DIGEST the pointer to the binary digest for the precalculated hash + value "username:realm:password" with specified ALGO. + + DIGEST_SIZE the number of bytes in DIGEST (the size must match + ALGO!) + + NONCE_TIMEOUT the nonce validity duration in seconds. Most of the + time it is sound to specify 300 seconds as its values. + + ALGO digest authentication algorithm to use. + + -- Function: int MHD_digest_auth_check_digest2 (struct MHD_Connection + *connection, const char *realm, const char *username, const + uint8_t *digest, unsigned int nonce_timeout, enum + MHD_DigestAuthAlgorithm algo) + Checks if the provided values in the WWW-Authenticate header are + valid and sound according to RFC2716. If valid return ‘MHD_YES’, + otherwise return ‘MHD_NO’. + + REALM must reference to a zero-terminated string representing the + realm. + + USERNAME must reference to a zero-terminated string representing + the username, it is usually the returned value from + MHD_digest_auth_get_username. + + DIGEST pointer to the binary MD5 sum for the precalculated hash + value "userame:realm:password". The size must match the selected + ALGO! + + NONCE_TIMEOUT is the amount of time in seconds for a nonce to be + invalid. Most of the time it is sound to specify 300 seconds as + its values. + + ALGO digest authentication algorithm to use. + + -- Function: int MHD_digest_auth_check_digest (struct MHD_Connection + *connection, const char *realm, const char *username, const + unsigned char digest[MHD_MD5_DIGEST_SIZE], unsigned int + nonce_timeout) + Checks if the provided values in the WWW-Authenticate header are + valid and sound according to RFC2716. If valid return ‘MHD_YES’, + otherwise return ‘MHD_NO’. Deprecated, use + ‘MHD_digest_auth_check_digest2’ instead. + + REALM must reference to a zero-terminated string representing the + realm. + + USERNAME must reference to a zero-terminated string representing + the username, it is usually the returned value from + MHD_digest_auth_get_username. + + DIGEST pointer to the binary MD5 sum for the precalculated hash + value "userame:realm:password" of ‘MHD_MD5_DIGEST_SIZE’ bytes. + + NONCE_TIMEOUT is the amount of time in seconds for a nonce to be + invalid. Most of the time it is sound to specify 300 seconds as + its values. + + -- Function: enum MHD_Result MHD_queue_auth_fail_response2 (struct + MHD_Connection *connection, const char *realm, const char + *opaque, struct MHD_Response *response, int signal_stale, enum + MHD_DigestAuthAlgorithm algo) + Queues a response to request authentication from the client, return + ‘MHD_YES’ if successful, otherwise ‘MHD_NO’. + + REALM must reference to a zero-terminated string representing the + realm. + + OPAQUE must reference to a zero-terminated string representing a + value that gets passed to the client and expected to be passed + again to the server as-is. This value can be a hexadecimal or + base64 string. + + RESPONSE a response structure to specify what shall be presented to + the client with a 401 HTTP status. + + SIGNAL_STALE a value that signals "stale=true" in the response + header to indicate the invalidity of the nonce and no need to ask + for authentication parameters and only a new nonce gets generated. + ‘MHD_YES’ to generate a new nonce, ‘MHD_NO’ to ask for + authentication parameters. + + ALGO which digest algorithm should we use. The same algorithm must + then be selected when checking digests received from clients! + + -- Function: enum MHD_Result MHD_queue_auth_fail_response (struct + MHD_Connection *connection, const char *realm, const char + *opaque, struct MHD_Response *response, int signal_stale) + Queues a response to request authentication from the client, return + ‘MHD_YES’ if successful, otherwise ‘MHD_NO’. + + REALM must reference to a zero-terminated string representing the + realm. + + OPAQUE must reference to a zero-terminated string representing a + value that gets passed to the client and expected to be passed + again to the server as-is. This value can be a hexadecimal or + base64 string. + + RESPONSE a response structure to specify what shall be presented to + the client with a 401 HTTP status. + + SIGNAL_STALE a value that signals "stale=true" in the response + header to indicate the invalidity of the nonce and no need to ask + for authentication parameters and only a new nonce gets generated. + ‘MHD_YES’ to generate a new nonce, ‘MHD_NO’ to ask for + authentication parameters. + + Example: handling digest authentication requests and responses. + + #define PAGE "libmicrohttpd demoAccess granted" + #define DENIED "libmicrohttpd demoAccess denied" + #define OPAQUE "11733b200778ce33060f31c9af70a870ba96ddd4" + + static int + ahc_echo (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, size_t *upload_data_size, void **ptr) + { + struct MHD_Response *response; + char *username; + const char *password = "testpass"; + const char *realm = "test@example.com"; + int ret; + static int already_called_marker; + + if (&already_called_marker != *req_cls) + { /* Called for the first time, request not fully read yet */ + *req_cls = &already_called_marker; + /* Wait for complete request */ + return MHD_YES; + } + + username = MHD_digest_auth_get_username (connection); + if (username == NULL) + { + response = MHD_create_response_from_buffer(strlen (DENIED), + DENIED, + MHD_RESPMEM_PERSISTENT); + ret = MHD_queue_auth_fail_response2 (connection, + realm, + OPAQUE, + response, + MHD_NO, + MHD_DIGEST_ALG_SHA256); + MHD_destroy_response(response); + return ret; + } + ret = MHD_digest_auth_check2 (connection, + realm, + username, + password, + 300, + MHD_DIGEST_ALG_SHA256); + MHD_free(username); + if ( (ret == MHD_INVALID_NONCE) || + (ret == MHD_NO) ) + { + response = MHD_create_response_from_buffer(strlen (DENIED), + DENIED, + MHD_RESPMEM_PERSISTENT); + if (NULL == response) + return MHD_NO; + ret = MHD_queue_auth_fail_response2 (connection, + realm, + OPAQUE, + response, + (ret == MHD_INVALID_NONCE) ? MHD_YES : MHD_NO, + MHD_DIGEST_ALG_SHA256); + MHD_destroy_response(response); + return ret; + } + response = MHD_create_response_from_buffer (strlen(PAGE), + PAGE, + MHD_RESPMEM_PERSISTENT); + ret = MHD_queue_response (connection, + MHD_HTTP_OK, + response); + MHD_destroy_response(response); + return ret; + } + + +File: libmicrohttpd.info, Node: microhttpd-post, Next: microhttpd-info, Prev: microhttpd-dauth, Up: Top + +11 Adding a ‘POST’ processor +**************************** + +* Menu: + +* microhttpd-post api:: Programming interface for the + ‘POST’ processor. + +MHD provides the post processor API to make it easier for applications +to parse the data of a client's ‘POST’ request: the +‘MHD_AccessHandlerCallback’ will be invoked multiple times to process +data as it arrives; at each invocation a new chunk of data must be +processed. The arguments UPLOAD_DATA and UPLOAD_DATA_SIZE are used to +reference the chunk of data. + + When ‘MHD_AccessHandlerCallback’ is invoked for a new request: its +‘*REQ_CLS’ argument is set to ‘NULL’. When ‘POST’ data comes in the +upload buffer it is *mandatory* to use the REQ_CLS to store a reference +to per-request data. The fact that the pointer was initially ‘NULL’ can +be used to detect that this is a new request. + + One method to detect that a new request was started is to set +‘*req_cls’ to an unused integer: + + int + access_handler (void *cls, + struct MHD_Connection * connection, + const char *url, + const char *method, const char *version, + const char *upload_data, size_t *upload_data_size, + void **req_cls) + { + static int old_connection_marker; + int new_connection = (NULL == *req_cls); + + if (new_connection) + { + /* new connection with POST */ + *req_cls = &old_connection_marker; + } + + ... + } + +In contrast to the previous example, for ‘POST’ requests in particular, +it is more common to use the value of ‘*req_cls’ to keep track of actual +state used during processing, such as the post processor (or a struct +containing a post processor): + + int + access_handler (void *cls, + struct MHD_Connection * connection, + const char *url, + const char *method, const char *version, + const char *upload_data, size_t *upload_data_size, + void **req_cls) + { + struct MHD_PostProcessor * pp = *req_cls; + + if (pp == NULL) + { + pp = MHD_create_post_processor(connection, ...); + *req_cls = pp; + return MHD_YES; + } + if (*upload_data_size) + { + MHD_post_process(pp, upload_data, *upload_data_size); + *upload_data_size = 0; + return MHD_YES; + } + else + { + MHD_destroy_post_processor(pp); + return MHD_queue_response(...); + } + } + + Note that the callback from ‘MHD_OPTION_NOTIFY_COMPLETED’ should be +used to destroy the post processor. This cannot be done inside of the +access handler since the connection may not always terminate normally. + + +File: libmicrohttpd.info, Node: microhttpd-post api, Up: microhttpd-post + +11.1 Programming interface for the ‘POST’ processor +=================================================== + + -- Function: struct MHD_PostProcessor * MHD_create_post_processor + (struct MHD_Connection *connection, size_t buffer_size, + MHD_PostDataIterator iterator, void *iterator_cls) + Create a PostProcessor. A PostProcessor can be used to + (incrementally) parse the data portion of a ‘POST’ request. + + CONNECTION + the connection on which the ‘POST’ is happening (used to + determine the ‘POST’ format); + + BUFFER_SIZE + maximum number of bytes to use for internal buffering (used + only for the parsing, specifically the parsing of the keys). + A tiny value (256-1024) should be sufficient; do *NOT* use a + value smaller than 256; for good performance, use 32k or 64k + (i.e. 65536). + + ITERATOR + iterator to be called with the parsed data; must *NOT* be + ‘NULL’; + + ITERATOR_CLS + custom value to be used as first argument to ITERATOR. + + Return ‘NULL’ on error (out of memory, unsupported encoding), + otherwise a PP handle. + + -- Function: enum MHD_Result MHD_post_process (struct MHD_PostProcessor + *pp, const char *post_data, size_t post_data_len) + Parse and process ‘POST’ data. Call this function when ‘POST’ data + is available (usually during an ‘MHD_AccessHandlerCallback’) with + the UPLOAD_DATA and UPLOAD_DATA_SIZE. Whenever possible, this will + then cause calls to the ‘MHD_IncrementalKeyValueIterator’. + + PP + the post processor; + + POST_DATA + POST_DATA_LEN bytes of ‘POST’ data; + + POST_DATA_LEN + length of POST_DATA. + + Return ‘MHD_YES’ on success, ‘MHD_NO’ on error (out-of-memory, + iterator aborted, parse error). + + -- Function: enum MHD_Result MHD_destroy_post_processor (struct + MHD_PostProcessor *pp) + Release PostProcessor resources. After this function is being + called, the PostProcessor is guaranteed to no longer call its + iterator. There is no special call to the iterator to indicate the + end of the post processing stream. After destroying the + PostProcessor, the programmer should perform any necessary work to + complete the processing of the iterator. + + Return ‘MHD_YES’ if processing completed nicely, ‘MHD_NO’ if there + were spurious characters or formatting problems with the post + request. It is common to ignore the return value of this function. + + +File: libmicrohttpd.info, Node: microhttpd-info, Next: microhttpd-util, Prev: microhttpd-post, Up: Top + +12 Obtaining and modifying status information. +********************************************** + +* Menu: + +* microhttpd-info daemon:: State information about an MHD daemon +* microhttpd-info conn:: State information about a connection +* microhttpd-option conn:: Modify per-connection options + + +File: libmicrohttpd.info, Node: microhttpd-info daemon, Next: microhttpd-info conn, Up: microhttpd-info + +12.1 Obtaining state information about an MHD daemon +==================================================== + + -- Function: const union MHD_DaemonInfo * MHD_get_daemon_info (struct + MHD_Daemon *daemon, enum MHD_DaemonInfoType infoType, ...) + Obtain information about the given daemon. This function is + currently not fully implemented. + + DAEMON + the daemon about which information is desired; + + INFOTYPE + type of information that is desired + + ... + additional arguments about the desired information (depending + on infoType) + + Returns a union with the respective member (depending on infoType) + set to the desired information), or ‘NULL’ in case the desired + information is not available or applicable. + + -- Enumeration: MHD_DaemonInfoType + Values of this enum are used to specify what information about a + daemon is desired. + ‘MHD_DAEMON_INFO_KEY_SIZE’ + Request information about the key size for a particular cipher + algorithm. The cipher algorithm should be passed as an extra + argument (of type 'enum MHD_GNUTLS_CipherAlgorithm'). No + longer supported, using this value will cause + ‘MHD_get_daemon_info’ to return NULL. + + ‘MHD_DAEMON_INFO_MAC_KEY_SIZE’ + Request information about the key size for a particular cipher + algorithm. The cipher algorithm should be passed as an extra + argument (of type 'enum MHD_GNUTLS_HashAlgorithm'). No longer + supported, using this value will cause ‘MHD_get_daemon_info’ + to return NULL. + + ‘MHD_DAEMON_INFO_LISTEN_FD’ + Request the file-descriptor number that MHD is using to listen + to the server socket. This can be useful if no port was + specified and a client needs to learn what port is actually + being used by MHD. No extra arguments should be passed. + + ‘MHD_DAEMON_INFO_EPOLL_FD’ + Request the file-descriptor number that MHD is using for + epoll. If the build is not supporting epoll, NULL is + returned; if we are using a thread pool or this daemon was not + started with ‘MHD_USE_EPOLL’, (a pointer to) -1 is returned. + If we are using ‘MHD_USE_INTERNAL_POLLING_THREAD’ or are in + 'external' select mode, the internal epoll FD is returned. + This function must be used in external select mode with epoll + to obtain the FD to call epoll on. No extra arguments should + be passed. + + ‘MHD_DAEMON_INFO_CURRENT_CONNECTIONS’ + Request the number of current connections handled by the + daemon. No extra arguments should be passed and a pointer to + a ‘union MHD_DaemonInfo’ value is returned, with the + ‘num_connections’ member of type ‘unsigned int’ set to the + number of active connections. + + Note that in multi-threaded or internal-select mode, the real + number of current connections may already be different when + ‘MHD_get_daemon_info’ returns. The number of current + connections can be used (even in multi-threaded and + internal-select mode) after ‘MHD_quiesce_daemon’ to detect + whether all connections have been handled. + + +File: libmicrohttpd.info, Node: microhttpd-info conn, Next: microhttpd-option conn, Prev: microhttpd-info daemon, Up: microhttpd-info + +12.2 Obtaining state information about a connection +=================================================== + + -- Function: const union MHD_ConnectionInfo * MHD_get_connection_info + (struct MHD_Connection *connection, enum + MHD_ConnectionInfoType infoType, ...) + Obtain information about the given connection. + + CONNECTION + the connection about which information is desired; + + INFOTYPE + type of information that is desired + + ... + additional arguments about the desired information (depending + on infoType) + + Returns a union with the respective member (depending on infoType) + set to the desired information), or ‘NULL’ in case the desired + information is not available or applicable. + + -- Enumeration: MHD_ConnectionInfoType + Values of this enum are used to specify what information about a + connection is desired. + + ‘MHD_CONNECTION_INFO_CIPHER_ALGO’ + What cipher algorithm is being used (HTTPS connections only). + ‘NULL’ is returned for non-HTTPS connections. + + Takes no extra arguments. + + ‘MHD_CONNECTION_INFO_PROTOCOL,’ + Allows finding out the TLS/SSL protocol used (HTTPS + connections only). ‘NULL’ is returned for non-HTTPS + connections. + + Takes no extra arguments. + + ‘MHD_CONNECTION_INFO_CLIENT_ADDRESS’ + Returns information about the address of the client. Returns + essentially a ‘struct sockaddr **’ (since the API returns a + ‘union MHD_ConnectionInfo *’ and that union contains a ‘struct + sockaddr *’). + + Takes no extra arguments. + + ‘MHD_CONNECTION_INFO_GNUTLS_SESSION,’ + Takes no extra arguments. Allows access to the underlying + GNUtls session, including access to the underlying GNUtls + client certificate (HTTPS connections only). Takes no extra + arguments. ‘NULL’ is returned for non-HTTPS connections. + + Takes no extra arguments. + + ‘MHD_CONNECTION_INFO_GNUTLS_CLIENT_CERT,’ + Dysfunctional (never implemented, deprecated). Use + MHD_CONNECTION_INFO_GNUTLS_SESSION to get the + ‘gnutls_session_t’ and then call + ‘gnutls_certificate_get_peers()’. + + ‘MHD_CONNECTION_INFO_DAEMON’ + Returns information about ‘struct MHD_Daemon’ which manages + this connection. + + Takes no extra arguments. + + ‘MHD_CONNECTION_INFO_CONNECTION_FD’ + Returns the file descriptor (usually a TCP socket) associated + with this connection (in the "connect-fd" member of the + returned struct). Note that manipulating the descriptor + directly can have problematic consequences (as in, break + HTTP). Applications might use this access to manipulate TCP + options, for example to set the "TCP-NODELAY" option for + COMET-like applications. Note that MHD will set TCP-CORK + after sending the HTTP header and clear it after finishing the + footers automatically (if the platform supports it). As the + connection callbacks are invoked in between, those might be + used to set different values for TCP-CORK and TCP-NODELAY in + the meantime. + + Takes no extra arguments. + + ‘MHD_CONNECTION_INFO_CONNECTION_SUSPENDED’ + Returns pointer to an integer that is ‘MHD_YES’ if the + connection is currently suspended (and thus can be safely + resumed) and ‘MHD_NO’ otherwise. + + Takes no extra arguments. + + ‘MHD_CONNECTION_INFO_SOCKET_CONTEXT’ + Returns the client-specific pointer to a ‘void *’ that was + (possibly) set during a ‘MHD_NotifyConnectionCallback’ when + the socket was first accepted. Note that this is NOT the same + as the ‘req_cls’ argument of the ‘MHD_AccessHandlerCallback’. + The ‘req_cls’ is fresh for each HTTP request, while the + ‘socket_context’ is fresh for each socket. + + Takes no extra arguments. + + ‘MHD_CONNECTION_INFO_CONNECTION_TIMEOUT’ + Returns pointer to an ‘unsigned int’ that is the current + timeout used for the connection (in seconds, 0 for no + timeout). Note that while suspended connections will not + timeout, the timeout value returned for suspended connections + will be the timeout that the connection will use after it is + resumed, and thus might not be zero. + + Takes no extra arguments. + + ‘MHD_CONNECTION_INFO_REQUEST_HEADER_SIZE’ + Returns pointer to an ‘size_t’ that represents the size of the + HTTP header received from the client. Only valid after the + first callback to the access handler. + + Takes no extra arguments. + + ‘MHD_CONNECTION_INFO_HTTP_STATUS’ + Returns the HTTP status code of the response that was queued. + Returns NULL if no response was queued yet. + + Takes no extra arguments. + + +File: libmicrohttpd.info, Node: microhttpd-option conn, Prev: microhttpd-info conn, Up: microhttpd-info + +12.3 Setting custom options for an individual connection +======================================================== + + -- Function: int MHD_set_connection_option (struct MHD_Connection + *daemon, enum MHD_CONNECTION_OPTION option, ...) + Set a custom option for the given connection. + + CONNECTION + the connection for which an option should be set or modified; + + OPTION + option to set + + ... + additional arguments for the option (depending on option) + + Returns ‘MHD_YES’ on success, ‘MHD_NO’ for errors (i.e. option + argument invalid or option unknown). + + -- Enumeration: MHD_CONNECTION_OPTION + Values of this enum are used to specify which option for a + connection should be changed. + + ‘MHD_CONNECTION_OPTION_TIMEOUT’ + Set a custom timeout for the given connection. Specified as + the number of seconds, given as an ‘unsigned int’. Use zero + for no timeout. + + +File: libmicrohttpd.info, Node: microhttpd-util, Next: microhttpd-websocket, Prev: microhttpd-info, Up: Top + +13 Utility functions. +********************* + +* Menu: + +* microhttpd-util feature:: Test supported MHD features +* microhttpd-util unescape:: Unescape strings + + +File: libmicrohttpd.info, Node: microhttpd-util feature, Next: microhttpd-util unescape, Up: microhttpd-util + +13.1 Testing for supported MHD features +======================================= + + -- Enumeration: MHD_FEATURE + Values of this enum are used to specify what information about a + daemon is desired. + ‘MHD_FEATURE_MESSAGES’ + Get whether messages are supported. If supported then in + debug mode messages can be printed to stderr or to external + logger. + + ‘MHD_FEATURE_SSL’ + Get whether HTTPS is supported. If supported then flag + MHD_USE_SSL and options MHD_OPTION_HTTPS_MEM_KEY, + MHD_OPTION_HTTPS_MEM_CERT, MHD_OPTION_HTTPS_MEM_TRUST, + MHD_OPTION_HTTPS_MEM_DHPARAMS, MHD_OPTION_HTTPS_CRED_TYPE, + MHD_OPTION_HTTPS_PRIORITIES can be used. + + ‘MHD_FEATURE_HTTPS_CERT_CALLBACK’ + Get whether option #MHD_OPTION_HTTPS_CERT_CALLBACK is + supported. + + ‘MHD_FEATURE_IPv6’ + Get whether IPv6 is supported. If supported then flag + MHD_USE_IPv6 can be used. + + ‘MHD_FEATURE_IPv6_ONLY’ + Get whether IPv6 without IPv4 is supported. If not supported + then IPv4 is always enabled in IPv6 sockets and flag + MHD_USE_DUAL_STACK if always used when MHD_USE_IPv6 is + specified. + + ‘MHD_FEATURE_POLL’ + Get whether ‘poll()’ is supported. If supported then flag + MHD_USE_POLL can be used. + + ‘MHD_FEATURE_EPOLL’ + Get whether ‘epoll()’ is supported. If supported then Flags + MHD_USE_EPOLL and MHD_USE_EPOLL_INTERNAL_THREAD can be used. + + ‘MHD_FEATURE_SHUTDOWN_LISTEN_SOCKET’ + Get whether shutdown on listen socket to signal other threads + is supported. If not supported flag MHD_USE_ITC is + automatically forced. + + ‘MHD_FEATURE_SOCKETPAIR’ + Get whether a ‘socketpair()’ is used internally instead of a + ‘pipe()’ to signal other threads. + + ‘MHD_FEATURE_TCP_FASTOPEN’ + Get whether TCP Fast Open is supported. If supported then + flag MHD_USE_TCP_FASTOPEN and option + MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE can be used. + + ‘MHD_FEATURE_BASIC_AUTH’ + Get whether HTTP Basic authorization is supported. If + supported then functions + ‘MHD_basic_auth_get_username_password()’ and + ‘MHD_queue_basic_auth_fail_response()’ can be used. + + ‘MHD_FEATURE_DIGEST_AUTH’ + Get whether HTTP Digest authorization is supported. If + supported then options MHD_OPTION_DIGEST_AUTH_RANDOM, + MHD_OPTION_NONCE_NC_SIZE and functions + ‘MHD_digest_auth_check()’, can be used. + + ‘MHD_FEATURE_POSTPROCESSOR’ + Get whether postprocessor is supported. If supported then + functions ‘MHD_create_post_processor()’, ‘MHD_post_process()’, + ‘MHD_destroy_post_processor()’ can be used. + + ‘MHD_FEATURE_SENDFILE’ + Get whether ‘sendfile()’ is supported. + + -- Function: int MHD_is_feature_supported (enum MHD_FEATURE feature) + Get information about supported MHD features. Indicate that MHD + was compiled with or without support for particular feature. Some + features require additional support by the kernel. However, kernel + support is not checked by this function. + + FEATURE + type of requested information + + Returns ‘MHD_YES’ if the feature is supported, and ‘MHD_NO’ if not. + + +File: libmicrohttpd.info, Node: microhttpd-util unescape, Prev: microhttpd-util feature, Up: microhttpd-util + +13.2 Unescape strings +===================== + + -- Function: size_t MHD_http_unescape (char *val) + Process escape sequences ('%HH') Updates val in place; the result + should be UTF-8 encoded and cannot be larger than the input. The + result must also still be 0-terminated. + + VAL + value to unescape (modified in the process), must be a + 0-terminated UTF-8 string. + + Returns length of the resulting val (‘strlen(val)’ may be shorter + afterwards due to elimination of escape sequences). + + +File: libmicrohttpd.info, Node: microhttpd-websocket, Next: GNU-LGPL, Prev: microhttpd-util, Up: Top + +14 Websocket functions. +*********************** + +Websocket functions provide what you need to use an upgraded connection +as a websocket. These functions are only available if you include the +header file ‘microhttpd_ws.h’ and compiled _libmicrohttpd_ with +websockets. + +* Menu: + +* microhttpd-websocket handshake:: Websocket handshake functions +* microhttpd-websocket stream:: Websocket stream functions +* microhttpd-websocket decode:: Websocket decode functions +* microhttpd-websocket encode:: Websocket encode functions +* microhttpd-websocket memory:: Websocket memory functions + + +File: libmicrohttpd.info, Node: microhttpd-websocket handshake, Next: microhttpd-websocket stream, Up: microhttpd-websocket + +14.1 Websocket handshake functions +================================== + + -- Function: enum MHD_WEBSOCKET_STATUS MHD_websocket_check_http_version + (const char* http_version) + Checks the HTTP version of the incoming request. Websocket + requests are only allowed for HTTP/1.1 or above. + + HTTP_VERSION + The value of the ‘version’ parameter of your ‘access_handler’ + callback. If you pass ‘NULL’ then this is handled like a not + matching HTTP version. + + Returns 0 when the HTTP version is valid for a websocket request + and a value less than zero when the HTTP version isn't valid for a + websocket request. Can be compared with ‘enum + MHD_WEBSOCKET_STATUS’. + + -- Function: enum MHD_WEBSOCKET_STATUS + MHD_websocket_check_connection_header (const char* + connection_header) + Checks the value of the ‘Connection’ HTTP request header. + Websocket requests require the token ‘Upgrade’ in the ‘Connection’ + HTTP request header. + + CONNECTION_HEADER + Value of the ‘Connection’ request header. You can get this + request header value by passing ‘MHD_HTTP_HEADER_CONNECTION’ + to ‘MHD_lookup_connection_value()’. If you pass ‘NULL’ then + this is handled like a not matching ‘Connection’ header value. + + Returns 0 when the ‘Connection’ header is valid for a websocket + request and a value less than zero when the ‘Connection’ header + isn't valid for a websocket request. Can be compared with ‘enum + MHD_WEBSOCKET_STATUS’. + + -- Function: enum MHD_WEBSOCKET_STATUS + MHD_websocket_check_upgrade_header (const char* + upgrade_header) + Checks the value of the ‘Upgrade’ HTTP request header. Websocket + requests require the value ‘websocket’ in the ‘Upgrade’ HTTP + request header. + + UPGRADE_HEADER + Value of the ‘Upgrade’ request header. You can get this + request header value by passing ‘MHD_HTTP_HEADER_UPGRADE’ to + ‘MHD_lookup_connection_value()’. If you pass ‘NULL’ then this + is handled like a not matching ‘Upgrade’ header value. + + Returns 0 when the ‘Upgrade’ header is valid for a websocket + request and a value less than zero when the ‘Upgrade’ header isn't + valid for a websocket request. Can be compared with ‘enum + MHD_WEBSOCKET_STATUS’. + + -- Function: enum MHD_WEBSOCKET_STATUS + MHD_websocket_check_version_header (const char* + version_header) + Checks the value of the ‘Sec-WebSocket-Version’ HTTP request + header. Websocket requests require the value ‘13’ in the + ‘Sec-WebSocket-Version’ HTTP request header. + + VERSION_HEADER + Value of the ‘Sec-WebSocket-Version’ request header. You can + get this request header value by passing + ‘MHD_HTTP_HEADER_SEC_WEBSOCKET_VERSION’ to + ‘MHD_lookup_connection_value()’. If you pass ‘NULL’ then this + is handled like a not matching ‘Sec-WebSocket-Version’ header + value. + + Returns 0 when the ‘Sec-WebSocket-Version’ header is valid for a + websocket request and a value less than zero when the + ‘Sec-WebSocket-Version’ header isn't valid for a websocket request. + Can be compared with ‘enum MHD_WEBSOCKET_STATUS’. + + -- Function: enum MHD_WEBSOCKET_STATUS + MHD_websocket_create_accept_header (const char* + sec_websocket_key, char* sec_websocket_accept) + Checks the value of the ‘Sec-WebSocket-Key’ HTTP request header and + generates the value for the ‘Sec-WebSocket-Accept’ HTTP response + header. The generated value must be sent to the client. + + SEC_WEBSOCKET_KEY + Value of the ‘Sec-WebSocket-Key’ request header. You can get + this request header value by passing + ‘MHD_HTTP_HEADER_SEC_WEBSOCKET_KEY’ to + ‘MHD_lookup_connection_value()’. If you pass ‘NULL’ then this + is handled like a not matching ‘Sec-WebSocket-Key’ header + value. + + SEC_WEBSOCKET_ACCEPT + Response buffer, which will receive the generated value for + the ‘Sec-WebSocket-Accept’ HTTP response header. This buffer + must be at least 29 bytes long and will contain the response + value plus a terminating ‘NUL’ character on success. Must not + be ‘NULL’. You can add this HTTP header to your response by + passing ‘MHD_HTTP_HEADER_SEC_WEBSOCKET_ACCEPT’ to + ‘MHD_add_response_header()’. + + Returns 0 when the ‘Sec-WebSocket-Key’ header was not empty and a + result value for the ‘Sec-WebSocket-Accept’ was calculated. A + value less than zero is returned when the ‘Sec-WebSocket-Key’ + header isn't valid for a websocket request or when any error + occurred. Can be compared with ‘enum MHD_WEBSOCKET_STATUS’. + + +File: libmicrohttpd.info, Node: microhttpd-websocket stream, Next: microhttpd-websocket decode, Prev: microhttpd-websocket handshake, Up: microhttpd-websocket + +14.2 Websocket stream functions +=============================== + + -- Function: enum MHD_WEBSOCKET_STATUS MHD_websocket_stream_init + (struct MHD_WebSocketStream **ws, int flags, size_t + max_payload_size) + Creates a new websocket stream, used for decoding/encoding. + + WS + pointer a variable to fill with the newly created ‘struct + MHD_WebSocketStream’, receives ‘NULL’ on error. May not be + ‘NULL’. + + If not required anymore, free the created websocket stream + with ‘MHD_websocket_stream_free()’. + + FLAGS + combination of ‘enum MHD_WEBSOCKET_FLAG’ values to modify the + behavior of the websocket stream. + + MAX_PAYLOAD_SIZE + maximum size for incoming payload data in bytes. Use 0 to + allow each size. + + Returns 0 on success, negative values on error. Can be compared + with ‘enum MHD_WEBSOCKET_STATUS’. + + -- Function: enum MHD_WEBSOCKET_STATUS MHD_websocket_stream_init2 + (struct MHD_WebSocketStream **ws, int flags, size_t + max_payload_size, MHD_WebSocketMallocCallback callback_malloc, + MHD_WebSocketReallocCallback callback_realloc, + MHD_WebSocketFreeCallback callback_free, void* cls_rng, + MHD_WebSocketRandomNumberGenerator callback_rng) + Creates a new websocket stream, used for decoding/encoding, but + with custom memory functions for malloc, realloc and free. Also a + random number generator can be specified for client mode. + + WS + pointer a variable to fill with the newly created ‘struct + MHD_WebSocketStream’, receives ‘NULL’ on error. Must not be + ‘NULL’. + + If not required anymore, free the created websocket stream + with ‘MHD_websocket_stream_free’. + + FLAGS + combination of ‘enum MHD_WEBSOCKET_FLAG’ values to modify the + behavior of the websocket stream. + + MAX_PAYLOAD_SIZE + maximum size for incoming payload data in bytes. Use 0 to + allow each size. + + CALLBACK_MALLOC + callback function for allocating memory. Must not be ‘NULL’. + The shorter ‘MHD_websocket_stream_init()’ passes a reference + to ‘malloc’ here. + + CALLBACK_REALLOC + callback function for reallocating memory. Must not be + ‘NULL’. The shorter ‘MHD_websocket_stream_init()’ passes a + reference to ‘realloc’ here. + + CALLBACK_FREE + callback function for freeing memory. Must not be ‘NULL’. + The shorter ‘MHD_websocket_stream_init()’ passes a reference + to ‘free’ here. + + CLS_RNG + closure for the random number generator. This is only + required when ‘MHD_WEBSOCKET_FLAG_CLIENT’ is passed in + ‘flags’. The given value is passed to the random number + generator callback. May be ‘NULL’ if not needed. Should be + ‘NULL’ when you are not using ‘MHD_WEBSOCKET_FLAG_CLIENT’. + The shorter ‘MHD_websocket_stream_init’ passes ‘NULL’ here. + + CALLBACK_RNG + callback function for a secure random number generator. This + is only required when ‘MHD_WEBSOCKET_FLAG_CLIENT’ is passed in + ‘flags’ and must not be ‘NULL’ then. Should be ‘NULL’ + otherwise. The shorter ‘MHD_websocket_stream_init()’ passes + ‘NULL’ here. + + Returns 0 on success, negative values on error. Can be compared + with ‘enum MHD_WEBSOCKET_STATUS’. + + -- Function: enum MHD_WEBSOCKET_STATUS MHD_websocket_stream_free + (struct MHD_WebSocketStream *ws) + Frees a previously allocated websocket stream + + WS + websocket stream to free, this value may be ‘NULL’. + + Returns 0 on success, negative values on error. Can be compared + with ‘enum MHD_WEBSOCKET_STATUS’. + + -- Function: enum MHD_WEBSOCKET_STATUS MHD_websocket_stream_invalidate + (struct MHD_WebSocketStream *ws) + Invalidates a websocket stream. After invalidation a websocket + stream cannot be used for decoding anymore. Encoding is still + possible. + + WS + websocket stream to invalidate. + + Returns 0 on success, negative values on error. Can be compared + with ‘enum MHD_WEBSOCKET_STATUS’. + + -- Function: enum MHD_WEBSOCKET_VALIDITY MHD_websocket_stream_is_valid + (struct MHD_WebSocketStream *ws) + Queries whether a websocket stream is valid. Invalidated websocket + streams cannot be used for decoding anymore. Encoding is still + possible. + + WS + websocket stream to invalidate. + + Returns 0 if invalid, 1 if valid for all types or 2 if valid only + for control frames. Can be compared with ‘enum + MHD_WEBSOCKET_VALIDITY’. + + +File: libmicrohttpd.info, Node: microhttpd-websocket decode, Next: microhttpd-websocket encode, Prev: microhttpd-websocket stream, Up: microhttpd-websocket + +14.3 Websocket decode functions +=============================== + + -- Function: enum MHD_WEBSOCKET_STATUS MHD_websocket_decode (struct + MHD_WebSocketStream* ws, const char* streambuf, size_t + streambuf_len, size_t* streambuf_read_len, char** payload, + size_t* payload_len) + Decodes a byte sequence for a websocket stream. Decoding is done + until either a frame is complete or the end of the byte sequence is + reached. + + WS + websocket stream for decoding. + + STREAMBUF + byte sequence for decoding. This is what you typically + received via ‘recv()’. + + STREAMBUF_LEN + length of the byte sequence in parameter ‘streambuf’. + + STREAMBUF_READ_LEN + pointer to a variable, which receives the number of bytes, + that has been processed by this call. This value may be less + than the value of ‘streambuf_len’ when a frame is decoded + before the end of the buffer is reached. The remaining bytes + of ‘buf’ must be passed to the next call of this function. + + PAYLOAD + pointer to a variable, which receives the allocated buffer + with the payload data of the decoded frame. Must not be + ‘NULL’. If no decoded data is available or an error occurred + ‘NULL’ is returned. When the returned value is not ‘NULL’ + then the buffer contains always ‘payload_len’ bytes plus one + terminating ‘NUL’ character (regardless of the frame type). + + The caller must free this buffer using ‘MHD_websocket_free()’. + + If you passed the flag + ‘MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR’ upon + creation of the websocket stream and a decoding error occurred + (function return value less than 0), then this buffer contains + a generated close frame, which must be sent via the socket to + the recipient. + + If you passed the flag ‘MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS’ + upon creation of the websocket stream then this payload may + only be a part of the complete message. Only complete UTF-8 + sequences are returned for fragmented text frames. If + necessary the UTF-8 sequence will be completed with the next + text fragment. + + PAYLOAD_LEN + pointer to a variable, which receives length of the result + ‘payload’ buffer in bytes. Must not be ‘NULL’. This receives + 0 when no data is available, when the decoded payload has a + length of zero or when an error occurred. + + Returns a value greater than zero when a frame is complete. + Compare with ‘enum MHD_WEBSOCKET_STATUS’ to distinguish the frame + type. Returns 0 when the call succeeded, but no frame is + available. Returns a value less than zero on errors. + + -- Function: enum MHD_WEBSOCKET_STATUS MHD_websocket_split_close_reason + (const char* payload, size_t payload_len, unsigned short* + reason_code, const char** reason_utf8, size_t* + reason_utf8_len) + Splits the payload of a decoded close frame. + + PAYLOAD + payload of the close frame. This parameter may only be ‘NULL’ + if ‘payload_len’ is 0. + + PAYLOAD_LEN + length of ‘payload’. + + REASON_CODE + pointer to a variable, which receives the numeric close + reason. If there was no close reason, this is 0. This value + can be compared with ‘enum MHD_WEBSOCKET_CLOSEREASON’. May be + ‘NULL’. + + REASON_UTF8 + pointer to a variable, which receives the literal close + reason. If there was no literal close reason, this will be + ‘NULL’. May be ‘NULL’. + + Please note that no memory is allocated in this function. If + not ‘NULL’ the returned value of this parameter points to a + position in the specified ‘payload’. + + REASON_UTF8_LEN + pointer to a variable, which receives the length of the + literal close reason. If there was no literal close reason, + this is 0. May be ‘NULL’. + + Returns 0 on success or a value less than zero on errors. Can be + compared with ‘enum MHD_WEBSOCKET_STATUS’. + + +File: libmicrohttpd.info, Node: microhttpd-websocket encode, Next: microhttpd-websocket memory, Prev: microhttpd-websocket decode, Up: microhttpd-websocket + +14.4 Websocket encode functions +=============================== + + -- Function: enum MHD_WEBSOCKET_STATUS MHD_websocket_encode_text + (struct MHD_WebSocketStream* ws, const char* payload_utf8, + size_t payload_utf8_len, int fragmentation, char** frame, + size_t* frame_len, int* utf8_step) + Encodes an UTF-8 encoded text into websocket text frame + + WS + websocket stream; + + PAYLOAD_UTF8 + text to send. This must be UTF-8 encoded. If you don't want + UTF-8 then send a binary frame with + ‘MHD_websocket_encode_binary()’ instead. May be be ‘NULL’ if + ‘payload_utf8_len’ is 0, must not be ‘NULL’ otherwise. + + PAYLOAD_UTF8_LEN + length of ‘payload_utf8’ in bytes. + + FRAGMENTATION + A value of ‘enum MHD_WEBSOCKET_FRAGMENTATION’ to specify the + fragmentation behavior. Specify + ‘MHD_WEBSOCKET_FRAGMENTATION_NONE’ or just 0 if you don't want + to use fragmentation (default). + + FRAME + pointer to a variable, which receives a buffer with the + encoded text frame. Must not be ‘NULL’. The buffer contains + what you typically send via ‘send()’ to the recipient. If no + encoded data is available the variable receives ‘NULL’. + + If the variable is not ‘NULL’ then the buffer contains always + ‘frame_len’ bytes plus one terminating ‘NUL’ character. The + caller must free this buffer using ‘MHD_websocket_free()’. + + FRAME_LEN + pointer to a variable, which receives the length of the + encoded frame in bytes. Must not be ‘NULL’. + + UTF8_STEP + If fragmentation is used (the parameter ‘fragmentation’ is not + 0) then is parameter is required and must not be ‘NULL’. If + no fragmentation is used, this parameter is optional and + should be ‘NULL’. + + This parameter is a pointer to a variable which contains the + last check status of the UTF-8 sequence. It is required to + continue a previous UTF-8 sequence check when fragmentation is + used, because a UTF-8 sequence could be split upon fragments. + + ‘enum MHD_WEBSOCKET_UTF8STEP’ is used for this value. If you + start a new fragment using ‘MHD_WEBSOCKET_FRAGMENTATION_NONE’ + or ‘MHD_WEBSOCKET_FRAGMENTATION_FIRST’ the old value of this + variable will be discarded and the value of this variable will + be initialized to ‘MHD_WEBSOCKET_UTF8STEP_NORMAL’. On all + other fragmentation modes the previous value of the pointed + variable will be used to continue the UTF-8 sequence check. + + Returns 0 on success or a value less than zero on errors. Can be + compared with ‘enum MHD_WEBSOCKET_STATUS’. + + -- Function: enum MHD_WEBSOCKET_STATUS MHD_websocket_encode_binary + (struct MHD_WebSocketStream* ws, const char* payload, size_t + payload_len, int fragmentation, char** frame, size_t* + frame_len) + Encodes binary data into websocket binary frame + + WS + websocket stream; + + PAYLOAD + binary data to send. May be be ‘NULL’ if ‘payload_len’ is 0, + must not be ‘NULL’ otherwise. + + PAYLOAD_LEN + length of ‘payload’ in bytes. + + FRAGMENTATION + A value of ‘enum MHD_WEBSOCKET_FRAGMENTATION’ to specify the + fragmentation behavior. Specify + ‘MHD_WEBSOCKET_FRAGMENTATION_NONE’ or just 0 if you don't want + to use fragmentation (default). + + FRAME + pointer to a variable, which receives a buffer with the + encoded binary frame. Must not be ‘NULL’. The buffer + contains what you typically send via ‘send()’ to the + recipient. If no encoded data is available the variable + receives ‘NULL’. + + If the variable is not ‘NULL’ then the buffer contains always + ‘frame_len’ bytes plus one terminating ‘NUL’ character. The + caller must free this buffer using ‘MHD_websocket_free()’. + + FRAME_LEN + pointer to a variable, which receives the length of the + encoded frame in bytes. Must not be ‘NULL’. + + Returns 0 on success or a value less than zero on errors. Can be + compared with ‘enum MHD_WEBSOCKET_STATUS’. + + -- Function: enum MHD_WEBSOCKET_STATUS MHD_websocket_encode_ping + (struct MHD_WebSocketStream* ws, const char* payload, size_t + payload_len, char** frame, size_t* frame_len) + Encodes a websocket ping frame. Ping frames are used to check + whether a recipient is still available and what latency the + websocket connection has. + + WS + websocket stream; + + PAYLOAD + binary ping data to send. May be ‘NULL’ if ‘payload_len’ is + 0. + + PAYLOAD_LEN + length of ‘payload’ in bytes. This may not exceed 125 bytes. + + FRAME + pointer to a variable, which receives a buffer with the + encoded ping frame. Must not be ‘NULL’. The buffer contains + what you typically send via ‘send()’ to the recipient. If no + encoded data is available the variable receives ‘NULL’. + + If the variable is not ‘NULL’ then the buffer contains always + ‘frame_len’ bytes plus one terminating ‘NUL’ character. The + caller must free this buffer using ‘MHD_websocket_free()’. + + FRAME_LEN + pointer to a variable, which receives the length of the + encoded frame in bytes. Must not be ‘NULL’. + + Returns 0 on success or a value less than zero on errors. Can be + compared with ‘enum MHD_WEBSOCKET_STATUS’. + + -- Function: enum MHD_WEBSOCKET_STATUS MHD_websocket_encode_pong + (struct MHD_WebSocketStream* ws, const char* payload, size_t + payload_len, char** frame, size_t* frame_len) + Encodes a websocket pong frame. Pong frames are used to answer a + previously received websocket ping frame. + + WS + websocket stream; + + PAYLOAD + binary pong data to send, which should be the decoded payload + from the received ping frame. May be ‘NULL’ if ‘payload_len’ + is 0. + + PAYLOAD_LEN + length of ‘payload’ in bytes. This may not exceed 125 bytes. + + FRAME + pointer to a variable, which receives a buffer with the + encoded pong frame. Must not be ‘NULL’. The buffer contains + what you typically send via ‘send()’ to the recipient. If no + encoded data is available the variable receives ‘NULL’. + + If the variable is not ‘NULL’ then the buffer contains always + ‘frame_len’ bytes plus one terminating ‘NUL’ character. The + caller must free this buffer using ‘MHD_websocket_free()’. + + FRAME_LEN + pointer to a variable, which receives the length of the + encoded frame in bytes. Must not be ‘NULL’. + + Returns 0 on success or a value less than zero on errors. Can be + compared with ‘enum MHD_WEBSOCKET_STATUS’. + + -- Function: enum MHD_WEBSOCKET_STATUS MHD_websocket_encode_close + (struct MHD_WebSocketStream* ws, unsigned short reason_code, + const char* reason_utf8, size_t reason_utf8_len, char** frame, + size_t* frame_len) + Encodes a websocket close frame. Close frames are used to close a + websocket connection in a formal way. + + WS + websocket stream; + + REASON_CODE + reason for close. You can use ‘enum + MHD_WEBSOCKET_CLOSEREASON’ for typical reasons, but you are + not limited to these values. The allowed values are specified + in RFC 6455 7.4. If you don't want to enter a reason, you can + specify ‘MHD_WEBSOCKET_CLOSEREASON_NO_REASON’ (or just 0) then + no reason is encoded. + + REASON_UTF8 + An UTF-8 encoded text reason why the connection is closed. + This may be ‘NULL’ if ‘reason_utf8_len’ is 0. This must be + ‘NULL’ if ‘reason_code’ equals to zero + (‘MHD_WEBSOCKET_CLOSEREASON_NO_REASON’). + + REASON_UTF8_LEN + length of the UTF-8 encoded text reason in bytes. This may + not exceed 123 bytes. + + FRAME + pointer to a variable, which receives a buffer with the + encoded close frame. Must not be ‘NULL’. The buffer contains + what you typically send via ‘send()’ to the recipient. If no + encoded data is available the variable receives ‘NULL’. + + If the variable is not ‘NULL’ then the buffer contains always + ‘frame_len’ bytes plus one terminating ‘NUL’ character. The + caller must free this buffer using ‘MHD_websocket_free()’. + + FRAME_LEN + pointer to a variable, which receives the length of the + encoded frame in bytes. Must not be ‘NULL’. + + Returns 0 on success or a value less than zero on errors. Can be + compared with ‘enum MHD_WEBSOCKET_STATUS’. + + +File: libmicrohttpd.info, Node: microhttpd-websocket memory, Prev: microhttpd-websocket encode, Up: microhttpd-websocket + +14.5 Websocket memory functions +=============================== + + -- Function: void* MHD_websocket_malloc (struct MHD_WebSocketStream* + ws, size_t buf_len) + Allocates memory with the associated ‘malloc()’ function of the + websocket stream. The memory allocation function could be + different for a websocket stream if ‘MHD_websocket_stream_init2()’ + has been used for initialization. + + WS + websocket stream; + + BUF_LEN + size of the buffer to allocate in bytes. + + Returns the pointer of the allocated buffer or ‘NULL’ on failure. + + -- Function: void* MHD_websocket_realloc (struct MHD_WebSocketStream* + ws, void* buf, size_t new_buf_len) + Reallocates memory with the associated ‘realloc()’ function of the + websocket stream. The memory reallocation function could be + different for a websocket stream if ‘MHD_websocket_stream_init2()’ + has been used for initialization. + + WS + websocket stream; + + BUF + current buffer, may be ‘NULL’; + + NEW_BUF_LEN + new size of the buffer in bytes. + + Return the pointer of the reallocated buffer or ‘NULL’ on failure. + On failure the old pointer remains valid. + + -- Function: void MHD_websocket_free (struct MHD_WebSocketStream* ws, + void* buf) + Frees memory with the associated ‘free()’ function of the websocket + stream. The memory free function could be different for a + websocket stream if ‘MHD_websocket_stream_init2()’ has been used + for initialization. + + WS + websocket stream; + + BUF + buffer to free, this may be ‘NULL’ then nothing happens. + + +File: libmicrohttpd.info, Node: GNU-LGPL, Next: eCos License, Prev: microhttpd-websocket, Up: Top + +GNU-LGPL +******** + + Version 2.1, February 1999 + + Copyright © 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + [This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence the + version number 2.1.] + +Preamble +-------- + +The licenses for most software are designed to take away your freedom to +share and change it. By contrast, the GNU General Public Licenses are +intended to guarantee your freedom to share and change free software--to +make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software--typically libraries--of the Free Software +Foundation and other authors who decide to use it. You can use it too, +but we suggest you first think carefully about whether this license or +the ordinary General Public License is the better strategy to use in any +particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of it +in new free programs; and that you are informed that you can do these +things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling it. +And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that there +is no warranty for the free library. Also, if the library is modified +by someone else and passed on, the recipients should know that what they +have is not the original version, so that the original author's +reputation will not be affected by problems that might be introduced by +others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that any +patent license obtained for a version of the library must be consistent +with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and is +quite different from the ordinary General Public License. We use this +license for certain libraries in order to permit linking those libraries +into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the entire +combination fits its criteria of freedom. The Lesser General Public +License permits more lax criteria for linking other code with the +library. + + We call this license the “Lesser” General Public License because it +does _Less_ to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less of +an advantage over competing non-free programs. These disadvantages are +the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free library +does the same job as widely used non-free libraries. In this case, +there is little to gain by limiting the free library to free software +only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of free +software. For example, permission to use the GNU C Library in non-free +programs enables many more people to use the whole GNU operating system, +as well as its variant, the GNU/Linux operating system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is linked +with the Library has the freedom and the wherewithal to run that program +using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +--------------------------------------------------------------- + + 0. This License Agreement applies to any software library or other + program which contains a notice placed by the copyright holder or + other authorized party saying it may be distributed under the terms + of this Lesser General Public License (also called "this License"). + Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data + prepared so as to be conveniently linked with application programs + (which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work + which has been distributed under these terms. A "work based on the + Library" means either the Library or any derivative work under + copyright law: that is to say, a work containing the Library or a + portion of it, either verbatim or with modifications and/or + translated straightforwardly into another language. (Hereinafter, + translation is included without limitation in the term + "modification".) + + "Source code" for a work means the preferred form of the work for + making modifications to it. For a library, complete source code + means all the source code for all modules it contains, plus any + associated interface definition files, plus the scripts used to + control compilation and installation of the library. + + Activities other than copying, distribution and modification are + not covered by this License; they are outside its scope. The act + of running a program using the Library is not restricted, and + output from such a program is covered only if its contents + constitute a work based on the Library (independent of the use of + the Library in a tool for writing it). Whether that is true + depends on what the Library does and what the program that uses the + Library does. + + 1. You may copy and distribute verbatim copies of the Library's + complete source code as you receive it, in any medium, provided + that you conspicuously and appropriately publish on each copy an + appropriate copyright notice and disclaimer of warranty; keep + intact all the notices that refer to this License and to the + absence of any warranty; and distribute a copy of this License + along with the Library. + + You may charge a fee for the physical act of transferring a copy, + and you may at your option offer warranty protection in exchange + for a fee. + + 2. You may modify your copy or copies of the Library or any portion of + it, thus forming a work based on the Library, and copy and + distribute such modifications or work under the terms of Section 1 + above, provided that you also meet all of these conditions: + + a. The modified work must itself be a software library. + + b. You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c. You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d. If a facility in the modified Library refers to a function or + a table of data to be supplied by an application program that + uses the facility, other than as an argument passed when the + facility is invoked, then you must make a good faith effort to + ensure that, in the event an application does not supply such + function or table, the facility still operates, and performs + whatever part of its purpose remains meaningful. + + (For example, a function in a library to compute square roots + has a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function + must be optional: if the application does not supply it, the + square root function must still compute square roots.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the + Library, and can be reasonably considered independent and separate + works in themselves, then this License, and its terms, do not apply + to those sections when you distribute them as separate works. But + when you distribute the same sections as part of a whole which is a + work based on the Library, the distribution of the whole must be on + the terms of this License, whose permissions for other licensees + extend to the entire whole, and thus to each and every part + regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or + contest your rights to work written entirely by you; rather, the + intent is to exercise the right to control the distribution of + derivative or collective works based on the Library. + + In addition, mere aggregation of another work not based on the + Library with the Library (or with a work based on the Library) on a + volume of a storage or distribution medium does not bring the other + work under the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public + License instead of this License to a given copy of the Library. To + do this, you must alter all the notices that refer to this License, + so that they refer to the ordinary GNU General Public License, + version 2, instead of to this License. (If a newer version than + version 2 of the ordinary GNU General Public License has appeared, + then you can specify that version instead if you wish.) Do not + make any other change in these notices. + + Once this change is made in a given copy, it is irreversible for + that copy, so the ordinary GNU General Public License applies to + all subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of the + Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or derivative + of it, under Section 2) in object code or executable form under the + terms of Sections 1 and 2 above provided that you accompany it with + the complete corresponding machine-readable source code, which must + be distributed under the terms of Sections 1 and 2 above on a + medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy + from a designated place, then offering equivalent access to copy + the source code from the same place satisfies the requirement to + distribute the source code, even though third parties are not + compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the + Library, but is designed to work with the Library by being compiled + or linked with it, is called a "work that uses the Library". Such + a work, in isolation, is not a derivative work of the Library, and + therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library + creates an executable that is a derivative of the Library (because + it contains portions of the Library), rather than a "work that uses + the library". The executable is therefore covered by this License. + Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header + file that is part of the Library, the object code for the work may + be a derivative work of the Library even though the source code is + not. Whether this is true is especially significant if the work + can be linked without the Library, or if the work is itself a + library. The threshold for this to be true is not precisely + defined by law. + + If such an object file uses only numerical parameters, data + structure layouts and accessors, and small macros and small inline + functions (ten lines or less in length), then the use of the object + file is unrestricted, regardless of whether it is legally a + derivative work. (Executables containing this object code plus + portions of the Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may + distribute the object code for the work under the terms of Section + 6. Any executables containing that work also fall under Section 6, + whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or link + a "work that uses the Library" with the Library to produce a work + containing portions of the Library, and distribute that work under + terms of your choice, provided that the terms permit modification + of the work for the customer's own use and reverse engineering for + debugging such modifications. + + You must give prominent notice with each copy of the work that the + Library is used in it and that the Library and its use are covered + by this License. You must supply a copy of this License. If the + work during execution displays copyright notices, you must include + the copyright notice for the Library among them, as well as a + reference directing the user to the copy of this License. Also, + you must do one of these things: + + a. Accompany the work with the complete corresponding + machine-readable source code for the Library including + whatever changes were used in the work (which must be + distributed under Sections 1 and 2 above); and, if the work is + an executable linked with the Library, with the complete + machine-readable "work that uses the Library", as object code + and/or source code, so that the user can modify the Library + and then relink to produce a modified executable containing + the modified Library. (It is understood that the user who + changes the contents of definitions files in the Library will + not necessarily be able to recompile the application to use + the modified definitions.) + + b. Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run + time a copy of the library already present on the user's + computer system, rather than copying library functions into + the executable, and (2) will operate properly with a modified + version of the library, if the user installs one, as long as + the modified version is interface-compatible with the version + that the work was made with. + + c. Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d. If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the + above specified materials from the same place. + + e. Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the + Library" must include any data and utility programs needed for + reproducing the executable from it. However, as a special + exception, the materials to be distributed need not include + anything that is normally distributed (in either source or binary + form) with the major components (compiler, kernel, and so on) of + the operating system on which the executable runs, unless that + component itself accompanies the executable. + + It may happen that this requirement contradicts the license + restrictions of other proprietary libraries that do not normally + accompany the operating system. Such a contradiction means you + cannot use both them and the Library together in an executable that + you distribute. + + 7. You may place library facilities that are a work based on the + Library side-by-side in a single library together with other + library facilities not covered by this License, and distribute such + a combined library, provided that the separate distribution of the + work based on the Library and of the other library facilities is + otherwise permitted, and provided that you do these two things: + + a. Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b. Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same + work. + + 8. You may not copy, modify, sublicense, link with, or distribute the + Library except as expressly provided under this License. Any + attempt otherwise to copy, modify, sublicense, link with, or + distribute the Library is void, and will automatically terminate + your rights under this License. However, parties who have received + copies, or rights, from you under this License will not have their + licenses terminated so long as such parties remain in full + compliance. + + 9. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify + or distribute the Library or its derivative works. These actions + are prohibited by law if you do not accept this License. + Therefore, by modifying or distributing the Library (or any work + based on the Library), you indicate your acceptance of this License + to do so, and all its terms and conditions for copying, + distributing or modifying the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the + Library), the recipient automatically receives a license from the + original licensor to copy, distribute, link with or modify the + Library subject to these terms and conditions. You may not impose + any further restrictions on the recipients' exercise of the rights + granted herein. You are not responsible for enforcing compliance + by third parties with this License. + + 11. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent + issues), conditions are imposed on you (whether by court order, + agreement or otherwise) that contradict the conditions of this + License, they do not excuse you from the conditions of this + License. If you cannot distribute so as to satisfy simultaneously + your obligations under this License and any other pertinent + obligations, then as a consequence you may not distribute the + Library at all. For example, if a patent license would not permit + royalty-free redistribution of the Library by all those who receive + copies directly or indirectly through you, then the only way you + could satisfy both it and this License would be to refrain entirely + from distribution of the Library. + + If any portion of this section is held invalid or unenforceable + under any particular circumstance, the balance of the section is + intended to apply, and the section as a whole is intended to apply + in other circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of + any such claims; this section has the sole purpose of protecting + the integrity of the free software distribution system which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is + willing to distribute software through any other system and a + licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed + to be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in + certain countries either by patents or by copyrighted interfaces, + the original copyright holder who places the Library under this + License may add an explicit geographical distribution limitation + excluding those countries, so that distribution is permitted only + in or among countries not thus excluded. In such case, this + License incorporates the limitation as if written in the body of + this License. + + 13. The Free Software Foundation may publish revised and/or new + versions of the Lesser General Public License from time to time. + Such new versions will be similar in spirit to the present version, + but may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the + Library specifies a version number of this License which applies to + it and "any later version", you have the option of following the + terms and conditions either of that version or of any later version + published by the Free Software Foundation. If the Library does not + specify a license version number, you may choose any version ever + published by the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free + programs whose distribution conditions are incompatible with these, + write to the author to ask for permission. For software which is + copyrighted by the Free Software Foundation, write to the Free + Software Foundation; we sometimes make exceptions for this. Our + decision will be guided by the two goals of preserving the free + status of all derivatives of our free software and of promoting the + sharing and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO + WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE + LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS + AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY + OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND + PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE + DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR + OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN + WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY + MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE + LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, + INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR + INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF + DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU + OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY + OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS +--------------------------- + +How to Apply These Terms to Your New Libraries +---------------------------------------------- + +If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of +the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should have +at least the "copyright" line and a pointer to where the full notice is +found. + + ONE LINE TO GIVE THE LIBRARY'S NAME AND AN IDEA OF WHAT IT DOES. + Copyright (C) YEAR NAME OF AUTHOR + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. + + Also add information on how to contact you by electronic and paper +mail. + + You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the library + `Frob' (a library for tweaking knobs) written by James Random Hacker. + + SIGNATURE OF TY COON, 1 April 1990 + Ty Coon, President of Vice + + That's all there is to it! + + +File: libmicrohttpd.info, Node: eCos License, Next: GNU-GPL, Prev: GNU-LGPL, Up: Top + +eCos License +************ + +GNU libmicrohttpd is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published +by the Free Software Foundation; either version 2 or (at your option) +any later version. + + GNU libmicrohttpd is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +Public License for more details. + + You should have received a copy of the GNU General Public License +along with GNU libmicrohttpd; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. + + As a special exception, if other files instantiate templates or use +macros or inline functions from this file, or you compile this file and +link it with other works to produce a work based on this file, this file +does not by itself cause the resulting work to be covered by the GNU +General Public License. However the source code for this file must +still be made available in accordance with section (3) of the GNU +General Public License v2. + + This exception does not invalidate any other reasons why a work based +on this file might be covered by the GNU General Public License. + + +File: libmicrohttpd.info, Node: GNU-GPL, Next: GNU-FDL, Prev: eCos License, Up: Top + +GNU General Public License +************************** + + Version 2, June 1991 + + Copyright © 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +Preamble +======== + +The licenses for most software are designed to take away your freedom to +share and change it. By contrast, the GNU General Public License is +intended to guarantee your freedom to share and change free software--to +make sure the software is free for all its users. This General Public +License applies to most of the Free Software Foundation's software and +to any other program whose authors commit to using it. (Some other Free +Software Foundation software is covered by the GNU Lesser General Public +License instead.) You can apply it to your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it if +you want it, that you can change the software or use pieces of it in new +free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, +and (2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +=============================================================== + + 0. This License applies to any program or other work which contains a + notice placed by the copyright holder saying it may be distributed + under the terms of this General Public License. The "Program", + below, refers to any such program or work, and a "work based on the + Program" means either the Program or any derivative work under + copyright law: that is to say, a work containing the Program or a + portion of it, either verbatim or with modifications and/or + translated into another language. (Hereinafter, translation is + included without limitation in the term "modification".) Each + licensee is addressed as "you". + + Activities other than copying, distribution and modification are + not covered by this License; they are outside its scope. The act + of running the Program is not restricted, and the output from the + Program is covered only if its contents constitute a work based on + the Program (independent of having been made by running the + Program). Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's source + code as you receive it, in any medium, provided that you + conspicuously and appropriately publish on each copy an appropriate + copyright notice and disclaimer of warranty; keep intact all the + notices that refer to this License and to the absence of any + warranty; and give any other recipients of the Program a copy of + this License along with the Program. + + You may charge a fee for the physical act of transferring a copy, + and you may at your option offer warranty protection in exchange + for a fee. + + 2. You may modify your copy or copies of the Program or any portion of + it, thus forming a work based on the Program, and copy and + distribute such modifications or work under the terms of Section 1 + above, provided that you also meet all of these conditions: + + a. You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b. You must cause any work that you distribute or publish, that + in whole or in part contains or is derived from the Program or + any part thereof, to be licensed as a whole at no charge to + all third parties under the terms of this License. + + c. If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display + an announcement including an appropriate copyright notice and + a notice that there is no warranty (or else, saying that you + provide a warranty) and that users may redistribute the + program under these conditions, and telling the user how to + view a copy of this License. (Exception: if the Program + itself is interactive but does not normally print such an + announcement, your work based on the Program is not required + to print an announcement.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the + Program, and can be reasonably considered independent and separate + works in themselves, then this License, and its terms, do not apply + to those sections when you distribute them as separate works. But + when you distribute the same sections as part of a whole which is a + work based on the Program, the distribution of the whole must be on + the terms of this License, whose permissions for other licensees + extend to the entire whole, and thus to each and every part + regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or + contest your rights to work written entirely by you; rather, the + intent is to exercise the right to control the distribution of + derivative or collective works based on the Program. + + In addition, mere aggregation of another work not based on the + Program with the Program (or with a work based on the Program) on a + volume of a storage or distribution medium does not bring the other + work under the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms + of Sections 1 and 2 above provided that you also do one of the + following: + + a. Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Sections 1 and 2 above on a medium customarily used for + software interchange; or, + + b. Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a + medium customarily used for software interchange; or, + + c. Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with + such an offer, in accord with Subsection b above.) + + The source code for a work means the preferred form of the work for + making modifications to it. For an executable work, complete + source code means all the source code for all modules it contains, + plus any associated interface definition files, plus the scripts + used to control compilation and installation of the executable. + However, as a special exception, the source code distributed need + not include anything that is normally distributed (in either source + or binary form) with the major components (compiler, kernel, and so + on) of the operating system on which the executable runs, unless + that component itself accompanies the executable. + + If distribution of executable or object code is made by offering + access to copy from a designated place, then offering equivalent + access to copy the source code from the same place counts as + distribution of the source code, even though third parties are not + compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense or distribute the Program is + void, and will automatically terminate your rights under this + License. However, parties who have received copies, or rights, + from you under this License will not have their licenses terminated + so long as such parties remain in full compliance. + + 5. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify + or distribute the Program or its derivative works. These actions + are prohibited by law if you do not accept this License. + Therefore, by modifying or distributing the Program (or any work + based on the Program), you indicate your acceptance of this License + to do so, and all its terms and conditions for copying, + distributing or modifying the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program subject + to these terms and conditions. You may not impose any further + restrictions on the recipients' exercise of the rights granted + herein. You are not responsible for enforcing compliance by third + parties to this License. + + 7. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent + issues), conditions are imposed on you (whether by court order, + agreement or otherwise) that contradict the conditions of this + License, they do not excuse you from the conditions of this + License. If you cannot distribute so as to satisfy simultaneously + your obligations under this License and any other pertinent + obligations, then as a consequence you may not distribute the + Program at all. For example, if a patent license would not permit + royalty-free redistribution of the Program by all those who receive + copies directly or indirectly through you, then the only way you + could satisfy both it and this License would be to refrain entirely + from distribution of the Program. + + If any portion of this section is held invalid or unenforceable + under any particular circumstance, the balance of the section is + intended to apply and the section as a whole is intended to apply + in other circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of + any such claims; this section has the sole purpose of protecting + the integrity of the free software distribution system, which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is + willing to distribute software through any other system and a + licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed + to be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, + the original copyright holder who places the Program under this + License may add an explicit geographical distribution limitation + excluding those countries, so that distribution is permitted only + in or among countries not thus excluded. In such case, this + License incorporates the limitation as if written in the body of + this License. + + 9. The Free Software Foundation may publish revised and/or new + versions of the General Public License from time to time. Such new + versions will be similar in spirit to the present version, but may + differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the + Program specifies a version number of this License which applies to + it and "any later version", you have the option of following the + terms and conditions either of that version or of any later version + published by the Free Software Foundation. If the Program does not + specify a version number of this License, you may choose any + version ever published by the Free Software Foundation. + + 10. If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the + author to ask for permission. For software which is copyrighted by + the Free Software Foundation, write to the Free Software + Foundation; we sometimes make exceptions for this. Our decision + will be guided by the two goals of preserving the free status of + all derivatives of our free software and of promoting the sharing + and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO + WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE + LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS + AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY + OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND + PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE + DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR + OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN + WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY + MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE + LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, + INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR + INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF + DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU + OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY + OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + +Appendix: How to Apply These Terms to Your New Programs +======================================================= + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES. + Copyright (C) YYYY NAME OF AUTHOR + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Also add information on how to contact you by electronic and paper +mail. + + If the program is interactive, make it output a short notice like +this when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) YEAR NAME OF AUTHOR + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + + The hypothetical commands ‘show w’ and ‘show c’ should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than ‘show w’ and ‘show +c’; they could even be mouse-clicks or menu items--whatever suits your +program. + + You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the program, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + SIGNATURE OF TY COON, 1 April 1989 + Ty Coon, President of Vice + + This General Public License does not permit incorporating your +program into proprietary programs. If your program is a subroutine +library, you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use the +GNU Lesser General Public License instead of this License. + + +File: libmicrohttpd.info, Node: GNU-FDL, Next: Concept Index, Prev: GNU-GPL, Up: Top + +GNU-FDL +******* + + Version 1.3, 3 November 2008 + + Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. + + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + 0. PREAMBLE + + The purpose of this License is to make a manual, textbook, or other + functional and useful document “free” in the sense of freedom: to + assure everyone the effective freedom to copy and redistribute it, + with or without modifying it, either commercially or + noncommercially. Secondarily, this License preserves for the + author and publisher a way to get credit for their work, while not + being considered responsible for modifications made by others. + + This License is a kind of "copyleft", which means that derivative + works of the document must themselves be free in the same sense. + It complements the GNU General Public License, which is a copyleft + license designed for free software. + + We have designed this License in order to use it for manuals for + free software, because free software needs free documentation: a + free program should come with manuals providing the same freedoms + that the software does. But this License is not limited to + software manuals; it can be used for any textual work, regardless + of subject matter or whether it is published as a printed book. We + recommend this License principally for works whose purpose is + instruction or reference. + + 1. APPLICABILITY AND DEFINITIONS + + This License applies to any manual or other work, in any medium, + that contains a notice placed by the copyright holder saying it can + be distributed under the terms of this License. Such a notice + grants a world-wide, royalty-free license, unlimited in duration, + to use that work under the conditions stated herein. The + "Document", below, refers to any such manual or work. Any member + of the public is a licensee, and is addressed as "you". You accept + the license if you copy, modify or distribute the work in a way + requiring permission under copyright law. + + A "Modified Version" of the Document means any work containing the + Document or a portion of it, either copied verbatim, or with + modifications and/or translated into another language. + + A "Secondary Section" is a named appendix or a front-matter section + of the Document that deals exclusively with the relationship of the + publishers or authors of the Document to the Document's overall + subject (or to related matters) and contains nothing that could + fall directly within that overall subject. (Thus, if the Document + is in part a textbook of mathematics, a Secondary Section may not + explain any mathematics.) The relationship could be a matter of + historical connection with the subject or with related matters, or + of legal, commercial, philosophical, ethical or political position + regarding them. + + The "Invariant Sections" are certain Secondary Sections whose + titles are designated, as being those of Invariant Sections, in the + notice that says that the Document is released under this License. + If a section does not fit the above definition of Secondary then it + is not allowed to be designated as Invariant. The Document may + contain zero Invariant Sections. If the Document does not identify + any Invariant Sections then there are none. + + The "Cover Texts" are certain short passages of text that are + listed, as Front-Cover Texts or Back-Cover Texts, in the notice + that says that the Document is released under this License. A + Front-Cover Text may be at most 5 words, and a Back-Cover Text may + be at most 25 words. + + A "Transparent" copy of the Document means a machine-readable copy, + represented in a format whose specification is available to the + general public, that is suitable for revising the document + straightforwardly with generic text editors or (for images composed + of pixels) generic paint programs or (for drawings) some widely + available drawing editor, and that is suitable for input to text + formatters or for automatic translation to a variety of formats + suitable for input to text formatters. A copy made in an otherwise + Transparent file format whose markup, or absence of markup, has + been arranged to thwart or discourage subsequent modification by + readers is not Transparent. An image format is not Transparent if + used for any substantial amount of text. A copy that is not + "Transparent" is called "Opaque". + + Examples of suitable formats for Transparent copies include plain + ASCII without markup, Texinfo input format, LaTeX input format, + SGML or XML using a publicly available DTD, and standard-conforming + simple HTML, PostScript or PDF designed for human modification. + Examples of transparent image formats include PNG, XCF and JPG. + Opaque formats include proprietary formats that can be read and + edited only by proprietary word processors, SGML or XML for which + the DTD and/or processing tools are not generally available, and + the machine-generated HTML, PostScript or PDF produced by some word + processors for output purposes only. + + The "Title Page" means, for a printed book, the title page itself, + plus such following pages as are needed to hold, legibly, the + material this License requires to appear in the title page. For + works in formats which do not have any title page as such, "Title + Page" means the text near the most prominent appearance of the + work's title, preceding the beginning of the body of the text. + + The "publisher" means any person or entity that distributes copies + of the Document to the public. + + A section "Entitled XYZ" means a named subunit of the Document + whose title either is precisely XYZ or contains XYZ in parentheses + following text that translates XYZ in another language. (Here XYZ + stands for a specific section name mentioned below, such as + "Acknowledgements", "Dedications", "Endorsements", or "History".) + To "Preserve the Title" of such a section when you modify the + Document means that it remains a section "Entitled XYZ" according + to this definition. + + The Document may include Warranty Disclaimers next to the notice + which states that this License applies to the Document. These + Warranty Disclaimers are considered to be included by reference in + this License, but only as regards disclaiming warranties: any other + implication that these Warranty Disclaimers may have is void and + has no effect on the meaning of this License. + + 2. VERBATIM COPYING + + You may copy and distribute the Document in any medium, either + commercially or noncommercially, provided that this License, the + copyright notices, and the license notice saying this License + applies to the Document are reproduced in all copies, and that you + add no other conditions whatsoever to those of this License. You + may not use technical measures to obstruct or control the reading + or further copying of the copies you make or distribute. However, + you may accept compensation in exchange for copies. If you + distribute a large enough number of copies you must also follow the + conditions in section 3. + + You may also lend copies, under the same conditions stated above, + and you may publicly display copies. + + 3. COPYING IN QUANTITY + + If you publish printed copies (or copies in media that commonly + have printed covers) of the Document, numbering more than 100, and + the Document's license notice requires Cover Texts, you must + enclose the copies in covers that carry, clearly and legibly, all + these Cover Texts: Front-Cover Texts on the front cover, and + Back-Cover Texts on the back cover. Both covers must also clearly + and legibly identify you as the publisher of these copies. The + front cover must present the full title with all words of the title + equally prominent and visible. You may add other material on the + covers in addition. Copying with changes limited to the covers, as + long as they preserve the title of the Document and satisfy these + conditions, can be treated as verbatim copying in other respects. + + If the required texts for either cover are too voluminous to fit + legibly, you should put the first ones listed (as many as fit + reasonably) on the actual cover, and continue the rest onto + adjacent pages. + + If you publish or distribute Opaque copies of the Document + numbering more than 100, you must either include a machine-readable + Transparent copy along with each Opaque copy, or state in or with + each Opaque copy a computer-network location from which the general + network-using public has access to download using public-standard + network protocols a complete Transparent copy of the Document, free + of added material. If you use the latter option, you must take + reasonably prudent steps, when you begin distribution of Opaque + copies in quantity, to ensure that this Transparent copy will + remain thus accessible at the stated location until at least one + year after the last time you distribute an Opaque copy (directly or + through your agents or retailers) of that edition to the public. + + It is requested, but not required, that you contact the authors of + the Document well before redistributing any large number of copies, + to give them a chance to provide you with an updated version of the + Document. + + 4. MODIFICATIONS + + You may copy and distribute a Modified Version of the Document + under the conditions of sections 2 and 3 above, provided that you + release the Modified Version under precisely this License, with the + Modified Version filling the role of the Document, thus licensing + distribution and modification of the Modified Version to whoever + possesses a copy of it. In addition, you must do these things in + the Modified Version: + + A. Use in the Title Page (and on the covers, if any) a title + distinct from that of the Document, and from those of previous + versions (which should, if there were any, be listed in the + History section of the Document). You may use the same title + as a previous version if the original publisher of that + version gives permission. + + B. List on the Title Page, as authors, one or more persons or + entities responsible for authorship of the modifications in + the Modified Version, together with at least five of the + principal authors of the Document (all of its principal + authors, if it has fewer than five), unless they release you + from this requirement. + + C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. + + D. Preserve all the copyright notices of the Document. + + E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. + + F. Include, immediately after the copyright notices, a license + notice giving the public permission to use the Modified + Version under the terms of this License, in the form shown in + the Addendum below. + + G. Preserve in that license notice the full lists of Invariant + Sections and required Cover Texts given in the Document's + license notice. + + H. Include an unaltered copy of this License. + + I. Preserve the section Entitled "History", Preserve its Title, + and add to it an item stating at least the title, year, new + authors, and publisher of the Modified Version as given on the + Title Page. If there is no section Entitled "History" in the + Document, create one stating the title, year, authors, and + publisher of the Document as given on its Title Page, then add + an item describing the Modified Version as stated in the + previous sentence. + + J. Preserve the network location, if any, given in the Document + for public access to a Transparent copy of the Document, and + likewise the network locations given in the Document for + previous versions it was based on. These may be placed in the + "History" section. You may omit a network location for a work + that was published at least four years before the Document + itself, or if the original publisher of the version it refers + to gives permission. + + K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section + all the substance and tone of each of the contributor + acknowledgements and/or dedications given therein. + + L. Preserve all the Invariant Sections of the Document, unaltered + in their text and in their titles. Section numbers or the + equivalent are not considered part of the section titles. + + M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. + + N. Do not retitle any existing section to be Entitled + "Endorsements" or to conflict in title with any Invariant + Section. + + O. Preserve any Warranty Disclaimers. + + If the Modified Version includes new front-matter sections or + appendices that qualify as Secondary Sections and contain no + material copied from the Document, you may at your option designate + some or all of these sections as invariant. To do this, add their + titles to the list of Invariant Sections in the Modified Version's + license notice. These titles must be distinct from any other + section titles. + + You may add a section Entitled "Endorsements", provided it contains + nothing but endorsements of your Modified Version by various + parties--for example, statements of peer review or that the text + has been approved by an organization as the authoritative + definition of a standard. + + You may add a passage of up to five words as a Front-Cover Text, + and a passage of up to 25 words as a Back-Cover Text, to the end of + the list of Cover Texts in the Modified Version. Only one passage + of Front-Cover Text and one of Back-Cover Text may be added by (or + through arrangements made by) any one entity. If the Document + already includes a cover text for the same cover, previously added + by you or by arrangement made by the same entity you are acting on + behalf of, you may not add another; but you may replace the old + one, on explicit permission from the previous publisher that added + the old one. + + The author(s) and publisher(s) of the Document do not by this + License give permission to use their names for publicity for or to + assert or imply endorsement of any Modified Version. + + 5. COMBINING DOCUMENTS + + You may combine the Document with other documents released under + this License, under the terms defined in section 4 above for + modified versions, provided that you include in the combination all + of the Invariant Sections of all of the original documents, + unmodified, and list them all as Invariant Sections of your + combined work in its license notice, and that you preserve all + their Warranty Disclaimers. + + The combined work need only contain one copy of this License, and + multiple identical Invariant Sections may be replaced with a single + copy. If there are multiple Invariant Sections with the same name + but different contents, make the title of each such section unique + by adding at the end of it, in parentheses, the name of the + original author or publisher of that section if known, or else a + unique number. Make the same adjustment to the section titles in + the list of Invariant Sections in the license notice of the + combined work. + + In the combination, you must combine any sections Entitled + "History" in the various original documents, forming one section + Entitled "History"; likewise combine any sections Entitled + "Acknowledgements", and any sections Entitled "Dedications". You + must delete all sections Entitled "Endorsements." + + 6. COLLECTIONS OF DOCUMENTS + + You may make a collection consisting of the Document and other + documents released under this License, and replace the individual + copies of this License in the various documents with a single copy + that is included in the collection, provided that you follow the + rules of this License for verbatim copying of each of the documents + in all other respects. + + You may extract a single document from such a collection, and + distribute it individually under this License, provided you insert + a copy of this License into the extracted document, and follow this + License in all other respects regarding verbatim copying of that + document. + + 7. AGGREGATION WITH INDEPENDENT WORKS + + A compilation of the Document or its derivatives with other + separate and independent documents or works, in or on a volume of a + storage or distribution medium, is called an "aggregate" if the + copyright resulting from the compilation is not used to limit the + legal rights of the compilation's users beyond what the individual + works permit. When the Document is included in an aggregate, this + License does not apply to the other works in the aggregate which + are not themselves derivative works of the Document. + + If the Cover Text requirement of section 3 is applicable to these + copies of the Document, then if the Document is less than one half + of the entire aggregate, the Document's Cover Texts may be placed + on covers that bracket the Document within the aggregate, or the + electronic equivalent of covers if the Document is in electronic + form. Otherwise they must appear on printed covers that bracket + the whole aggregate. + + 8. TRANSLATION + + Translation is considered a kind of modification, so you may + distribute translations of the Document under the terms of section + 4. Replacing Invariant Sections with translations requires special + permission from their copyright holders, but you may include + translations of some or all Invariant Sections in addition to the + original versions of these Invariant Sections. You may include a + translation of this License, and all the license notices in the + Document, and any Warranty Disclaimers, provided that you also + include the original English version of this License and the + original versions of those notices and disclaimers. In case of a + disagreement between the translation and the original version of + this License or a notice or disclaimer, the original version will + prevail. + + If a section in the Document is Entitled "Acknowledgements", + "Dedications", or "History", the requirement (section 4) to + Preserve its Title (section 1) will typically require changing the + actual title. + + 9. TERMINATION + + You may not copy, modify, sublicense, or distribute the Document + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense, or distribute it is void, + and will automatically terminate your rights under this License. + + However, if you cease all violation of this License, then your + license from a particular copyright holder is reinstated (a) + provisionally, unless and until the copyright holder explicitly and + finally terminates your license, and (b) permanently, if the + copyright holder fails to notify you of the violation by some + reasonable means prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is + reinstated permanently if the copyright holder notifies you of the + violation by some reasonable means, this is the first time you have + received notice of violation of this License (for any work) from + that copyright holder, and you cure the violation prior to 30 days + after your receipt of the notice. + + Termination of your rights under this section does not terminate + the licenses of parties who have received copies or rights from you + under this License. If your rights have been terminated and not + permanently reinstated, receipt of a copy of some or all of the + same material does not give you any rights to use it. + + 10. FUTURE REVISIONS OF THIS LICENSE + + The Free Software Foundation may publish new, revised versions of + the GNU Free Documentation License from time to time. Such new + versions will be similar in spirit to the present version, but may + differ in detail to address new problems or concerns. See + . + + Each version of the License is given a distinguishing version + number. If the Document specifies that a particular numbered + version of this License "or any later version" applies to it, you + have the option of following the terms and conditions either of + that specified version or of any later version that has been + published (not as a draft) by the Free Software Foundation. If the + Document does not specify a version number of this License, you may + choose any version ever published (not as a draft) by the Free + Software Foundation. If the Document specifies that a proxy can + decide which future versions of this License can be used, that + proxy's public statement of acceptance of a version permanently + authorizes you to choose that version for the Document. + + 11. RELICENSING + + "Massive Multiauthor Collaboration Site" (or "MMC Site") means any + World Wide Web server that publishes copyrightable works and also + provides prominent facilities for anybody to edit those works. A + public wiki that anybody can edit is an example of such a server. + A "Massive Multiauthor Collaboration" (or "MMC") contained in the + site means any set of copyrightable works thus published on the MMC + site. + + "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 + license published by Creative Commons Corporation, a not-for-profit + corporation with a principal place of business in San Francisco, + California, as well as future copyleft versions of that license + published by that same organization. + + "Incorporate" means to publish or republish a Document, in whole or + in part, as part of another Document. + + An MMC is "eligible for relicensing" if it is licensed under this + License, and if all works that were first published under this + License somewhere other than this MMC, and subsequently + incorporated in whole or in part into the MMC, (1) had no cover + texts or invariant sections, and (2) were thus incorporated prior + to November 1, 2008. + + The operator of an MMC Site may republish an MMC contained in the + site under CC-BY-SA on the same site at any time before August 1, + 2009, provided the MMC is eligible for relicensing. + +ADDENDUM: How to use this License for your documents +==================================================== + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and license +notices just after the title page: + + Copyright (C) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. A copy of the license is included in the section entitled ``GNU + Free Documentation License''. + + If you have Invariant Sections, Front-Cover Texts and Back-Cover +Texts, replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with + the Front-Cover Texts being LIST, and with the Back-Cover Texts + being LIST. + + If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + + If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of free +software license, such as the GNU General Public License, to permit +their use in free software. + + +File: libmicrohttpd.info, Node: Concept Index, Next: Function and Data Index, Prev: GNU-FDL, Up: Top + +Concept Index +************* + +[index] +* Menu: + +* ARM: microhttpd-intro. (line 285) +* bind, restricting bind: microhttpd-const. (line 330) +* bind, restricting bind <1>: microhttpd-const. (line 565) +* cipher: microhttpd-const. (line 403) +* clock: microhttpd-const. (line 105) +* compilation: microhttpd-intro. (line 123) +* connection, limiting number of connections: microhttpd-const. + (line 209) +* connection, limiting number of connections <1>: microhttpd-info daemon. + (line 60) +* cookie: microhttpd-const. (line 597) +* cortex m3: microhttpd-intro. (line 285) +* date: microhttpd-const. (line 105) +* debugging: microhttpd-const. (line 31) +* debugging <1>: microhttpd-const. (line 341) +* deprecated: microhttpd-const. (line 61) +* DH: microhttpd-const. (line 557) +* digest auth: microhttpd-const. (line 442) +* digest auth <1>: microhttpd-const. (line 453) +* eCos, GNU General Public License with eCos Extension: eCos License. + (line 6) +* embedded systems: microhttpd-intro. (line 123) +* embedded systems <1>: microhttpd-intro. (line 285) +* embedded systems <2>: microhttpd-const. (line 105) +* embedded systems <3>: microhttpd-const. (line 112) +* embedded systems <4>: microhttpd-const. (line 541) +* epoll: microhttpd-intro. (line 67) +* epoll <1>: microhttpd-const. (line 77) +* epoll <2>: microhttpd-info daemon. + (line 49) +* escaping: microhttpd-const. (line 524) +* FD_SETSIZE: microhttpd-const. (line 70) +* FD_SETSIZE <1>: microhttpd-const. (line 77) +* foreign-function interface: microhttpd-const. (line 502) +* HTTP2: microhttpd-response upgrade. + (line 6) +* IAR: microhttpd-intro. (line 285) +* internationalization: microhttpd-const. (line 524) +* IPv6: microhttpd-const. (line 45) +* IPv6 <1>: microhttpd-const. (line 55) +* license: GNU-LGPL. (line 6) +* license <1>: eCos License. (line 6) +* license <2>: GNU-GPL. (line 6) +* license <3>: GNU-FDL. (line 6) +* listen: microhttpd-const. (line 112) +* listen <1>: microhttpd-const. (line 143) +* listen <2>: microhttpd-const. (line 547) +* listen <3>: microhttpd-info daemon. + (line 43) +* logging: microhttpd-const. (line 341) +* logging <1>: microhttpd-const. (line 483) +* long long: microhttpd-intro. (line 285) +* memory: microhttpd-const. (line 201) +* memory, limiting memory utilization: microhttpd-const. (line 193) +* MHD_LONG_LONG: microhttpd-intro. (line 285) +* microhttpd.h: microhttpd-intro. (line 224) +* OCSP: microhttpd-const. (line 426) +* options: microhttpd-const. (line 502) +* performance: microhttpd-intro. (line 91) +* performance <1>: microhttpd-const. (line 90) +* performance <2>: microhttpd-const. (line 494) +* performance <3>: microhttpd-info conn. + (line 114) +* poll: microhttpd-intro. (line 67) +* poll <1>: microhttpd-const. (line 70) +* poll <2>: microhttpd-init. (line 74) +* portability: microhttpd-intro. (line 123) +* portability <1>: microhttpd-intro. (line 224) +* POST method: microhttpd-const. (line 601) +* POST method <1>: microhttpd-struct. (line 22) +* POST method <2>: microhttpd-cb. (line 48) +* POST method <3>: microhttpd-post. (line 6) +* POST method <4>: microhttpd-post api. + (line 6) +* proxy: microhttpd-const. (line 112) +* PSK: microhttpd-const. (line 436) +* pthread: microhttpd-const. (line 541) +* PUT method: microhttpd-cb. (line 48) +* query string: microhttpd-const. (line 341) +* quiesce: microhttpd-const. (line 119) +* quiesce <1>: microhttpd-init. (line 51) +* random: microhttpd-const. (line 442) +* replay attack: microhttpd-const. (line 453) +* reusing listening address: microhttpd-const. (line 565) +* RFC2817: microhttpd-response upgrade. + (line 6) +* select: microhttpd-intro. (line 67) +* select <1>: microhttpd-const. (line 70) +* select <2>: microhttpd-const. (line 77) +* select <3>: microhttpd-init. (line 74) +* select <4>: microhttpd-init. (line 89) +* signals: microhttpd-intro. (line 246) +* SNI: microhttpd-const. (line 411) +* SNI <1>: microhttpd-const. (line 426) +* SSL: microhttpd-const. (line 34) +* SSL <1>: microhttpd-const. (line 364) +* SSL <2>: microhttpd-const. (line 370) +* SSL <3>: microhttpd-const. (line 380) +* SSL <4>: microhttpd-const. (line 386) +* SSL <5>: microhttpd-const. (line 398) +* SSL <6>: microhttpd-const. (line 403) +* SSL <7>: microhttpd-const. (line 411) +* SSL <8>: microhttpd-const. (line 426) +* SSL <9>: microhttpd-const. (line 436) +* SSL <10>: microhttpd-const. (line 557) +* stack: microhttpd-const. (line 541) +* systemd: microhttpd-const. (line 476) +* testing: microhttpd-const. (line 319) +* thread: microhttpd-const. (line 541) +* timeout: microhttpd-const. (line 247) +* timeout <1>: microhttpd-inspect. (line 39) +* timeout <2>: microhttpd-option conn. + (line 6) +* TLS: microhttpd-const. (line 34) +* TLS <1>: microhttpd-const. (line 364) +* TLS <2>: microhttpd-const. (line 370) +* TLS <3>: microhttpd-const. (line 380) +* TLS <4>: microhttpd-const. (line 386) +* TLS <5>: microhttpd-const. (line 398) +* TLS <6>: microhttpd-const. (line 403) +* TLS <7>: microhttpd-const. (line 411) +* TLS <8>: microhttpd-const. (line 426) +* TLS <9>: microhttpd-const. (line 436) +* TLS <10>: microhttpd-const. (line 557) +* upgrade: microhttpd-const. (line 148) +* Upgrade: microhttpd-response upgrade. + (line 6) +* websocket: microhttpd-const. (line 708) +* websocket <1>: microhttpd-const. (line 773) +* websocket <2>: microhttpd-const. (line 805) +* websocket <3>: microhttpd-const. (line 999) +* websocket <4>: microhttpd-const. (line 1064) +* websocket <5>: microhttpd-const. (line 1122) +* websocket <6>: microhttpd-struct. (line 31) +* websocket <7>: microhttpd-cb. (line 243) +* websocket <8>: microhttpd-cb. (line 259) +* websocket <9>: microhttpd-cb. (line 278) +* websocket <10>: microhttpd-cb. (line 292) +* websocket <11>: microhttpd-websocket handshake. + (line 8) +* websocket <12>: microhttpd-websocket handshake. + (line 24) +* websocket <13>: microhttpd-websocket handshake. + (line 42) +* websocket <14>: microhttpd-websocket handshake. + (line 60) +* websocket <15>: microhttpd-websocket handshake. + (line 80) +* websocket <16>: microhttpd-websocket stream. + (line 9) +* websocket <17>: microhttpd-websocket stream. + (line 36) +* websocket <18>: microhttpd-websocket stream. + (line 91) +* websocket <19>: microhttpd-websocket stream. + (line 101) +* websocket <20>: microhttpd-websocket stream. + (line 113) +* websocket <21>: microhttpd-websocket decode. + (line 10) +* websocket <22>: microhttpd-websocket decode. + (line 70) +* websocket <23>: microhttpd-websocket encode. + (line 10) +* websocket <24>: microhttpd-websocket encode. + (line 70) +* websocket <25>: microhttpd-websocket encode. + (line 109) +* websocket <26>: microhttpd-websocket encode. + (line 143) +* websocket <27>: microhttpd-websocket encode. + (line 178) +* websocket <28>: microhttpd-websocket memory. + (line 8) +* websocket <29>: microhttpd-websocket memory. + (line 23) +* websocket <30>: microhttpd-websocket memory. + (line 42) +* WebSockets: microhttpd-response upgrade. + (line 6) + + +File: libmicrohttpd.info, Node: Function and Data Index, Next: Type Index, Prev: Concept Index, Up: Top + +Function and Data Index +*********************** + +[index] +* Menu: + +* *MHD_ContentReaderCallback: microhttpd-cb. (line 150) +* *MHD_ContentReaderFreeCallback: microhttpd-cb. (line 197) +* *MHD_RequestCompletedCallback: microhttpd-cb. (line 96) +* *MHD_UpgradeHandler: microhttpd-response upgrade. + (line 37) +* *MHD_WebSocketFreeCallback: microhttpd-cb. (line 277) +* *MHD_WebSocketMallocCallback: microhttpd-cb. (line 241) +* *MHD_WebSocketRandomNumberGenerator: microhttpd-cb. (line 290) +* *MHD_WebSocketReallocCallback: microhttpd-cb. (line 257) +* MHD_add_connection: microhttpd-init. (line 115) +* MHD_basic_auth_get_username_password3: microhttpd-dauth basic. + (line 10) +* MHD_create_post_processor: microhttpd-post api. (line 6) +* MHD_create_response_from_buffer: microhttpd-response create. + (line 104) +* MHD_create_response_from_buffer_with_free_callback: microhttpd-response create. + (line 125) +* MHD_create_response_from_callback: microhttpd-response create. + (line 6) +* MHD_create_response_from_data: microhttpd-response create. + (line 143) +* MHD_create_response_from_fd: microhttpd-response create. + (line 32) +* MHD_create_response_from_fd_at_offset: microhttpd-response create. + (line 62) +* MHD_create_response_from_iovec: microhttpd-response create. + (line 179) +* MHD_create_response_from_pipe: microhttpd-response create. + (line 50) +* MHD_destroy_response: microhttpd-response enqueue. + (line 29) +* MHD_digest_auth_check: microhttpd-dauth digest. + (line 111) +* MHD_digest_auth_check_digest: microhttpd-dauth digest. + (line 185) +* MHD_digest_auth_check_digest2: microhttpd-dauth digest. + (line 160) +* MHD_digest_auth_check2: microhttpd-dauth digest. + (line 86) +* MHD_digest_auth_get_username: microhttpd-dauth digest. + (line 55) +* MHD_DigestAuthResult: microhttpd-dauth digest. + (line 62) +* MHD_DigestAuthResult <1>: microhttpd-dauth digest. + (line 134) +* MHD_free: microhttpd-dauth basic. + (line 6) +* MHD_get_connection_info: microhttpd-info conn. + (line 6) +* MHD_get_connection_values: microhttpd-requests. (line 6) +* MHD_get_daemon_info: microhttpd-info daemon. + (line 6) +* MHD_get_response_header: microhttpd-response inspect. + (line 18) +* MHD_get_response_headers: microhttpd-response inspect. + (line 6) +* MHD_http_unescape: microhttpd-util unescape. + (line 6) +* MHD_is_feature_supported: microhttpd-util feature. + (line 77) +* MHD_lookup_connection_value: microhttpd-requests. (line 58) +* MHD_lookup_connection_value_n: microhttpd-requests. (line 67) +* MHD_queue_basic_auth_fail_response3: microhttpd-dauth basic. + (line 19) +* MHD_quiesce_daemon: microhttpd-init. (line 50) +* MHD_Result: microhttpd-cb. (line 6) +* MHD_Result <1>: microhttpd-cb. (line 19) +* MHD_Result <2>: microhttpd-cb. (line 116) +* MHD_Result <3>: microhttpd-cb. (line 202) +* MHD_Result <4>: microhttpd-init. (line 70) +* MHD_Result <5>: microhttpd-init. (line 86) +* MHD_Result <6>: microhttpd-inspect. (line 6) +* MHD_Result <7>: microhttpd-inspect. (line 31) +* MHD_Result <8>: microhttpd-inspect. (line 37) +* MHD_Result <9>: microhttpd-requests. (line 35) +* MHD_Result <10>: microhttpd-response enqueue. + (line 6) +* MHD_Result <11>: microhttpd-response headers. + (line 6) +* MHD_Result <12>: microhttpd-response headers. + (line 30) +* MHD_Result <13>: microhttpd-response headers. + (line 47) +* MHD_Result <14>: microhttpd-response options. + (line 6) +* MHD_Result <15>: microhttpd-response upgrade. + (line 23) +* MHD_Result <16>: microhttpd-response upgrade. + (line 91) +* MHD_Result <17>: microhttpd-flow. (line 20) +* MHD_Result <18>: microhttpd-flow. (line 56) +* MHD_Result <19>: microhttpd-dauth digest. + (line 208) +* MHD_Result <20>: microhttpd-dauth digest. + (line 235) +* MHD_Result <21>: microhttpd-post api. (line 33) +* MHD_Result <22>: microhttpd-post api. (line 52) +* MHD_set_connection_option: microhttpd-option conn. + (line 6) +* MHD_set_panic_func: microhttpd-init. (line 6) +* MHD_start_daemon: microhttpd-init. (line 18) +* MHD_stop_daemon: microhttpd-init. (line 67) +* MHD_websocket_check_connection_header: microhttpd-websocket handshake. + (line 21) +* MHD_websocket_check_http_version: microhttpd-websocket handshake. + (line 6) +* MHD_websocket_check_upgrade_header: microhttpd-websocket handshake. + (line 39) +* MHD_websocket_check_version_header: microhttpd-websocket handshake. + (line 57) +* MHD_websocket_create_accept_header: microhttpd-websocket handshake. + (line 77) +* MHD_websocket_decode: microhttpd-websocket decode. + (line 6) +* MHD_websocket_encode_binary: microhttpd-websocket encode. + (line 66) +* MHD_websocket_encode_close: microhttpd-websocket encode. + (line 174) +* MHD_websocket_encode_ping: microhttpd-websocket encode. + (line 106) +* MHD_websocket_encode_pong: microhttpd-websocket encode. + (line 140) +* MHD_websocket_encode_text: microhttpd-websocket encode. + (line 6) +* MHD_websocket_free: microhttpd-websocket memory. + (line 40) +* MHD_websocket_malloc: microhttpd-websocket memory. + (line 6) +* MHD_websocket_realloc: microhttpd-websocket memory. + (line 21) +* MHD_websocket_split_close_reason: microhttpd-websocket decode. + (line 66) +* MHD_websocket_stream_free: microhttpd-websocket stream. + (line 89) +* MHD_websocket_stream_init: microhttpd-websocket stream. + (line 6) +* MHD_websocket_stream_init2: microhttpd-websocket stream. + (line 30) +* MHD_websocket_stream_invalidate: microhttpd-websocket stream. + (line 99) +* MHD_websocket_stream_is_valid: microhttpd-websocket stream. + (line 111) + + +File: libmicrohttpd.info, Node: Type Index, Prev: Function and Data Index, Up: Top + +Type Index +********** + +[index] +* Menu: + +* MHD_Connection: microhttpd-struct. (line 9) +* MHD_CONNECTION_OPTION: microhttpd-option conn. + (line 22) +* MHD_ConnectionInfo: microhttpd-struct. (line 24) +* MHD_ConnectionInfoType: microhttpd-info conn. + (line 25) +* MHD_Daemon: microhttpd-struct. (line 6) +* MHD_DaemonInfo: microhttpd-struct. (line 27) +* MHD_DaemonInfoType: microhttpd-info daemon. + (line 25) +* MHD_DigestAuthAlgorithm: microhttpd-dauth digest. + (line 10) +* MHD_DigestAuthResult: microhttpd-dauth digest. + (line 23) +* MHD_FEATURE: microhttpd-util feature. + (line 6) +* MHD_FLAG: microhttpd-const. (line 6) +* MHD_IoVec: microhttpd-struct. (line 18) +* MHD_OPTION: microhttpd-const. (line 184) +* MHD_OptionItem: microhttpd-const. (line 576) +* MHD_PostProcessor: microhttpd-struct. (line 21) +* MHD_RequestTerminationCode: microhttpd-const. (line 614) +* MHD_Response: microhttpd-struct. (line 15) +* MHD_ResponseFlags: microhttpd-const. (line 654) +* MHD_ResponseMemoryMode: microhttpd-const. (line 632) +* MHD_ResponseOptions: microhttpd-const. (line 699) +* MHD_UpgradeAction: microhttpd-response upgrade. + (line 103) +* MHD_ValueKind: microhttpd-const. (line 589) +* MHD_WEBSOCKET_CLOSEREASON: microhttpd-const. (line 998) +* MHD_WEBSOCKET_FLAG: microhttpd-const. (line 707) +* MHD_WEBSOCKET_FRAGMENTATION: microhttpd-const. (line 772) +* MHD_WEBSOCKET_STATUS: microhttpd-const. (line 804) +* MHD_WEBSOCKET_UTF8STEP: microhttpd-const. (line 1063) +* MHD_WEBSOCKET_VALIDITY: microhttpd-const. (line 1121) +* MHD_WebSocketStream: microhttpd-struct. (line 30) + + + +Tag Table: +Node: Top818 +Node: microhttpd-intro3153 +Ref: fig:performance8064 +Ref: tbl:supported9036 +Node: microhttpd-const17461 +Node: microhttpd-struct75242 +Node: microhttpd-cb76180 +Node: microhttpd-init89479 +Node: microhttpd-inspect95357 +Node: microhttpd-requests98134 +Node: microhttpd-responses102184 +Node: microhttpd-response enqueue103383 +Ref: microhttpd-response enqueue-Footnote-1105708 +Node: microhttpd-response create105943 +Node: microhttpd-response headers113953 +Node: microhttpd-response options116427 +Node: microhttpd-response inspect117310 +Node: microhttpd-response upgrade118531 +Node: microhttpd-flow123873 +Node: microhttpd-dauth127425 +Node: microhttpd-dauth basic128985 +Node: microhttpd-dauth digest130576 +Node: microhttpd-post144187 +Node: microhttpd-post api147171 +Node: microhttpd-info149839 +Node: microhttpd-info daemon150255 +Node: microhttpd-info conn153703 +Node: microhttpd-option conn158962 +Node: microhttpd-util160042 +Node: microhttpd-util feature160321 +Node: microhttpd-util unescape163907 +Node: microhttpd-websocket164551 +Node: microhttpd-websocket handshake165270 +Node: microhttpd-websocket stream170435 +Node: microhttpd-websocket decode175475 +Node: microhttpd-websocket encode179973 +Node: microhttpd-websocket memory189398 +Node: GNU-LGPL191223 +Node: eCos License219321 +Node: GNU-GPL220712 +Node: GNU-FDL239974 +Node: Concept Index265043 +Node: Function and Data Index278229 +Node: Type Index288554 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/vendor/libmicrohttpd/share/info/libmicrohttpd_performance_data.png b/vendor/libmicrohttpd/share/info/libmicrohttpd_performance_data.png new file mode 100644 index 0000000000000000000000000000000000000000..0e447c2409e71562de5253d642621a1a7c9e6fba GIT binary patch literal 9169 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 literal 0 HcmV?d00001 diff --git a/vendor/libmicrohttpd/share/man/man3/libmicrohttpd.3 b/vendor/libmicrohttpd/share/man/man3/libmicrohttpd.3 new file mode 100644 index 0000000..dbd3d70 --- /dev/null +++ b/vendor/libmicrohttpd/share/man/man3/libmicrohttpd.3 @@ -0,0 +1,46 @@ +.Dd June 21, 2013 +.Dt LIBMICROHTTPD 3 +.Os +.Sh NAME +.Nm libmicrohttpd +.Nd library for embedding HTTP servers +.Sh LIBRARY +.ds doc-str-Lb-libmicrohttpd library for embedding HTTP servers (libmicrohttpd) +.Lb libmicrohttpd +.Sh SYNOPSIS +.In microhttpd.h +.Sh DESCRIPTION +GNU libmicrohttpd (short MHD) allows applications to easily integrate the functionality of a simple HTTP server. MHD is a GNU package. +.sp +The details of the API are described in comments in the header file, a detailed reference documentation in Texinfo, a tutorial, and in brief on the MHD webpage. +.Sh LEGAL NOTICE +libmicrohttpd is released under both the LGPL Version 2.1 or higher and the GNU GPL with eCos extension. For details on both licenses please read the respective appendix in the Texinfo manual. +.Sh FILES +.Bl -tag -width /etc/ttys -compact +.It Pa microhttpd.h +libmicrohttpd include file +.It Pa libmicrohttpd.so +libmicrohttpd library +.El +.Sh SEE ALSO +.Xr curl 1 , +.Xr libcurl 3 , +info libmicrohttpd +.Sh AUTHORS +GNU +.Nm +was originally designed by +.An -nosplit +.An Christian Grothoff Aq Mt christian@grothoff.org +and +.An Chris GauthierDickey Aq Mt chrisg@cs.du.edu Ns . +The original implementation was done by +.An Daniel Pittman Aq Mt depittman@gmail.com +and Christian Grothoff. +SSL/TLS support was added by Sagie Amir using code from GnuTLS. See the AUTHORS file in the distribution for a more detailed list of contributors. +.Sh AVAILABILITY +You can obtain the latest version from +.Lk https://www.gnu.org/software/libmicrohttpd/ Ns . +.Sh BUGS +Report bugs by using +.Lk https://bugs.gnunet.org/set_project.php?project_id=10 "Mantis" Ns .

Ac3F;Tz%?GhWCz!s*I;^8GHP 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