28#define MHD_NO_DEPRECATION 1
31#ifdef HAVE_SYS_IOCTL_H
34#if defined(_WIN32) && ! defined(__CYGWIN__)
51#if defined(MHD_W32_MUTEX_)
52#ifndef WIN32_LEAN_AND_MEAN
53#define WIN32_LEAN_AND_MEAN 1
66#ifndef MHD_FILE_READ_BLOCK_SIZE
68#define MHD_FILE_READ_BLOCK_SIZE 16384
70#define MHD_FILE_READ_BLOCK_SIZE 4096
77#define _MHD_insert_header_first(presponse, phdr) do { \
78 mhd_assert (NULL == phdr->next); \
79 mhd_assert (NULL == phdr->prev); \
80 if (NULL == presponse->first_header) \
82 mhd_assert (NULL == presponse->last_header); \
83 presponse->first_header = phdr; \
84 presponse->last_header = phdr; \
88 mhd_assert (NULL != presponse->last_header); \
89 presponse->first_header->prev = phdr; \
90 phdr->next = presponse->first_header; \
91 presponse->first_header = phdr; \
98#define _MHD_insert_header_last(presponse, phdr) do { \
99 mhd_assert (NULL == phdr->next); \
100 mhd_assert (NULL == phdr->prev); \
101 if (NULL == presponse->last_header) \
103 mhd_assert (NULL == presponse->first_header); \
104 presponse->last_header = phdr; \
105 presponse->first_header = phdr; \
109 mhd_assert (NULL != presponse->first_header); \
110 presponse->last_header->next = phdr; \
111 phdr->prev = presponse->last_header; \
112 presponse->last_header = phdr; \
120#define _MHD_remove_header(presponse, phdr) do { \
121 mhd_assert (NULL != presponse->first_header); \
122 mhd_assert (NULL != presponse->last_header); \
123 if (NULL == phdr->prev) \
125 mhd_assert (phdr == presponse->first_header); \
126 presponse->first_header = phdr->next; \
130 mhd_assert (phdr != presponse->first_header); \
131 mhd_assert (phdr == phdr->prev->next); \
132 phdr->prev->next = phdr->next; \
134 if (NULL == phdr->next) \
136 mhd_assert (phdr == presponse->last_header); \
137 presponse->last_header = phdr->prev; \
141 mhd_assert (phdr != presponse->last_header); \
142 mhd_assert (phdr == phdr->next->prev); \
143 phdr->next->prev = phdr->prev; \
183 hdr->
value = content;
214 char *header_malloced;
215 char *value_malloced;
219 header_malloced = malloc (header_len + 1);
220 if (
NULL == header_malloced)
223 memcpy (header_malloced,
header, header_len);
224 header_malloced[header_len] = 0;
226 value_malloced = malloc (content_len + 1);
227 if (
NULL != value_malloced)
229 memcpy (value_malloced, content, content_len);
230 value_malloced[content_len] = 0;
233 header_malloced, header_len,
234 value_malloced, content_len))
237 free (value_malloced);
239 free (header_malloced);
263 if (
NULL == response)
267 if (0 == content_len)
269 if (
NULL != memchr (
header,
'\t', header_len))
273 if (
NULL != memchr (
header,
'\r', header_len))
275 if (
NULL != memchr (
header,
'\n', header_len))
277 if (
NULL != memchr (content,
'\r', content_len))
279 if (
NULL != memchr (content,
'\n', content_len))
283 content, content_len);
309 header_len = strlen (
header);
310 content_len = strlen (content);
334 static const size_t key_len =
337 size_t old_value_len;
342 bool value_has_close;
343 bool already_has_close;
357 mhd_assert (already_has_close == (0 == memcmp (hdr->
value,
"close", 5)));
362 already_has_close =
false;
373 value_len = strlen (
value);
377 norm_len = value_len + value_len / 2 + 1;
380 buf_size = old_value_len + (size_t) norm_len;
382 buf = malloc (buf_size);
387 ssize_t norm_len_s = (ssize_t) norm_len;
402 norm_len = (size_t) norm_len_s;
404#ifdef UPGRADE_SUPPORT
405 if ( (
NULL != response->upgrade_handler) && value_has_close)
417 if (! value_has_close)
422 if (already_has_close)
429 if (value_has_close && ! already_has_close)
432 mhd_assert (buf_size >= old_value_len + norm_len \
436 buf + old_value_len, norm_len + 1);
441 if (0 != old_value_len)
448 memcpy (buf + pos, hdr->
value,
461 mhd_assert ((value_has_close && ! already_has_close) ? \
463 (old_value_len == pos));
476 new_hdr->
header = malloc (key_len + 1);
479 memcpy (new_hdr->
header, key, key_len + 1);
481 new_hdr->
value = buf;
502 if (value_has_close && ! already_has_close)
553 if (0 != memcmp (hdr->
value,
561 if (0 != memcmp (hdr->
value,
"close, ",
757 header_len = strlen (
header);
765 content_len = strlen (content);
774 (0 == memcmp (content,
840 if ((
NULL != iterator) &&
841 (
MHD_NO == iterator (iterator_cls,
869 key_size = strlen (key);
943 if ( (
NULL == key) ||
1000 if ((
NULL ==
crc) || (0 == block_size))
1006 response->
data = (
void *) &response[1];
1008#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1063 va_start (ap,
flags);
1097#if ! defined(_WIN32) || defined(__CYGWIN__)
1100 const HANDLE fh = (HANDLE) (uintptr_t) _get_osfhandle (response->
fd);
1102 const int64_t offset64 = (int64_t) (pos + response->
fd_off);
1107#if ! defined(_WIN32) || defined(__CYGWIN__)
1111#if defined(HAVE_PREAD64)
1112 n = pread64 (response->
fd, buf, max, offset64);
1113#elif defined(HAVE_PREAD)
1114 if ( (
sizeof(off_t) <
sizeof (uint64_t)) &&
1118 n = pread (response->
fd, buf, max, (off_t) offset64);
1120#if defined(HAVE_LSEEK64)
1121 if (lseek64 (response->
fd,
1123 SEEK_SET) != offset64)
1126 if ( (
sizeof(off_t) <
sizeof (uint64_t)) &&
1130 if (lseek (response->
fd,
1132 SEEK_SET) != (off_t) offset64)
1135 n = read (response->
fd,
1146 if (INVALID_HANDLE_VALUE == fh)
1150 OVERLAPPED f_ol = {0, 0, {{0, 0}}, 0};
1151 ULARGE_INTEGER pos_uli;
1155 pos_uli.QuadPart = (uint64_t) offset64;
1156 f_ol.Offset = pos_uli.LowPart;
1157 f_ol.OffsetHigh = pos_uli.HighPart;
1158 if (! ReadFile (fh, (
void *) buf, toRead, &resRead, &f_ol))
1162 return (ssize_t) resRead;
1192 n = read (response->
fd,
1198 n = read (response->
fd,
1200 (
unsigned int) max);
1222 (void) close (response->
fd);
1227#undef MHD_create_response_from_fd_at_offset
1295#if ! defined(HAVE___LSEEKI64) && ! defined(HAVE_LSEEK64)
1296 if ( (
sizeof(uint64_t) >
sizeof(off_t)) &&
1302 if ( ((int64_t) size < 0) ||
1303 ((int64_t)
offset < 0) ||
1304 ((int64_t) (size +
offset) < 0) )
1312 if (
NULL == response)
1349 if (
NULL == response)
1559 mhd_copy = malloc (size);
1560 if (
NULL == mhd_copy)
1562 memcpy (mhd_copy, buffer, size);
1640 if ((
NULL == buffer) && (size > 0))
1642#if SIZEOF_SIZE_T >= SIZEOF_UINT64_T
1649#if defined(MHD_USE_THREADS)
1688 unsigned int iovcnt,
1696 const void *last_valid_buffer =
NULL;
1698 if ((
NULL == iov) && (0 < iovcnt))
1702 if (
NULL == response)
1710 for (i = 0; i < iovcnt; ++i)
1712 if (0 == iov[i].iov_len)
1714 if (
NULL == iov[i].iov_base)
1726 last_valid_buffer = iov[i].
iov_base;
1728#if defined(MHD_POSIX_SOCKETS) || ! defined(_WIN64)
1734 i_add = (int64_t) (iov[i].iov_len / ULONG_MAX);
1735 if (0 != iov[i].iov_len % ULONG_MAX)
1742 i_cp += (int) i_add;
1757 response->
crfc = free_cb;
1766 response->
data = last_valid_buffer;
1774 int num_copy_elements = i_cp;
1776 iov_copy =
MHD_calloc_ ((
size_t) num_copy_elements, \
1778 if (
NULL == iov_copy)
1785 for (i = 0; i < iovcnt; ++i)
1787 size_t element_size = iov[i].
iov_len;
1788 const uint8_t *buf = (
const uint8_t *) iov[i].iov_base;
1790 if (0 == element_size)
1792#if defined(MHD_WINSOCK_SOCKETS) && defined(_WIN64)
1796 iov_copy[i_cp].
iov_len = ULONG_MAX;
1798 element_size -= ULONG_MAX;
1853#ifdef UPGRADE_SUPPORT
1876 connection = urh->connection;
1879 if (
NULL == connection)
1881 daemon = connection->
daemon;
1888 if (urh->was_closed)
1907 MHD_upgraded_connection_mark_app_closed_ (connection);
1941#if defined(HTTPS_SUPPORT) || defined(_DEBUG) || defined(HAVE_MESSAGES)
1944 struct MHD_UpgradeResponseHandle *urh;
1947#ifdef MHD_USE_THREADS
1965 _ (
"Cannot execute \"upgrade\" as the socket is in " \
1966 "the blocking mode.\n"));
1970 urh =
MHD_calloc_ (1,
sizeof (
struct MHD_UpgradeResponseHandle));
1973 urh->connection = connection;
1982#if defined(MHD_socket_nosignal_) || ! defined(MHD_socket_pair_nblk_)
1987#ifdef MHD_socket_pair_nblk_
1988 if (! MHD_socket_pair_nblk_ (sv))
1994 if (! MHD_socket_pair_ (sv))
2001 if ( (! res1) || (! res2) )
2005 _ (
"Failed to make loopback sockets non-blocking.\n"));
2017#ifdef MHD_socket_nosignal_
2018 res1 = MHD_socket_nosignal_ (sv[0]);
2019 res2 = MHD_socket_nosignal_ (sv[1]);
2020 if ( (! res1) || (! res2) )
2024 _ (
"Failed to set SO_NOSIGPIPE on loopback sockets.\n"));
2043 _ (
"Socketpair descriptor is not less than FD_SETSIZE: " \
2053 urh->app.socket = sv[0];
2056 urh->mhd.socket = sv[1];
2065 struct epoll_event event;
2069 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2070 event.data.ptr = &urh->app;
2071 if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
2078 _ (
"Call to epoll_ctl failed: %s\n"),
2088 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2089 event.data.ptr = &urh->mhd;
2090 if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
2095 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI;
2096 event.data.ptr = &urh->app;
2097 if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
2101 MHD_PANIC (
_ (
"Error cleaning up while handling epoll error.\n"));
2104 _ (
"Call to epoll_ctl failed: %s\n"),
2113 daemon->eready_urh_tail,
2115 urh->in_eready_list =
true;
2135 urh->clean_ready =
true;
2138 urh->clean_ready =
true;
2140 connection->urh = urh;
2147 response->upgrade_handler (response->upgrade_handler_cls,
2154 connection->
socket_fd : urh->app.socket,
2163 struct MemoryPool *
const pool = connection->
pool;
2185 if (avail < RESERVE_EBUF_SIZE)
2189 avail = RESERVE_EBUF_SIZE;
2193 _ (
"Memory shortage in connection's memory pool. " \
2194 "The \"upgraded\" communication will be inefficient.\n"));
2208 urh->in_buffer_size = avail / 2;
2209 urh->out_buffer_size = avail - urh->in_buffer_size;
2210 urh->in_buffer = buf;
2211 urh->out_buffer = buf + urh->in_buffer_size;
2249 void *upgrade_handler_cls)
2253 if (
NULL == upgrade_handler)
2256 if (
NULL == response)
2258#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2265 response->upgrade_handler = upgrade_handler;
2266 response->upgrade_handler_cls = upgrade_handler_cls;
2298 if (
NULL == response)
2300#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2305#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2310#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2342#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2346#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
Methods for managing connections.
void internal_suspend_connection_(struct MHD_Connection *connection)
enum MHD_Result(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
_MHD_EXTERN int MHD_get_response_headers(struct MHD_Response *response, MHD_KeyValueIterator iterator, void *iterator_cls)
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer_with_free_callback(size_t size, void *buffer, MHD_ContentReaderFreeCallback crfc)
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_iovec(const struct MHD_IoVec *iov, unsigned int iovcnt, MHD_ContentReaderFreeCallback free_cb, void *cls)
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_data(size_t size, void *data, int must_free, int must_copy)
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer_copy(size_t size, const void *buffer)
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
_MHD_EXTERN enum MHD_Result MHD_del_response_header(struct MHD_Response *response, const char *header, const char *content)
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_pipe(int fd)
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
struct MHD_HTTP_Res_Header * MHD_get_response_element_n_(struct MHD_Response *response, enum MHD_ValueKind kind, const char *key, size_t key_len)
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd(size_t size, int fd)
_MHD_EXTERN struct MHD_Response * MHD_create_response_empty(enum MHD_ResponseFlags flags)
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer_static(size_t size, const void *buffer)
void(* MHD_ContentReaderFreeCallback)(void *cls)
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd_at_offset64(uint64_t size, int fd, uint64_t offset)
_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)
_MHD_EXTERN enum MHD_Result MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
_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)
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd64(uint64_t size, int fd)
_MHD_EXTERN enum MHD_Result MHD_add_response_footer(struct MHD_Response *response, const char *footer, const char *content)
MHD internal shared structures.
@ MHD_EPOLL_STATE_UNREADY
#define DLL_insert(head, tail, element)
#define MHD_D_DOES_SCKT_FIT_FDSET_(sckt, d)
#define MHD_D_IS_USING_SELECT_(d)
#define EDLL_insert(head, tail, element)
struct MHD_IoVec MHD_iovec_
@ MHD_RAF_HAS_CONTENT_LENGTH
@ MHD_RAF_HAS_CONNECTION_CLOSE
@ MHD_RAF_HAS_TRANS_ENC_CHUNKED
@ MHD_RAF_HAS_CONNECTION_HDR
#define _MHD_DROP_CONST(ptr)
#define MHD_D_GET_FD_SETSIZE_(d)
#define MHD_D_IS_USING_THREAD_PER_CONN_(d)
#define MHD_D_IS_USING_THREADS_(d)
#define MHD_D_IS_USING_EPOLL_(d)
#define MHD_IOV_ELMN_MAX_SIZE
void MHD_pool_deallocate(struct MemoryPool *pool, void *block, size_t block_size)
size_t MHD_pool_get_free(struct MemoryPool *pool)
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, bool from_end)
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...
#define mhd_assert(ignore)
void * MHD_calloc_(size_t nelem, size_t elsize)
Header for platform missing functions.
Header for platform-independent inter-thread communication.
limits values definitions
#define MHD_mutex_unlock_chk_(ignore)
#define MHD_mutex_init_(ignore)
#define MHD_mutex_lock_chk_(ignore)
#define MHD_mutex_destroy_chk_(ignore)
additional automatic macros for MHD_config.h
bool MHD_connection_set_cork_state_(struct MHD_Connection *connection, bool cork_state)
bool MHD_connection_set_nodelay_state_(struct MHD_Connection *connection, bool nodelay_state)
Declarations of send() wrappers.
int MHD_socket_nonblocking_(MHD_socket sock)
size_t MHD_SCKT_SEND_SIZE_
#define MHD_socket_last_strerr_()
#define MHD_socket_close_chk_(fd)
int MHD_str_equal_caseless_(const char *str1, const char *str2)
bool MHD_str_remove_tokens_caseless_(char *str, size_t *str_len, const char *const tokens, const size_t tokens_len)
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
bool MHD_str_remove_token_caseless_(const char *str, size_t str_len, const char *const token, const size_t token_len, char *buf, ssize_t *buf_size)
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
Header for string manipulating helpers.
#define MHD_STATICSTR_LEN_(macro)
#define MHD_thread_handle_ID_is_current_thread_(hndl_id)
#define MHD_CONTENT_READER_END_OF_STREAM
#define MHD_create_response_from_fd_at_offset(size, fd, offset)
_MHD_EXTERN struct MHD_Response * MHD_create_response_for_upgrade(MHD_UpgradeHandler upgrade_handler, void *upgrade_handler_cls)
#define MHD_INVALID_SOCKET
ssize_t(* MHD_ContentReaderCallback)(void *cls, uint64_t pos, char *buf, size_t max)
#define MHD_CONTENT_READER_END_WITH_ERROR
@ MHD_UPGRADE_ACTION_CORK_ON
@ MHD_UPGRADE_ACTION_CLOSE
@ MHD_UPGRADE_ACTION_CORK_OFF
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)
@ MHD_RF_HEAD_ONLY_RESPONSE
@ MHD_RF_INSANITY_HEADER_CONTENT_LENGTH
_MHD_EXTERN enum MHD_Result MHD_upgrade_action(struct MHD_UpgradeResponseHandle *urh, enum MHD_UpgradeAction action,...)
static void free_callback(void *cls)
#define MHD_FILE_READ_BLOCK_SIZE
bool MHD_check_response_header_token_ci(const struct MHD_Response *response, const char *key, size_t key_len, const char *token, size_t token_len)
bool MHD_add_response_entry_no_check_(struct MHD_Response *response, enum MHD_ValueKind kind, const char *header, size_t header_len, const char *content, size_t content_len)
#define _MHD_insert_header_last(presponse, phdr)
static bool add_response_entry_n(struct MHD_Response *response, enum MHD_ValueKind kind, const char *header, size_t header_len, const char *content, size_t content_len)
#define _MHD_remove_header(presponse, phdr)
static enum MHD_Result add_response_header_connection(struct MHD_Response *response, const char *value)
#define _MHD_insert_header_first(presponse, phdr)
static enum MHD_Result add_response_entry(struct MHD_Response *response, enum MHD_ValueKind kind, const char *header, const char *content)
static ssize_t file_reader(void *cls, uint64_t pos, char *buf, size_t max)
static enum MHD_Result del_response_header_connection(struct MHD_Response *response, const char *value)
bool MHD_add_response_entry_no_alloc_(struct MHD_Response *response, enum MHD_ValueKind kind, char *header, size_t header_len, char *content, size_t content_len)
static ssize_t pipe_reader(void *cls, uint64_t pos, char *buf, size_t max)
void MHD_increment_response_rc(struct MHD_Response *response)
_MHD_EXTERN enum MHD_Result MHD_set_response_options(struct MHD_Response *response, enum MHD_ResponseFlags flags,...)
Methods for managing response objects.
enum MHD_Result MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
size_t write_buffer_send_offset
size_t write_buffer_append_offset
size_t read_buffer_offset
enum MHD_CONNECTION_STATE state
struct MHD_Daemon * daemon
MHD_ContentReaderFreeCallback crfc
MHD_ContentReaderCallback crc
enum MHD_ResponseAutoFlags flags_auto
enum MHD_ResponseFlags flags
unsigned int reference_count
struct MHD_HTTP_Res_Header * first_header