diff options
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r-- | src/microhttpd/daemon.c | 236 |
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, MHD_PanicCallback mhd_panic; /** - * Closure argument for "mhd_panic". + * Closure argument for #mhd_panic. */ void *mhd_panic_cls; @@ -401,7 +401,9 @@ MHD_ip_limit_del (struct MHD_Daemon *daemon, * @return number of bytes actually received */ static ssize_t -recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i) +recv_tls_adapter (struct MHD_Connection *connection, + void *other, + size_t i) { ssize_t res; @@ -410,7 +412,9 @@ recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i) connection->daemon->num_tls_read_ready--; connection->tls_read_ready = MHD_NO; } - res = gnutls_record_recv (connection->tls_session, other, i); + res = gnutls_record_recv (connection->tls_session, + other, + i); if ( (GNUTLS_E_AGAIN == res) || (GNUTLS_E_INTERRUPTED == res) ) { @@ -447,11 +451,14 @@ recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i) */ static ssize_t send_tls_adapter (struct MHD_Connection *connection, - const void *other, size_t i) + const void *other, + size_t i) { int res; - res = gnutls_record_send (connection->tls_session, other, i); + res = gnutls_record_send (connection->tls_session, + other, + i); if ( (GNUTLS_E_AGAIN == res) || (GNUTLS_E_INTERRUPTED == res) ) { @@ -2157,6 +2164,123 @@ MHD_get_timeout (struct MHD_Daemon *daemon, } +#if HTTPS_SUPPORT +/** + * Performs bi-directional forwarding on upgraded HTTPS connections + * based on the readyness state stored in the @a urh handle. + * + * @param urh handle to process + */ +static void +process_urh (struct MHD_UpgradeResponseHandle *urh) +{ +#if FIXME_BUFFERS + // FIXME: we need buffer/buffer_size/buffer_off for + // both directions to be somehow stored within urh. + // (Note that despite using the same variable names + // below, we need actually different buffers for each + // direction.) + + /* handle reading from HTTPS client and writing to application */ + if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->celi_client)) && + (buffer_off < buffer_size) ) + { + ssize_t res; + + res = gnutls_record_recv (uri->connection->tls_session, + &buffer[buffer_off], + buffer_size - buffer_off); + if ( (GNUTLS_E_AGAIN == res) || + (GNUTLS_E_INTERRUPTED == res) ) + { + urh->celi_client &= ~MHD_EPOLL_STATE_READ_READY; + } + else if (res > 0) + { + buffer_off += res; + } + } + if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->celi_mhd)) && + (buffer_off > 0) ) + { + size_t res; + + res = write (urh->mhd_socket, + buffer, + buffer_off); + if (-1 == res) + { + /* FIXME: differenciate by errno? */ + urh->celi_mhd &= ~MHD_EPOLL_STATE_WRITE_READY; + } + else + { + if (buffer_off != res) + { + memmove (buffer, + &buffer[res], + buffer_off - res); + buffer_off -= res; + } + else + { + buffer_off = 0; + } + } + } + + /* handle reading from application and writing to HTTPS client */ + if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->celi_mhd)) && + (buffer_off < buffer_size) ) + { + size_t res; + + res = read (urh->mhd_socket, + &buffer[buffer_off], + buffer_size - buffer_off); + if (-1 == res) + { + /* FIXME: differenciate by errno? */ + urh->celi_mhd &= ~MHD_EPOLL_STATE_READ_READY; + } + else + { + buffer_off += res; + } + } + if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->celi_client)) && + (buffer_off > 0) ) + { + ssize_t res; + + res = gnutls_record_send (uri->connection->tls_session, + buffer, + buffer_off); + if ( (GNUTLS_E_AGAIN == res) || + (GNUTLS_E_INTERRUPTED == res) ) + { + urh->celi_client &= ~MHD_EPOLL_STATE_WRITE_READY; + } + else if (res > 0) + { + if (buffer_off != res) + { + memmove (buffer, + &buffer[res], + buffer_off - res); + buffer_off -= res; + } + else + { + buffer_off = 0; + } + } + } +#endif +} +#endif + + /** * Run webserver operations. This method should be called by clients * in combination with #MHD_get_fdset if the client-controlled select @@ -2185,7 +2309,9 @@ MHD_run_from_select (struct MHD_Daemon *daemon, MHD_socket ds; struct MHD_Connection *pos; struct MHD_Connection *next; +#if HTTPS_SUPPORT struct MHD_UpgradeResponseHandle *urh; +#endif unsigned int mask = MHD_USE_SUSPEND_RESUME | MHD_USE_EPOLL_INTERNALLY | MHD_USE_SELECT_INTERNALLY | MHD_USE_POLL_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION; @@ -2239,8 +2365,17 @@ MHD_run_from_select (struct MHD_Daemon *daemon, #if HTTPS_SUPPORT for (urh = daemon->urh_head; NULL != urh; urh = urh->next) { - // if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->celi_mhd)) && - // (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->celi_client)) ) + /* update urh state based on select() output */ + if (FD_ISSET (urh->connection->socket_fd, read_fd_set)) + urh->celi_client |= MHD_EPOLL_STATE_READ_READY; + if (FD_ISSET (urh->connection->socket_fd, write_fd_set)) + urh->celi_client |= MHD_EPOLL_STATE_WRITE_READY; + if (FD_ISSET (urh->mhd_socket, read_fd_set)) + urh->celi_mhd |= MHD_EPOLL_STATE_READ_READY; + if (FD_ISSET (urh->mhd_socket, write_fd_set)) + urh->celi_mhd |= MHD_EPOLL_STATE_WRITE_READY; + /* call generic forwarding function for passing data */ + process_urh (urh); } #endif MHD_cleanup_connections (daemon); @@ -2298,10 +2433,10 @@ MHD_select (struct MHD_Daemon *daemon, { /* accept only, have one thread per connection */ if ( (MHD_INVALID_SOCKET != daemon->socket_fd) && - (!MHD_add_to_fd_set_ (daemon->socket_fd, - &rs, - &maxsock, - FD_SETSIZE)) ) + (! MHD_add_to_fd_set_ (daemon->socket_fd, + &rs, + &maxsock, + FD_SETSIZE)) ) { #ifdef HAVE_MESSAGES MHD_DLOG (daemon, "Could not add listen socket to fdset"); @@ -2310,10 +2445,10 @@ MHD_select (struct MHD_Daemon *daemon, } } if ( (MHD_INVALID_PIPE_ != daemon->wpipe[0]) && - (!MHD_add_to_fd_set_ (daemon->wpipe[0], - &rs, - &maxsock, - FD_SETSIZE)) ) + (! MHD_add_to_fd_set_ (daemon->wpipe[0], + &rs, + &maxsock, + FD_SETSIZE)) ) { #if defined(MHD_WINSOCK_SOCKETS) /* fdset limit reached, new connections @@ -2322,10 +2457,10 @@ MHD_select (struct MHD_Daemon *daemon, if (MHD_INVALID_SOCKET != daemon->socket_fd) { FD_CLR (daemon->socket_fd, &rs); - if (!MHD_add_to_fd_set_ (daemon->wpipe[0], - &rs, - &maxsock, - FD_SETSIZE)) + if (! MHD_add_to_fd_set_ (daemon->wpipe[0], + &rs, + &maxsock, + FD_SETSIZE)) { #endif /* MHD_WINSOCK_SOCKETS */ #ifdef HAVE_MESSAGES @@ -2410,6 +2545,10 @@ MHD_poll_all (struct MHD_Daemon *daemon, unsigned int num_connections; struct MHD_Connection *pos; struct MHD_Connection *next; +#if HTTPS_SUPPORT + struct MHD_UpgradeResponseHandle *urh; + struct MHD_UpgradeResponseHandle *urhn; +#endif if ( (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME)) && (MHD_YES == resume_suspended_connections (daemon)) ) @@ -2419,6 +2558,10 @@ MHD_poll_all (struct MHD_Daemon *daemon, num_connections = 0; for (pos = daemon->connections_head; NULL != pos; pos = pos->next) num_connections++; +#if HTTPS_SUPPORT + for (urh = daemon->urh_head; NULL != urh; urh = urh->next) + num_connections += 2; +#endif { MHD_UNSIGNED_LONG_LONG ltimeout; unsigned int i; @@ -2428,7 +2571,7 @@ MHD_poll_all (struct MHD_Daemon *daemon, int poll_pipe; struct pollfd *p; - p = malloc(sizeof (struct pollfd) * (2 + num_connections)); + p = malloc (sizeof (struct pollfd) * (2 + num_connections)); if (NULL == p) { #ifdef HAVE_MESSAGES @@ -2493,6 +2636,23 @@ MHD_poll_all (struct MHD_Daemon *daemon, } i++; } +#if HTTPS_SUPPORT + for (urh = daemon->urh_head; NULL != urh; urh = urh->next) + { + p[poll_server+i].fd = urh->connection->socket_fd; + if (0 == (MHD_EPOLL_STATE_READ_READY & urh->celi_client)) + p[poll_server+i].events |= POLLIN; + if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->celi_client)) + p[poll_server+i].events |= POLLOUT; + i++; + p[poll_server+i].fd = urh->mhd_socket; + if (0 == (MHD_EPOLL_STATE_READ_READY & urh->celi_mhd)) + p[poll_server+i].events |= POLLIN; + if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->celi_mhd)) + p[poll_server+i].events |= POLLOUT; + i++; + } +#endif if (0 == poll_server + num_connections) { free(p); @@ -2542,6 +2702,33 @@ MHD_poll_all (struct MHD_Daemon *daemon, 0 != (p[poll_server+i].revents & POLLOUT), MHD_NO); } +#if HTTPS_SUPPORT + for (urh = daemon->urh_head; NULL != urh; urh = urhn) + { + urhn = urh->next; + if (p[poll_server+i].fd != urh->connection->socket_fd) + continue; /* fd mismatch, something else happened, retry later ... */ + if (0 != (p[poll_server+i].revents & POLLIN)) + urh->celi_client |= MHD_EPOLL_STATE_READ_READY; + if (0 != (p[poll_server+i].revents & POLLOUT)) + urh->celi_client |= MHD_EPOLL_STATE_WRITE_READY; + i++; + if (p[poll_server+i].fd != urh->mhd_socket) + { + /* fd mismatch, something else happened, retry later ... */ + /* may still be able to do something based on updates + to socket_fd availability */ + process_urh (urh); + continue; + } + if (0 != (p[poll_server+i].revents & POLLIN)) + urh->celi_mhd |= MHD_EPOLL_STATE_READ_READY; + if (0 != (p[poll_server+i].revents & POLLOUT)) + urh->celi_mhd |= MHD_EPOLL_STATE_WRITE_READY; + i++; + process_urh (urh); + } +#endif /* handle 'listen' FD */ if ( (-1 != poll_listen) && (0 != (p[poll_listen].revents & POLLIN)) ) @@ -3081,9 +3268,10 @@ MHD_quiesce_daemon (struct MHD_Daemon *daemon) * @param format format string * @param va arguments to the format string (fprintf-style) */ -typedef void (*VfprintfFunctionPointerType)(void *cls, - const char *format, - va_list va); +typedef void +(*VfprintfFunctionPointerType)(void *cls, + const char *format, + va_list va); /** @@ -3687,7 +3875,7 @@ MHD_start_daemon_va (unsigned int flags, } if ( (0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL))) && (1 == use_pipe) && - (!MHD_SCKT_FD_FITS_FDSET_(daemon->wpipe[0], NULL)) ) + (! MHD_SCKT_FD_FITS_FDSET_(daemon->wpipe[0], NULL)) ) { #ifdef HAVE_MESSAGES MHD_DLOG (daemon, |