00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00027 #ifndef INTERNAL_H
00028 #define INTERNAL_H
00029
00030 #include "platform.h"
00031 #include "microhttpd.h"
00032 #if HTTPS_SUPPORT
00033 #include <gnutls/gnutls.h>
00034 #if GNUTLS_VERSION_MAJOR >= 3
00035 #include <gnutls/abstract.h>
00036 #endif
00037 #endif
00038 #if EPOLL_SUPPORT
00039 #include <sys/epoll.h>
00040 #endif
00041
00042
00047 #define EXTRA_CHECKS MHD_NO
00048
00049 #define MHD_MAX(a,b) ((a)<(b)) ? (b) : (a)
00050 #define MHD_MIN(a,b) ((a)<(b)) ? (a) : (b)
00051
00052
00060 #define MHD_BUF_INC_SIZE 1024
00061
00062
00066 extern MHD_PanicCallback mhd_panic;
00067
00071 extern void *mhd_panic_cls;
00072
00073 #if HAVE_MESSAGES
00074
00079 #define MHD_PANIC(msg) mhd_panic (mhd_panic_cls, __FILE__, __LINE__, msg)
00080 #else
00081
00086 #define MHD_PANIC(msg) mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL)
00087 #endif
00088
00089
00093 enum MHD_EpollState
00094 {
00095
00100 MHD_EPOLL_STATE_UNREADY = 0,
00101
00106 MHD_EPOLL_STATE_READ_READY = 1,
00107
00112 MHD_EPOLL_STATE_WRITE_READY = 2,
00113
00117 MHD_EPOLL_STATE_IN_EREADY_EDLL = 4,
00118
00122 MHD_EPOLL_STATE_IN_EPOLL_SET = 8,
00123
00127 MHD_EPOLL_STATE_SUSPENDED = 16
00128 };
00129
00130
00134 enum MHD_ConnectionEventLoopInfo
00135 {
00139 MHD_EVENT_LOOP_INFO_READ = 0,
00140
00144 MHD_EVENT_LOOP_INFO_WRITE = 1,
00145
00149 MHD_EVENT_LOOP_INFO_BLOCK = 2,
00150
00154 MHD_EVENT_LOOP_INFO_CLEANUP = 3
00155 };
00156
00157
00164 #define MAX_NONCE_LENGTH 129
00165
00166
00171 struct MHD_NonceNc
00172 {
00173
00178 unsigned long int nc;
00179
00183 char nonce[MAX_NONCE_LENGTH];
00184
00185 };
00186
00187 #if HAVE_MESSAGES
00188
00192 void
00193 MHD_DLOG (const struct MHD_Daemon *daemon,
00194 const char *format, ...);
00195 #endif
00196
00208 size_t
00209 MHD_http_unescape (void *cls,
00210 struct MHD_Connection *connection,
00211 char *val);
00212
00213
00217 struct MHD_HTTP_Header
00218 {
00222 struct MHD_HTTP_Header *next;
00223
00228 char *header;
00229
00233 char *value;
00234
00239 enum MHD_ValueKind kind;
00240
00241 };
00242
00243
00247 struct MHD_Response
00248 {
00249
00255 struct MHD_HTTP_Header *first_header;
00256
00261 char *data;
00262
00267 void *crc_cls;
00268
00273 MHD_ContentReaderCallback crc;
00274
00279 MHD_ContentReaderFreeCallback crfc;
00280
00285 pthread_mutex_t mutex;
00286
00290 uint64_t total_size;
00291
00296 uint64_t data_start;
00297
00301 off_t fd_off;
00302
00306 size_t data_size;
00307
00311 size_t data_buffer_size;
00312
00317 unsigned int reference_count;
00318
00322 int fd;
00323
00324 };
00325
00326
00341 enum MHD_CONNECTION_STATE
00342 {
00347 MHD_CONNECTION_INIT = 0,
00348
00352 MHD_CONNECTION_URL_RECEIVED = MHD_CONNECTION_INIT + 1,
00353
00357 MHD_CONNECTION_HEADER_PART_RECEIVED = MHD_CONNECTION_URL_RECEIVED + 1,
00358
00362 MHD_CONNECTION_HEADERS_RECEIVED = MHD_CONNECTION_HEADER_PART_RECEIVED + 1,
00363
00367 MHD_CONNECTION_HEADERS_PROCESSED = MHD_CONNECTION_HEADERS_RECEIVED + 1,
00368
00372 MHD_CONNECTION_CONTINUE_SENDING = MHD_CONNECTION_HEADERS_PROCESSED + 1,
00373
00377 MHD_CONNECTION_CONTINUE_SENT = MHD_CONNECTION_CONTINUE_SENDING + 1,
00378
00382 MHD_CONNECTION_BODY_RECEIVED = MHD_CONNECTION_CONTINUE_SENT + 1,
00383
00388 MHD_CONNECTION_FOOTER_PART_RECEIVED = MHD_CONNECTION_BODY_RECEIVED + 1,
00389
00394 MHD_CONNECTION_FOOTERS_RECEIVED = MHD_CONNECTION_FOOTER_PART_RECEIVED + 1,
00395
00400 MHD_CONNECTION_HEADERS_SENDING = MHD_CONNECTION_FOOTERS_RECEIVED + 1,
00401
00405 MHD_CONNECTION_HEADERS_SENT = MHD_CONNECTION_HEADERS_SENDING + 1,
00406
00410 MHD_CONNECTION_NORMAL_BODY_READY = MHD_CONNECTION_HEADERS_SENT + 1,
00411
00416 MHD_CONNECTION_NORMAL_BODY_UNREADY = MHD_CONNECTION_NORMAL_BODY_READY + 1,
00417
00421 MHD_CONNECTION_CHUNKED_BODY_READY = MHD_CONNECTION_NORMAL_BODY_UNREADY + 1,
00422
00426 MHD_CONNECTION_CHUNKED_BODY_UNREADY = MHD_CONNECTION_CHUNKED_BODY_READY + 1,
00427
00431 MHD_CONNECTION_BODY_SENT = MHD_CONNECTION_CHUNKED_BODY_UNREADY + 1,
00432
00436 MHD_CONNECTION_FOOTERS_SENDING = MHD_CONNECTION_BODY_SENT + 1,
00437
00441 MHD_CONNECTION_FOOTERS_SENT = MHD_CONNECTION_FOOTERS_SENDING + 1,
00442
00446 MHD_CONNECTION_CLOSED = MHD_CONNECTION_FOOTERS_SENT + 1,
00447
00451 MHD_CONNECTION_IN_CLEANUP = MHD_CONNECTION_CLOSED + 1,
00452
00453
00454
00455
00456
00462 MHD_TLS_CONNECTION_INIT = MHD_CONNECTION_IN_CLEANUP + 1
00463
00464 };
00465
00469 #define DEBUG_STATES MHD_NO
00470
00471
00472 #if HAVE_MESSAGES
00473 #if DEBUG_STATES
00474 const char *
00475 MHD_state_to_string (enum MHD_CONNECTION_STATE state);
00476 #endif
00477 #endif
00478
00487 typedef ssize_t (*ReceiveCallback) (struct MHD_Connection * conn,
00488 void *write_to, size_t max_bytes);
00489
00490
00499 typedef ssize_t (*TransmitCallback) (struct MHD_Connection * conn,
00500 const void *write_to, size_t max_bytes);
00501
00502
00506 struct MHD_Connection
00507 {
00508
00509 #if EPOLL_SUPPORT
00510
00513 struct MHD_Connection *nextE;
00514
00518 struct MHD_Connection *prevE;
00519 #endif
00520
00524 struct MHD_Connection *next;
00525
00529 struct MHD_Connection *prev;
00530
00534 struct MHD_Connection *nextX;
00535
00539 struct MHD_Connection *prevX;
00540
00544 struct MHD_Daemon *daemon;
00545
00549 struct MHD_HTTP_Header *headers_received;
00550
00554 struct MHD_HTTP_Header *headers_received_tail;
00555
00559 struct MHD_Response *response;
00560
00571 struct MemoryPool *pool;
00572
00579 void *client_context;
00580
00585 char *method;
00586
00591 char *url;
00592
00597 char *version;
00598
00605 char *read_buffer;
00606
00611 char *write_buffer;
00612
00618 char *last;
00619
00626 char *colon;
00627
00632 struct sockaddr *addr;
00633
00638 pthread_t pid;
00639
00646 size_t read_buffer_size;
00647
00652 size_t read_buffer_offset;
00653
00657 size_t write_buffer_size;
00658
00662 size_t write_buffer_send_offset;
00663
00668 size_t write_buffer_append_offset;
00669
00674 uint64_t remaining_upload_size;
00675
00681 uint64_t response_write_position;
00682
00687 size_t continue_message_write_offset;
00688
00692 socklen_t addr_len;
00693
00698 time_t last_activity;
00699
00704 unsigned int connection_timeout;
00705
00711 int client_aware;
00712
00718 int socket_fd;
00719
00726 int read_closed;
00727
00731 int thread_joined;
00732
00736 int in_idle;
00737
00738 #if EPOLL_SUPPORT
00739
00742 enum MHD_EpollState epoll_state;
00743 #endif
00744
00748 enum MHD_CONNECTION_STATE state;
00749
00753 enum MHD_ConnectionEventLoopInfo event_loop_info;
00754
00759 unsigned int responseCode;
00760
00768 int response_unready;
00769
00777 int have_chunked_upload;
00778
00785 unsigned int current_chunk_size;
00786
00791 unsigned int current_chunk_offset;
00792
00796 int (*read_handler) (struct MHD_Connection * connection);
00797
00801 int (*write_handler) (struct MHD_Connection * connection);
00802
00806 int (*idle_handler) (struct MHD_Connection * connection);
00807
00811 ReceiveCallback recv_cls;
00812
00816 TransmitCallback send_cls;
00817
00818 #if HTTPS_SUPPORT
00819
00822 gnutls_session_t tls_session;
00823
00827 int protocol;
00828
00832 int cipher;
00833
00838 int tls_read_ready;
00839 #endif
00840
00844 int suspended;
00845
00849 int resuming;
00850 };
00851
00860 typedef void * (*LogCallback)(void * cls,
00861 const char * uri,
00862 struct MHD_Connection *con);
00863
00873 typedef size_t (*UnescapeCallback)(void *cls,
00874 struct MHD_Connection *conn,
00875 char *uri);
00876
00877
00885 struct MHD_Daemon
00886 {
00887
00891 MHD_AccessHandlerCallback default_handler;
00892
00896 void *default_handler_cls;
00897
00901 struct MHD_Connection *connections_head;
00902
00906 struct MHD_Connection *connections_tail;
00907
00911 struct MHD_Connection *suspended_connections_head;
00912
00916 struct MHD_Connection *suspended_connections_tail;
00917
00921 struct MHD_Connection *cleanup_head;
00922
00926 struct MHD_Connection *cleanup_tail;
00927
00928 #if EPOLL_SUPPORT
00929
00932 struct MHD_Connection *eready_head;
00933
00937 struct MHD_Connection *eready_tail;
00938 #endif
00939
00952 struct MHD_Connection *normal_timeout_head;
00953
00958 struct MHD_Connection *normal_timeout_tail;
00959
00965 struct MHD_Connection *manual_timeout_head;
00966
00971 struct MHD_Connection *manual_timeout_tail;
00972
00977 MHD_AcceptPolicyCallback apc;
00978
00982 void *apc_cls;
00983
00988 MHD_RequestCompletedCallback notify_completed;
00989
00993 void *notify_completed_cls;
00994
01002 LogCallback uri_log_callback;
01003
01007 void *uri_log_callback_cls;
01008
01012 UnescapeCallback unescape_callback;
01013
01017 void *unescape_callback_cls;
01018
01019 #if HAVE_MESSAGES
01020
01024 void (*custom_error_log) (void *cls, const char *fmt, va_list va);
01025
01029 void *custom_error_log_cls;
01030 #endif
01031
01035 struct MHD_Daemon *master;
01036
01040 struct MHD_Daemon *worker_pool;
01041
01045 void *per_ip_connection_count;
01046
01050 size_t pool_size;
01051
01055 size_t pool_increment;
01056
01060 size_t thread_stack_size;
01061
01065 unsigned int worker_pool_size;
01066
01070 pthread_t pid;
01071
01075 pthread_mutex_t per_ip_connection_mutex;
01076
01080 pthread_mutex_t cleanup_connection_mutex;
01081
01085 int socket_fd;
01086
01087 #if EPOLL_SUPPORT
01088
01091 int epoll_fd;
01092
01097 int listen_socket_in_epoll;
01098 #endif
01099
01106 int wpipe[2];
01107
01111 int shutdown;
01112
01113
01114
01115
01116 int resuming;
01117
01121 unsigned int max_connections;
01122
01127 unsigned int connection_timeout;
01128
01133 unsigned int per_ip_connection_limit;
01134
01138 enum MHD_OPTION options;
01139
01143 uint16_t port;
01144
01145 #if HTTPS_SUPPORT
01146
01149 gnutls_priority_t priority_cache;
01150
01155 gnutls_credentials_type_t cred_type;
01156
01160 gnutls_certificate_credentials_t x509_cred;
01161
01165 gnutls_dh_params_t dh_params;
01166
01167 #if GNUTLS_VERSION_MAJOR >= 3
01168
01172 gnutls_certificate_retrieve_function2 *cert_callback;
01173 #endif
01174
01178 const char *https_mem_key;
01179
01183 const char *https_mem_cert;
01184
01188 const char *https_mem_trust;
01189
01196 unsigned int num_tls_read_ready;
01197
01198 #endif
01199
01200 #ifdef DAUTH_SUPPORT
01201
01205 const char *digest_auth_random;
01206
01210 struct MHD_NonceNc *nnc;
01211
01215 pthread_mutex_t nnc_lock;
01216
01220 unsigned int digest_auth_rand_size;
01221
01225 unsigned int nonce_nc_size;
01226
01227 #endif
01228
01229 };
01230
01231
01232 #if EXTRA_CHECKS
01233 #define EXTRA_CHECK(a) if (!(a)) abort();
01234 #else
01235 #define EXTRA_CHECK(a)
01236 #endif
01237
01238
01247 #define DLL_insert(head,tail,element) do { \
01248 (element)->next = (head); \
01249 (element)->prev = NULL; \
01250 if ((tail) == NULL) \
01251 (tail) = element; \
01252 else \
01253 (head)->prev = element; \
01254 (head) = (element); } while (0)
01255
01256
01266 #define DLL_remove(head,tail,element) do { \
01267 if ((element)->prev == NULL) \
01268 (head) = (element)->next; \
01269 else \
01270 (element)->prev->next = (element)->next; \
01271 if ((element)->next == NULL) \
01272 (tail) = (element)->prev; \
01273 else \
01274 (element)->next->prev = (element)->prev; \
01275 (element)->next = NULL; \
01276 (element)->prev = NULL; } while (0)
01277
01278
01279
01288 #define XDLL_insert(head,tail,element) do { \
01289 (element)->nextX = (head); \
01290 (element)->prevX = NULL; \
01291 if ((tail) == NULL) \
01292 (tail) = element; \
01293 else \
01294 (head)->prevX = element; \
01295 (head) = (element); } while (0)
01296
01297
01307 #define XDLL_remove(head,tail,element) do { \
01308 if ((element)->prevX == NULL) \
01309 (head) = (element)->nextX; \
01310 else \
01311 (element)->prevX->nextX = (element)->nextX; \
01312 if ((element)->nextX == NULL) \
01313 (tail) = (element)->prevX; \
01314 else \
01315 (element)->nextX->prevX = (element)->prevX; \
01316 (element)->nextX = NULL; \
01317 (element)->prevX = NULL; } while (0)
01318
01319
01328 #define EDLL_insert(head,tail,element) do { \
01329 (element)->nextE = (head); \
01330 (element)->prevE = NULL; \
01331 if ((tail) == NULL) \
01332 (tail) = element; \
01333 else \
01334 (head)->prevE = element; \
01335 (head) = (element); } while (0)
01336
01337
01347 #define EDLL_remove(head,tail,element) do { \
01348 if ((element)->prevE == NULL) \
01349 (head) = (element)->nextE; \
01350 else \
01351 (element)->prevE->nextE = (element)->nextE; \
01352 if ((element)->nextE == NULL) \
01353 (tail) = (element)->prevE; \
01354 else \
01355 (element)->nextE->prevE = (element)->prevE; \
01356 (element)->nextE = NULL; \
01357 (element)->prevE = NULL; } while (0)
01358
01359
01367 time_t MHD_monotonic_time(void);
01368
01369 #endif