aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r--src/microhttpd/daemon.c236
1 files changed, 212 insertions, 24 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 780ba28e..dbf21e18 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -123,7 +123,7 @@ mhd_panic_std (void *cls,
123MHD_PanicCallback mhd_panic; 123MHD_PanicCallback mhd_panic;
124 124
125/** 125/**
126 * Closure argument for "mhd_panic". 126 * Closure argument for #mhd_panic.
127 */ 127 */
128void *mhd_panic_cls; 128void *mhd_panic_cls;
129 129
@@ -401,7 +401,9 @@ MHD_ip_limit_del (struct MHD_Daemon *daemon,
401 * @return number of bytes actually received 401 * @return number of bytes actually received
402 */ 402 */
403static ssize_t 403static ssize_t
404recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i) 404recv_tls_adapter (struct MHD_Connection *connection,
405 void *other,
406 size_t i)
405{ 407{
406 ssize_t res; 408 ssize_t res;
407 409
@@ -410,7 +412,9 @@ recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i)
410 connection->daemon->num_tls_read_ready--; 412 connection->daemon->num_tls_read_ready--;
411 connection->tls_read_ready = MHD_NO; 413 connection->tls_read_ready = MHD_NO;
412 } 414 }
413 res = gnutls_record_recv (connection->tls_session, other, i); 415 res = gnutls_record_recv (connection->tls_session,
416 other,
417 i);
414 if ( (GNUTLS_E_AGAIN == res) || 418 if ( (GNUTLS_E_AGAIN == res) ||
415 (GNUTLS_E_INTERRUPTED == res) ) 419 (GNUTLS_E_INTERRUPTED == res) )
416 { 420 {
@@ -447,11 +451,14 @@ recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i)
447 */ 451 */
448static ssize_t 452static ssize_t
449send_tls_adapter (struct MHD_Connection *connection, 453send_tls_adapter (struct MHD_Connection *connection,
450 const void *other, size_t i) 454 const void *other,
455 size_t i)
451{ 456{
452 int res; 457 int res;
453 458
454 res = gnutls_record_send (connection->tls_session, other, i); 459 res = gnutls_record_send (connection->tls_session,
460 other,
461 i);
455 if ( (GNUTLS_E_AGAIN == res) || 462 if ( (GNUTLS_E_AGAIN == res) ||
456 (GNUTLS_E_INTERRUPTED == res) ) 463 (GNUTLS_E_INTERRUPTED == res) )
457 { 464 {
@@ -2157,6 +2164,123 @@ MHD_get_timeout (struct MHD_Daemon *daemon,
2157} 2164}
2158 2165
2159 2166
2167#if HTTPS_SUPPORT
2168/**
2169 * Performs bi-directional forwarding on upgraded HTTPS connections
2170 * based on the readyness state stored in the @a urh handle.
2171 *
2172 * @param urh handle to process
2173 */
2174static void
2175process_urh (struct MHD_UpgradeResponseHandle *urh)
2176{
2177#if FIXME_BUFFERS
2178 // FIXME: we need buffer/buffer_size/buffer_off for
2179 // both directions to be somehow stored within urh.
2180 // (Note that despite using the same variable names
2181 // below, we need actually different buffers for each
2182 // direction.)
2183
2184 /* handle reading from HTTPS client and writing to application */
2185 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->celi_client)) &&
2186 (buffer_off < buffer_size) )
2187 {
2188 ssize_t res;
2189
2190 res = gnutls_record_recv (uri->connection->tls_session,
2191 &buffer[buffer_off],
2192 buffer_size - buffer_off);
2193 if ( (GNUTLS_E_AGAIN == res) ||
2194 (GNUTLS_E_INTERRUPTED == res) )
2195 {
2196 urh->celi_client &= ~MHD_EPOLL_STATE_READ_READY;
2197 }
2198 else if (res > 0)
2199 {
2200 buffer_off += res;
2201 }
2202 }
2203 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->celi_mhd)) &&
2204 (buffer_off > 0) )
2205 {
2206 size_t res;
2207
2208 res = write (urh->mhd_socket,
2209 buffer,
2210 buffer_off);
2211 if (-1 == res)
2212 {
2213 /* FIXME: differenciate by errno? */
2214 urh->celi_mhd &= ~MHD_EPOLL_STATE_WRITE_READY;
2215 }
2216 else
2217 {
2218 if (buffer_off != res)
2219 {
2220 memmove (buffer,
2221 &buffer[res],
2222 buffer_off - res);
2223 buffer_off -= res;
2224 }
2225 else
2226 {
2227 buffer_off = 0;
2228 }
2229 }
2230 }
2231
2232 /* handle reading from application and writing to HTTPS client */
2233 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->celi_mhd)) &&
2234 (buffer_off < buffer_size) )
2235 {
2236 size_t res;
2237
2238 res = read (urh->mhd_socket,
2239 &buffer[buffer_off],
2240 buffer_size - buffer_off);
2241 if (-1 == res)
2242 {
2243 /* FIXME: differenciate by errno? */
2244 urh->celi_mhd &= ~MHD_EPOLL_STATE_READ_READY;
2245 }
2246 else
2247 {
2248 buffer_off += res;
2249 }
2250 }
2251 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->celi_client)) &&
2252 (buffer_off > 0) )
2253 {
2254 ssize_t res;
2255
2256 res = gnutls_record_send (uri->connection->tls_session,
2257 buffer,
2258 buffer_off);
2259 if ( (GNUTLS_E_AGAIN == res) ||
2260 (GNUTLS_E_INTERRUPTED == res) )
2261 {
2262 urh->celi_client &= ~MHD_EPOLL_STATE_WRITE_READY;
2263 }
2264 else if (res > 0)
2265 {
2266 if (buffer_off != res)
2267 {
2268 memmove (buffer,
2269 &buffer[res],
2270 buffer_off - res);
2271 buffer_off -= res;
2272 }
2273 else
2274 {
2275 buffer_off = 0;
2276 }
2277 }
2278 }
2279#endif
2280}
2281#endif
2282
2283
2160/** 2284/**
2161 * Run webserver operations. This method should be called by clients 2285 * Run webserver operations. This method should be called by clients
2162 * in combination with #MHD_get_fdset if the client-controlled select 2286 * in combination with #MHD_get_fdset if the client-controlled select
@@ -2185,7 +2309,9 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
2185 MHD_socket ds; 2309 MHD_socket ds;
2186 struct MHD_Connection *pos; 2310 struct MHD_Connection *pos;
2187 struct MHD_Connection *next; 2311 struct MHD_Connection *next;
2312#if HTTPS_SUPPORT
2188 struct MHD_UpgradeResponseHandle *urh; 2313 struct MHD_UpgradeResponseHandle *urh;
2314#endif
2189 unsigned int mask = MHD_USE_SUSPEND_RESUME | MHD_USE_EPOLL_INTERNALLY | 2315 unsigned int mask = MHD_USE_SUSPEND_RESUME | MHD_USE_EPOLL_INTERNALLY |
2190 MHD_USE_SELECT_INTERNALLY | MHD_USE_POLL_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION; 2316 MHD_USE_SELECT_INTERNALLY | MHD_USE_POLL_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION;
2191 2317
@@ -2239,8 +2365,17 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
2239#if HTTPS_SUPPORT 2365#if HTTPS_SUPPORT
2240 for (urh = daemon->urh_head; NULL != urh; urh = urh->next) 2366 for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
2241 { 2367 {
2242 // if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->celi_mhd)) && 2368 /* update urh state based on select() output */
2243 // (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->celi_client)) ) 2369 if (FD_ISSET (urh->connection->socket_fd, read_fd_set))
2370 urh->celi_client |= MHD_EPOLL_STATE_READ_READY;
2371 if (FD_ISSET (urh->connection->socket_fd, write_fd_set))
2372 urh->celi_client |= MHD_EPOLL_STATE_WRITE_READY;
2373 if (FD_ISSET (urh->mhd_socket, read_fd_set))
2374 urh->celi_mhd |= MHD_EPOLL_STATE_READ_READY;
2375 if (FD_ISSET (urh->mhd_socket, write_fd_set))
2376 urh->celi_mhd |= MHD_EPOLL_STATE_WRITE_READY;
2377 /* call generic forwarding function for passing data */
2378 process_urh (urh);
2244 } 2379 }
2245#endif 2380#endif
2246 MHD_cleanup_connections (daemon); 2381 MHD_cleanup_connections (daemon);
@@ -2298,10 +2433,10 @@ MHD_select (struct MHD_Daemon *daemon,
2298 { 2433 {
2299 /* accept only, have one thread per connection */ 2434 /* accept only, have one thread per connection */
2300 if ( (MHD_INVALID_SOCKET != daemon->socket_fd) && 2435 if ( (MHD_INVALID_SOCKET != daemon->socket_fd) &&
2301 (!MHD_add_to_fd_set_ (daemon->socket_fd, 2436 (! MHD_add_to_fd_set_ (daemon->socket_fd,
2302 &rs, 2437 &rs,
2303 &maxsock, 2438 &maxsock,
2304 FD_SETSIZE)) ) 2439 FD_SETSIZE)) )
2305 { 2440 {
2306#ifdef HAVE_MESSAGES 2441#ifdef HAVE_MESSAGES
2307 MHD_DLOG (daemon, "Could not add listen socket to fdset"); 2442 MHD_DLOG (daemon, "Could not add listen socket to fdset");
@@ -2310,10 +2445,10 @@ MHD_select (struct MHD_Daemon *daemon,
2310 } 2445 }
2311 } 2446 }
2312 if ( (MHD_INVALID_PIPE_ != daemon->wpipe[0]) && 2447 if ( (MHD_INVALID_PIPE_ != daemon->wpipe[0]) &&
2313 (!MHD_add_to_fd_set_ (daemon->wpipe[0], 2448 (! MHD_add_to_fd_set_ (daemon->wpipe[0],
2314 &rs, 2449 &rs,
2315 &maxsock, 2450 &maxsock,
2316 FD_SETSIZE)) ) 2451 FD_SETSIZE)) )
2317 { 2452 {
2318#if defined(MHD_WINSOCK_SOCKETS) 2453#if defined(MHD_WINSOCK_SOCKETS)
2319 /* fdset limit reached, new connections 2454 /* fdset limit reached, new connections
@@ -2322,10 +2457,10 @@ MHD_select (struct MHD_Daemon *daemon,
2322 if (MHD_INVALID_SOCKET != daemon->socket_fd) 2457 if (MHD_INVALID_SOCKET != daemon->socket_fd)
2323 { 2458 {
2324 FD_CLR (daemon->socket_fd, &rs); 2459 FD_CLR (daemon->socket_fd, &rs);
2325 if (!MHD_add_to_fd_set_ (daemon->wpipe[0], 2460 if (! MHD_add_to_fd_set_ (daemon->wpipe[0],
2326 &rs, 2461 &rs,
2327 &maxsock, 2462 &maxsock,
2328 FD_SETSIZE)) 2463 FD_SETSIZE))
2329 { 2464 {
2330#endif /* MHD_WINSOCK_SOCKETS */ 2465#endif /* MHD_WINSOCK_SOCKETS */
2331#ifdef HAVE_MESSAGES 2466#ifdef HAVE_MESSAGES
@@ -2410,6 +2545,10 @@ MHD_poll_all (struct MHD_Daemon *daemon,
2410 unsigned int num_connections; 2545 unsigned int num_connections;
2411 struct MHD_Connection *pos; 2546 struct MHD_Connection *pos;
2412 struct MHD_Connection *next; 2547 struct MHD_Connection *next;
2548#if HTTPS_SUPPORT
2549 struct MHD_UpgradeResponseHandle *urh;
2550 struct MHD_UpgradeResponseHandle *urhn;
2551#endif
2413 2552
2414 if ( (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME)) && 2553 if ( (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME)) &&
2415 (MHD_YES == resume_suspended_connections (daemon)) ) 2554 (MHD_YES == resume_suspended_connections (daemon)) )
@@ -2419,6 +2558,10 @@ MHD_poll_all (struct MHD_Daemon *daemon,
2419 num_connections = 0; 2558 num_connections = 0;
2420 for (pos = daemon->connections_head; NULL != pos; pos = pos->next) 2559 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
2421 num_connections++; 2560 num_connections++;
2561#if HTTPS_SUPPORT
2562 for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
2563 num_connections += 2;
2564#endif
2422 { 2565 {
2423 MHD_UNSIGNED_LONG_LONG ltimeout; 2566 MHD_UNSIGNED_LONG_LONG ltimeout;
2424 unsigned int i; 2567 unsigned int i;
@@ -2428,7 +2571,7 @@ MHD_poll_all (struct MHD_Daemon *daemon,
2428 int poll_pipe; 2571 int poll_pipe;
2429 struct pollfd *p; 2572 struct pollfd *p;
2430 2573
2431 p = malloc(sizeof (struct pollfd) * (2 + num_connections)); 2574 p = malloc (sizeof (struct pollfd) * (2 + num_connections));
2432 if (NULL == p) 2575 if (NULL == p)
2433 { 2576 {
2434#ifdef HAVE_MESSAGES 2577#ifdef HAVE_MESSAGES
@@ -2493,6 +2636,23 @@ MHD_poll_all (struct MHD_Daemon *daemon,
2493 } 2636 }
2494 i++; 2637 i++;
2495 } 2638 }
2639#if HTTPS_SUPPORT
2640 for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
2641 {
2642 p[poll_server+i].fd = urh->connection->socket_fd;
2643 if (0 == (MHD_EPOLL_STATE_READ_READY & urh->celi_client))
2644 p[poll_server+i].events |= POLLIN;
2645 if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->celi_client))
2646 p[poll_server+i].events |= POLLOUT;
2647 i++;
2648 p[poll_server+i].fd = urh->mhd_socket;
2649 if (0 == (MHD_EPOLL_STATE_READ_READY & urh->celi_mhd))
2650 p[poll_server+i].events |= POLLIN;
2651 if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->celi_mhd))
2652 p[poll_server+i].events |= POLLOUT;
2653 i++;
2654 }
2655#endif
2496 if (0 == poll_server + num_connections) 2656 if (0 == poll_server + num_connections)
2497 { 2657 {
2498 free(p); 2658 free(p);
@@ -2542,6 +2702,33 @@ MHD_poll_all (struct MHD_Daemon *daemon,
2542 0 != (p[poll_server+i].revents & POLLOUT), 2702 0 != (p[poll_server+i].revents & POLLOUT),
2543 MHD_NO); 2703 MHD_NO);
2544 } 2704 }
2705#if HTTPS_SUPPORT
2706 for (urh = daemon->urh_head; NULL != urh; urh = urhn)
2707 {
2708 urhn = urh->next;
2709 if (p[poll_server+i].fd != urh->connection->socket_fd)
2710 continue; /* fd mismatch, something else happened, retry later ... */
2711 if (0 != (p[poll_server+i].revents & POLLIN))
2712 urh->celi_client |= MHD_EPOLL_STATE_READ_READY;
2713 if (0 != (p[poll_server+i].revents & POLLOUT))
2714 urh->celi_client |= MHD_EPOLL_STATE_WRITE_READY;
2715 i++;
2716 if (p[poll_server+i].fd != urh->mhd_socket)
2717 {
2718 /* fd mismatch, something else happened, retry later ... */
2719 /* may still be able to do something based on updates
2720 to socket_fd availability */
2721 process_urh (urh);
2722 continue;
2723 }
2724 if (0 != (p[poll_server+i].revents & POLLIN))
2725 urh->celi_mhd |= MHD_EPOLL_STATE_READ_READY;
2726 if (0 != (p[poll_server+i].revents & POLLOUT))
2727 urh->celi_mhd |= MHD_EPOLL_STATE_WRITE_READY;
2728 i++;
2729 process_urh (urh);
2730 }
2731#endif
2545 /* handle 'listen' FD */ 2732 /* handle 'listen' FD */
2546 if ( (-1 != poll_listen) && 2733 if ( (-1 != poll_listen) &&
2547 (0 != (p[poll_listen].revents & POLLIN)) ) 2734 (0 != (p[poll_listen].revents & POLLIN)) )
@@ -3081,9 +3268,10 @@ MHD_quiesce_daemon (struct MHD_Daemon *daemon)
3081 * @param format format string 3268 * @param format format string
3082 * @param va arguments to the format string (fprintf-style) 3269 * @param va arguments to the format string (fprintf-style)
3083 */ 3270 */
3084typedef void (*VfprintfFunctionPointerType)(void *cls, 3271typedef void
3085 const char *format, 3272(*VfprintfFunctionPointerType)(void *cls,
3086 va_list va); 3273 const char *format,
3274 va_list va);
3087 3275
3088 3276
3089/** 3277/**
@@ -3687,7 +3875,7 @@ MHD_start_daemon_va (unsigned int flags,
3687 } 3875 }
3688 if ( (0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL))) && 3876 if ( (0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
3689 (1 == use_pipe) && 3877 (1 == use_pipe) &&
3690 (!MHD_SCKT_FD_FITS_FDSET_(daemon->wpipe[0], NULL)) ) 3878 (! MHD_SCKT_FD_FITS_FDSET_(daemon->wpipe[0], NULL)) )
3691 { 3879 {
3692#ifdef HAVE_MESSAGES 3880#ifdef HAVE_MESSAGES
3693 MHD_DLOG (daemon, 3881 MHD_DLOG (daemon,