[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r6876 - in libmicrohttpd: . src/daemon src/examples
From: |
gnunet |
Subject: |
[GNUnet-SVN] r6876 - in libmicrohttpd: . src/daemon src/examples |
Date: |
Sat, 24 May 2008 07:59:21 -0600 (MDT) |
Author: lv-426
Date: 2008-05-24 07:59:21 -0600 (Sat, 24 May 2008)
New Revision: 6876
Added:
libmicrohttpd/src/examples/https_echo_client_example.c
libmicrohttpd/src/examples/https_server_example.c
Modified:
libmicrohttpd/configure.ac
libmicrohttpd/src/daemon/daemon.c
libmicrohttpd/src/daemon/internal.h
libmicrohttpd/src/examples/Makefile.am
Log:
added :
* configure.ac support for --with-gnutls=PFX
* TLS connection handler in daemon.c
* simple TLS echo client server example
Modified: libmicrohttpd/configure.ac
===================================================================
--- libmicrohttpd/configure.ac 2008-05-24 06:59:29 UTC (rev 6875)
+++ libmicrohttpd/configure.ac 2008-05-24 13:59:21 UTC (rev 6876)
@@ -141,6 +141,37 @@
AM_CONDITIONAL(HAVE_ZZUF, test 0 != $HAVE_ZZUF)
AM_CONDITIONAL(HAVE_SOCAT, test 0 != $HAVE_SOCAT)
+# GNUtls linkage
+AC_ARG_WITH(gnutls,
+ [ --with-gnutls=PFX Base of GNU TLS installation],
+ [AC_MSG_RESULT("$with_gnutls")
+ case $with_gnutls in
+ no)
+ ;;
+ yes)
+ AC_CHECK_HEADERS(gnutls.h,gnutls=true)
+ ;;
+ *)
+ LDFLAGS="-L$with_gnutls/lib $LDFLAGS"
+ CPPFLAGS="-I$with_gnutls/include $CPPFLAGS"
+ AC_CHECK_HEADERS(gnutls/gnutls.h,
+ # check for 'gnutls_global_init' in gnutls.so
+ AC_CHECK_LIB(gnutls,gnutls_global_init,
+ GNUTLS_LIB_PATH="$with_gnutls/lib"
+ GNUTLS_LDFLAGS="-L$with_gnutls/lib"
+ GNUTLS_CPPFLAGS="-I$with_gnutls/include"
+ gnutls=true))
+ LDFLAGS=$SAVE_LDFLAGS
+ CPPFLAGS=$SAVE_CPPFLAGS
+ ;;
+ esac
+ ],
+ [AC_MSG_RESULT([--with-gnutls not specified])])
+
+AC_SUBST(GNUTLS_LIB_PATH)
+AC_SUBST(GNUTLS_LDFLAGS)
+AC_SUBST(GNUTLS_CPPFLAGS)
+
AC_SUBST(CPPFLAGS)
AC_SUBST(LIBS)
AC_SUBST(LDFLAGS)
Modified: libmicrohttpd/src/daemon/daemon.c
===================================================================
--- libmicrohttpd/src/daemon/daemon.c 2008-05-24 06:59:29 UTC (rev 6875)
+++ libmicrohttpd/src/daemon/daemon.c 2008-05-24 13:59:21 UTC (rev 6876)
@@ -1,22 +1,22 @@
/*
- This file is part of libmicrohttpd
- (C) 2007 Daniel Pittman and Christian Grothoff
+ This file is part of libmicrohttpd
+ (C) 2007 Daniel Pittman and Christian Grothoff
- 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 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.
+ 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
+ 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 daemon.c
@@ -52,7 +52,6 @@
*/
#define DEBUG_CONNECT MHD_NO
-
/**
* Obtain the select sets for this daemon.
*
@@ -60,307 +59,331 @@
* daemon was not started with the right
* options for this call.
*/
-int
-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)
-{
- struct MHD_Connection *pos;
- int fd;
+int 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)
+ {
+ struct MHD_Connection *con_itr;
+ int fd;
- if ((daemon == NULL) ||
- (read_fd_set == NULL) ||
- (write_fd_set == NULL) ||
- (except_fd_set == NULL) ||
- (max_fd == NULL) ||
- (-1 == (fd = daemon->socket_fd)) ||
- (daemon->shutdown == MHD_YES) ||
- ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0))
- return MHD_NO;
- FD_SET (fd, read_fd_set);
- if ((*max_fd) < fd)
- *max_fd = fd;
- pos = daemon->connections;
- while (pos != NULL)
- {
- if (MHD_YES != MHD_connection_get_fdset (pos,
- read_fd_set,
- write_fd_set,
- except_fd_set, max_fd))
- return MHD_NO;
- pos = pos->next;
- }
+ if ((daemon == NULL) || (read_fd_set == NULL) || (write_fd_set == NULL)
+ || (except_fd_set == NULL) || (max_fd == NULL) || (-1 == (fd = daemon->
+ socket_fd)) || (daemon->shutdown == MHD_YES) || ((daemon->options
+ & MHD_USE_THREAD_PER_CONNECTION) != 0))
+ return MHD_NO;
+
+ __FD_SET (fd, read_fd_set);
+
+ /* update max file descriptor */
+ if ((*max_fd) < fd)
+ *max_fd = fd;
+
+ con_itr = daemon->connections;
+ while (con_itr != NULL)
+ {
+ if (MHD_YES != MHD_connection_get_fdset (con_itr,
+ read_fd_set,
+ write_fd_set,
+ except_fd_set, max_fd))
+ return MHD_NO;
+ con_itr = con_itr->next;
+ }
#if DEBUG_CONNECT
- MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
+ MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
#endif
- return MHD_YES;
-}
+ return MHD_YES;
+ }
/**
* Main function of the thread that handles an individual
* connection.
*/
-static void *
-MHD_handle_connection (void *data)
-{
- struct MHD_Connection *con = data;
- int num_ready;
- fd_set rs;
- fd_set ws;
- fd_set es;
- int max;
- struct timeval tv;
- unsigned int timeout;
- unsigned int now;
+static void * MHD_handle_connection(void *data)
+ {
+ struct MHD_Connection *con = data;
+ int num_ready;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ struct timeval tv;
+ unsigned int timeout;
+ unsigned int now;
- if (con == NULL)
- abort ();
- timeout = con->daemon->connection_timeout;
- while ((!con->daemon->shutdown) && (con->socket_fd != -1))
- {
- FD_ZERO (&rs);
- FD_ZERO (&ws);
- FD_ZERO (&es);
- max = 0;
- MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
- now = time (NULL);
- tv.tv_usec = 0;
- if (timeout > (now - con->last_activity))
- tv.tv_sec = timeout - (now - con->last_activity);
- else
- tv.tv_sec = 0;
- num_ready = SELECT (max + 1,
- &rs, &ws, &es, (timeout != 0) ? &tv : NULL);
- if (num_ready < 0)
- {
- if (errno == EINTR)
- continue;
+ if (con == NULL)
+ abort();
+ timeout = con->daemon->connection_timeout;
+ while ((!con->daemon->shutdown) && (con->socket_fd != -1))
+ {
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ max = 0;
+ MHD_connection_get_fdset(con, &rs, &ws, &es, &max);
+ now = time(NULL);
+ tv.tv_usec = 0;
+ if (timeout > (now - con->last_activity))
+ tv.tv_sec = timeout - (now - con->last_activity);
+ else
+ tv.tv_sec = 0;
+ num_ready = SELECT (max + 1,
+ &rs, &ws, &es, (timeout != 0) ? &tv : NULL);
+ if (num_ready < 0)
+ {
+ if (errno == EINTR)
+ continue;
#if HAVE_MESSAGES
- MHD_DLOG (con->daemon, "Error during select (%d): `%s'\n",
- max, STRERROR (errno));
+ MHD_DLOG(con->daemon, "Error during select (%d): `%s'\n", max,
+ STRERROR (errno));
#endif
- break;
- }
- if (FD_ISSET (con->socket_fd, &rs))
- MHD_connection_handle_read (con);
- if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws)))
- MHD_connection_handle_write (con);
- if (con->socket_fd != -1)
- MHD_connection_handle_idle (con);
- }
- if (con->socket_fd != -1)
- {
+ break;
+ }
+ if (FD_ISSET (con->socket_fd, &rs))
+ MHD_connection_handle_read(con);
+ if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws)))
+ MHD_connection_handle_write(con);
+ if (con->socket_fd != -1)
+ MHD_connection_handle_idle(con);
+ }
+ if (con->socket_fd != -1)
+ {
#if DEBUG_CLOSE
#if HAVE_MESSAGES
- MHD_DLOG (con->daemon,
- "Processing thread terminating, closing connection\n");
+ MHD_DLOG (con->daemon,
+ "Processing thread terminating, closing connection\n");
#endif
#endif
- SHUTDOWN (con->socket_fd, SHUT_RDWR);
- CLOSE (con->socket_fd);
- con->socket_fd = -1;
- }
- return NULL;
-}
+ SHUTDOWN (con->socket_fd, SHUT_RDWR);
+ CLOSE (con->socket_fd);
+ con->socket_fd = -1;
+ }
+ return NULL;
+ }
+/**
+ * Handle an individual TLS connection.
+ */
+static void * MHDS_handle_connection(void *data)
+ {
+ struct MHD_Connection *con = data;
+ if (con == NULL)
+ abort();
+
+ /* forward call to handler */
+ con->daemon->default_handler(NULL, con, NULL, NULL, NULL, NULL, NULL,
+ NULL);
+
+ return NULL;
+ }
+
/**
* Accept an incoming connection and create the MHD_Connection object for
* it. This function also enforces policy by way of checking with the
* accept policy callback.
*/
-static int
-MHD_accept_connection (struct MHD_Daemon *daemon)
-{
- struct MHD_Connection *pos;
- struct MHD_Connection *connection;
- struct sockaddr_in6 addr6;
- struct sockaddr *addr = (struct sockaddr *) &addr6;
- socklen_t addrlen;
- unsigned int have;
- int s;
+static int MHD_accept_connection(struct MHD_Daemon *daemon)
+ {
+ struct MHD_Connection *pos;
+ struct MHD_Connection *connection;
+ struct sockaddr_in6 addr6;
+ struct sockaddr *addr = (struct sockaddr *) &addr6;
+ socklen_t addrlen;
+ unsigned int have;
+ int s, res_thread_create;
#if OSX
- static int on = 1;
+ static int on = 1;
#endif
+ if (sizeof(struct sockaddr) > sizeof(struct sockaddr_in6))
+ abort(); /* fatal, serious error */
+ addrlen = sizeof(struct sockaddr_in6);
+ memset(addr, 0, sizeof(struct sockaddr_in6));
- if (sizeof (struct sockaddr) > sizeof (struct sockaddr_in6))
- abort (); /* fatal, serious error */
- addrlen = sizeof (struct sockaddr_in6);
- memset (addr, 0, sizeof (struct sockaddr_in6));
- s = ACCEPT (daemon->socket_fd, addr, &addrlen);
- if ((s < 0) || (addrlen <= 0))
- {
+ s = ACCEPT (daemon->socket_fd, addr, &addrlen);
+
+ if ((s < 0) || (addrlen <= 0))
+ {
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "Error accepting connection: %s\n", STRERROR (errno));
+ MHD_DLOG(daemon, "Error accepting connection: %s\n", STRERROR (errno));
#endif
- if (s != -1)
- {
- SHUTDOWN (s, SHUT_RDWR);
- CLOSE (s); /* just in case */
- }
- return MHD_NO;
- }
+ if (s != -1)
+ {
+ SHUTDOWN (s, SHUT_RDWR);
+ CLOSE (s);
+ /* just in case */
+ }
+ return MHD_NO;
+ }
#if DEBUG_CONNECT
- MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
+ MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
#endif
- have = 0;
- if ((daemon->per_ip_connection_limit != 0) && (daemon->max_connections > 0))
- {
- pos = daemon->connections;
- while (pos != NULL)
- {
- if ((pos->addr != NULL) && (pos->addr_len == addrlen))
- {
- if (addrlen == sizeof (struct sockaddr_in))
- {
- const struct sockaddr_in *a1 =
- (const struct sockaddr_in *) &addr;
- const struct sockaddr_in *a2 =
- (const struct sockaddr_in *) pos->addr;
- if (0 ==
- memcmp (&a1->sin_addr, &a2->sin_addr,
- sizeof (struct in_addr)))
- have++;
- }
- if (addrlen == sizeof (struct sockaddr_in6))
- {
- const struct sockaddr_in6 *a1 =
- (const struct sockaddr_in6 *) &addr;
- const struct sockaddr_in6 *a2 =
- (const struct sockaddr_in6 *) pos->addr;
- if (0 ==
- memcmp (&a1->sin6_addr, &a2->sin6_addr,
- sizeof (struct in6_addr)))
- have++;
- }
- }
- pos = pos->next;
- }
- }
+ have = 0;
+ if ((daemon->per_ip_connection_limit != 0) && (daemon->max_connections >
0))
+ {
+ pos = daemon->connections;
+ while (pos != NULL)
+ {
+ if ((pos->addr != NULL) && (pos->addr_len == addrlen))
+ {
+ if (addrlen == sizeof(struct sockaddr_in))
+ {
+ const struct sockaddr_in *a1 =
+ (const struct sockaddr_in *) &addr;
+ const struct sockaddr_in *a2 =
+ (const struct sockaddr_in *) pos->addr;
+ if (0 == memcmp(&a1->sin_addr, &a2->sin_addr,
+ sizeof(struct in_addr)))
+ have++;
+ }
+ if (addrlen == sizeof(struct sockaddr_in6))
+ {
+ const struct sockaddr_in6 *a1 =
+ (const struct sockaddr_in6 *) &addr;
+ const struct sockaddr_in6 *a2 =
+ (const struct sockaddr_in6 *) pos->addr;
+ if (0 == memcmp(&a1->sin6_addr, &a2->sin6_addr,
+ sizeof(struct in6_addr)))
+ have++;
+ }
+ }
+ pos = pos->next;
+ }
+ }
- if ((daemon->max_connections == 0) ||
- ((daemon->per_ip_connection_limit != 0) &&
- (daemon->per_ip_connection_limit <= have)))
- {
- /* above connection limit - reject */
+ if ((daemon->max_connections == 0) || ((daemon->per_ip_connection_limit
+ != 0) && (daemon->
+ per_ip_connection_limit <= have)))
+ {
+ /* above connection limit - reject */
#if HAVE_MESSAGES
- MHD_DLOG (daemon,
- "Server reached connection limit (closing inbound
connection)\n");
+ MHD_DLOG(daemon,
+ "Server reached connection limit (closing inbound connection)\n");
#endif
- SHUTDOWN (s, SHUT_RDWR);
- CLOSE (s);
- return MHD_NO;
- }
- if ((daemon->apc != NULL) &&
- (MHD_NO == daemon->apc (daemon->apc_cls, addr, addrlen)))
- {
+ SHUTDOWN (s, SHUT_RDWR);
+ CLOSE (s);
+ return MHD_NO;
+ }
+ if ((daemon->apc != NULL) && (MHD_NO == daemon->apc (daemon->apc_cls,
addr, addrlen)))
+ {
#if DEBUG_CLOSE
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "Connection rejected, closing connection\n");
+ MHD_DLOG (daemon, "Connection rejected, closing connection\n");
#endif
#endif
- SHUTDOWN (s, SHUT_RDWR);
- CLOSE (s);
- return MHD_YES;
- }
+ SHUTDOWN (s, SHUT_RDWR);
+ CLOSE (s);
+ return MHD_YES;
+ }
#if OSX
#ifdef SOL_SOCKET
#ifdef SO_NOSIGPIPE
- setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof (on));
+ setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof (on));
#endif
#endif
#endif
- connection = malloc (sizeof (struct MHD_Connection));
- if (connection == NULL)
- {
+ connection = malloc(sizeof(struct MHD_Connection));
+ if (connection == NULL)
+ {
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
+ MHD_DLOG(daemon, "Error allocating memory: %s\n", STRERROR (errno));
#endif
- SHUTDOWN (s, SHUT_RDWR);
- CLOSE (s);
- return MHD_NO;
- }
- memset (connection, 0, sizeof (struct MHD_Connection));
- connection->pool = NULL;
- connection->addr = malloc (addrlen);
- if (connection->addr == NULL)
- {
+ SHUTDOWN (s, SHUT_RDWR);
+ CLOSE (s);
+ return MHD_NO;
+ }
+ memset(connection, 0, sizeof(struct MHD_Connection));
+ connection->pool = NULL;
+ connection->addr = malloc(addrlen);
+ if (connection->addr == NULL)
+ {
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
+ MHD_DLOG(daemon, "Error allocating memory: %s\n", STRERROR (errno));
#endif
- SHUTDOWN (s, SHUT_RDWR);
- CLOSE (s);
- free (connection);
- return MHD_NO;
- }
- memcpy (connection->addr, addr, addrlen);
- connection->addr_len = addrlen;
- connection->socket_fd = s;
- connection->daemon = daemon;
- if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
- (0 != pthread_create (&connection->pid,
- NULL, &MHD_handle_connection, connection)))
- {
+ SHUTDOWN (s, SHUT_RDWR);
+ CLOSE (s);
+ free(connection);
+ return MHD_NO;
+ }
+ memcpy(connection->addr, addr, addrlen);
+ connection->addr_len = addrlen;
+ connection->socket_fd = s;
+ connection->daemon = daemon;
+
+ /* attempt to create handler thread */
+ if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
+ {
+ if (daemon->options & MHD_USE_SSL)
+ res_thread_create= pthread_create(&connection->pid, NULL,
+ &MHDS_handle_connection, connection);
+ else
+ {
+ res_thread_create= pthread_create(&connection->pid, NULL,
+ &MHD_handle_connection, connection);
+ }
+ if (res_thread_create != 0)
+ {
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "Failed to create a thread: %s\n", STRERROR (errno));
+ MHD_DLOG(daemon, "Failed to create a thread: %s\n", STRERROR
(errno));
#endif
- SHUTDOWN (s, SHUT_RDWR);
- CLOSE (s);
- free (connection->addr);
- free (connection);
- return MHD_NO;
- }
- connection->last_activity = time (NULL);
- connection->next = daemon->connections;
- daemon->connections = connection;
- daemon->max_connections--;
- return MHD_YES;
-}
+ SHUTDOWN (s, SHUT_RDWR);
+ CLOSE (s);
+ free(connection->addr);
+ free(connection);
+ return MHD_NO;
+ }
+ }
+ connection->last_activity = time(NULL);
+ connection->next = daemon->connections;
+ daemon->connections = connection;
+ daemon->max_connections--;
+ return MHD_YES;
+ }
/**
* Free resources associated with all closed connections.
* (destroy responses, free buffers, etc.). A connection
* is known to be closed if the socket_fd is -1.
*/
-static void
-MHD_cleanup_connections (struct MHD_Daemon *daemon)
-{
- struct MHD_Connection *pos;
- struct MHD_Connection *prev;
- void *unused;
+static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
+ {
+ struct MHD_Connection *pos;
+ struct MHD_Connection *prev;
+ void *unused;
- pos = daemon->connections;
- prev = NULL;
- while (pos != NULL)
- {
- if (pos->socket_fd == -1)
- {
- if (prev == NULL)
- daemon->connections = pos->next;
- else
- prev->next = pos->next;
- if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
- {
- pthread_kill (pos->pid, SIGALRM);
- pthread_join (pos->pid, &unused);
- }
- MHD_destroy_response (pos->response);
- MHD_pool_destroy (pos->pool);
- free (pos->addr);
- free (pos);
- daemon->max_connections++;
- if (prev == NULL)
- pos = daemon->connections;
- else
- pos = prev->next;
- continue;
- }
- prev = pos;
- pos = pos->next;
- }
-}
+ pos = daemon->connections;
+ prev = NULL;
+ while (pos != NULL)
+ {
+ if (pos->socket_fd == -1)
+ {
+ if (prev == NULL)
+ daemon->connections = pos->next;
+ else
+ prev->next = pos->next;
+ if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
+ {
+ pthread_kill(pos->pid, SIGALRM);
+ pthread_join(pos->pid, &unused);
+ }
+ MHD_destroy_response(pos->response);
+ MHD_pool_destroy(pos->pool);
+ free(pos->addr);
+ free(pos);
+ daemon->max_connections++;
+ if (prev == NULL)
+ pos = daemon->connections;
+ else
+ pos = prev->next;
+ continue;
+ }
+ prev = pos;
+ pos = pos->next;
+ }
+ }
/**
* Obtain timeout value for select for this daemon
@@ -373,35 +396,34 @@
* not used (or no connections exist that would
* necessiate the use of a timeout right now).
*/
-int
-MHD_get_timeout (struct MHD_Daemon *daemon, unsigned long long *timeout)
-{
- time_t earliest_deadline;
- time_t now;
- struct MHD_Connection *pos;
- unsigned int dto;
+int MHD_get_timeout(struct MHD_Daemon *daemon, unsigned long long *timeout)
+ {
+ time_t earliest_deadline;
+ time_t now;
+ struct MHD_Connection *pos;
+ unsigned int dto;
- dto = daemon->connection_timeout;
- if (0 == dto)
- return MHD_NO;
- pos = daemon->connections;
- if (pos == NULL)
- return MHD_NO; /* no connections */
- now = time (NULL);
- /* start with conservative estimate */
- earliest_deadline = now + dto;
- while (pos != NULL)
- {
- if (earliest_deadline > pos->last_activity + dto)
- earliest_deadline = pos->last_activity + dto;
- pos = pos->next;
- }
- if (earliest_deadline < now)
- *timeout = 0;
- else
- *timeout = (earliest_deadline - now);
- return MHD_YES;
-}
+ dto = daemon->connection_timeout;
+ if (0 == dto)
+ return MHD_NO;
+ pos = daemon->connections;
+ if (pos == NULL)
+ return MHD_NO; /* no connections */
+ now = time(NULL);
+ /* start with conservative estimate */
+ earliest_deadline = now + dto;
+ while (pos != NULL)
+ {
+ if (earliest_deadline > pos->last_activity + dto)
+ earliest_deadline = pos->last_activity + dto;
+ pos = pos->next;
+ }
+ if (earliest_deadline < now)
+ *timeout = 0;
+ else
+ *timeout = (earliest_deadline - now);
+ return MHD_YES;
+ }
/**
* Main select call.
@@ -409,102 +431,103 @@
* @param may_block YES if blocking, NO if non-blocking
* @return MHD_NO on serious errors, MHD_YES on success
*/
-static int
-MHD_select (struct MHD_Daemon *daemon, int may_block)
-{
- struct MHD_Connection *pos;
- int num_ready;
- fd_set rs;
- fd_set ws;
- fd_set es;
- int max;
- struct timeval timeout;
- unsigned long long ltimeout;
- int ds;
- time_t now;
+static int MHD_select(struct MHD_Daemon *daemon, int may_block)
+ {
+ struct MHD_Connection *pos;
+ int num_ready;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ struct timeval timeout;
+ unsigned long long ltimeout;
+ int ds;
+ time_t now;
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
- if (daemon == NULL)
- abort ();
- if (daemon->shutdown == MHD_YES)
- return MHD_NO;
- FD_ZERO (&rs);
- FD_ZERO (&ws);
- FD_ZERO (&es);
- max = 0;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ if (daemon == NULL)
+ abort();
+ if (daemon->shutdown == MHD_YES)
+ return MHD_NO;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ max = 0;
- if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
- {
- /* single-threaded, go over everything */
- if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max))
- return MHD_NO;
- }
- else
- {
- /* accept only, have one thread per connection */
- max = daemon->socket_fd;
- if (max == -1)
- return MHD_NO;
- FD_SET (max, &rs);
- }
- if (may_block == MHD_NO)
- {
- timeout.tv_usec = 0;
- timeout.tv_sec = 0;
- }
- else
- {
- /* ltimeout is in ms */
- if (MHD_YES == MHD_get_timeout (daemon, <imeout))
- {
- timeout.tv_usec = (ltimeout % 1000) * 1000;
- timeout.tv_sec = ltimeout / 1000;
- may_block = MHD_NO;
- }
- }
- num_ready = SELECT (max + 1,
- &rs, &ws, &es, may_block == MHD_NO ? &timeout : NULL);
- if (daemon->shutdown == MHD_YES)
- return MHD_NO;
- if (num_ready < 0)
- {
- if (errno == EINTR)
- return MHD_YES;
+ if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
+ {
+ /* single-threaded, go over everything */
+ if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max))
+ return MHD_NO;
+ }
+ else
+ {
+ /* accept only, have one thread per connection */
+ max = daemon->socket_fd;
+ if (max == -1)
+ return MHD_NO;
+ FD_SET (max, &rs);
+ }
+
+ if (may_block == MHD_NO)
+ {
+ timeout.tv_usec = 0;
+ timeout.tv_sec = 0;
+ }
+ else
+ {
+ /* ltimeout is in ms */
+ if (MHD_YES == MHD_get_timeout (daemon, <imeout))
+ {
+ timeout.tv_usec = (ltimeout % 1000) * 1000;
+ timeout.tv_sec = ltimeout / 1000;
+ may_block = MHD_NO;
+ }
+ }
+
+ num_ready = select(max + 1, &rs, &ws, &es, may_block == MHD_NO ? &timeout
+ : NULL);
+
+ if (daemon->shutdown == MHD_YES)
+ return MHD_NO;
+ if (num_ready < 0)
+ {
+ if (errno == EINTR)
+ return MHD_YES;
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "Select failed: %s\n", STRERROR (errno));
+ MHD_DLOG(daemon, "Select failed: %s\n", STRERROR (errno));
#endif
- return MHD_NO;
- }
- ds = daemon->socket_fd;
- if (ds == -1)
+ return MHD_NO;
+ }
+ ds = daemon->socket_fd;
+ if (ds == -1)
+ return MHD_YES;
+ if (__FD_ISSET (ds, &rs))
+ MHD_accept_connection(daemon);
+ if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
+ {
+ /* do not have a thread per connection, process all connections now */
+ now = time(NULL);
+ pos = daemon->connections;
+ while (pos != NULL)
+ {
+ ds = pos->socket_fd;
+ if (ds != -1)
+ {
+ if (FD_ISSET (ds, &rs))
+ MHD_connection_handle_read(pos);
+ if ((pos->socket_fd != -1) && (FD_ISSET (ds, &ws)))
+ MHD_connection_handle_write(pos);
+ if (pos->socket_fd != -1)
+ MHD_connection_handle_idle(pos);
+ }
+ pos = pos->next;
+ }
+ }
return MHD_YES;
- if (FD_ISSET (ds, &rs))
- MHD_accept_connection (daemon);
- if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
- {
- /* do not have a thread per connection, process all connections now */
- now = time (NULL);
- pos = daemon->connections;
- while (pos != NULL)
- {
- ds = pos->socket_fd;
- if (ds != -1)
- {
- if (FD_ISSET (ds, &rs))
- MHD_connection_handle_read (pos);
- if ((pos->socket_fd != -1) && (FD_ISSET (ds, &ws)))
- MHD_connection_handle_write (pos);
- if (pos->socket_fd != -1)
- MHD_connection_handle_idle (pos);
- }
- pos = pos->next;
- }
- }
- return MHD_YES;
-}
+ }
-
/**
* Run webserver operations (without blocking unless
* in client callbacks). This method should be called
@@ -515,36 +538,32 @@
* daemon was not started with the right
* options for this call.
*/
-int
-MHD_run (struct MHD_Daemon *daemon)
-{
- if ((daemon->shutdown != MHD_NO) ||
- (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
- (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
- return MHD_NO;
- MHD_select (daemon, MHD_NO);
- MHD_cleanup_connections (daemon);
- return MHD_YES;
-}
+int MHD_run(struct MHD_Daemon *daemon)
+ {
+ if ((daemon->shutdown != MHD_NO) || (0 != (daemon->options
+ & MHD_USE_THREAD_PER_CONNECTION)) || (0 != (daemon->options
+ & MHD_USE_SELECT_INTERNALLY)))
+ return MHD_NO;
+ MHD_select(daemon, MHD_NO);
+ MHD_cleanup_connections(daemon);
+ return MHD_YES;
+ }
-
/**
* Thread that runs the select loop until the daemon
* is explicitly shut down.
*/
-static void *
-MHD_select_thread (void *cls)
-{
- struct MHD_Daemon *daemon = cls;
- while (daemon->shutdown == MHD_NO)
- {
- MHD_select (daemon, MHD_YES);
- MHD_cleanup_connections (daemon);
- }
- return NULL;
-}
+static void * MHD_select_thread(void *cls)
+ {
+ struct MHD_Daemon *daemon = cls;
+ while (daemon->shutdown == MHD_NO)
+ {
+ MHD_select(daemon, MHD_YES);
+ MHD_cleanup_connections(daemon);
+ }
+ return NULL;
+ }
-
/**
* Start a webserver on the given port.
*
@@ -556,106 +575,119 @@
* @param dh_cls extra argument to dh
* @return NULL on error, handle to daemon on success
*/
-struct MHD_Daemon *
-MHD_start_daemon (unsigned int options,
- unsigned short port,
- MHD_AcceptPolicyCallback apc,
- void *apc_cls,
- MHD_AccessHandlerCallback dh, void *dh_cls, ...)
-{
- const int on = 1;
- struct MHD_Daemon *retVal;
- int socket_fd;
- struct sockaddr_in servaddr4;
- struct sockaddr_in6 servaddr6;
- const struct sockaddr *servaddr;
- socklen_t addrlen;
- va_list ap;
- enum MHD_OPTION opt;
+struct MHD_Daemon * MHD_start_daemon(unsigned int options,
+ unsigned short port,
+ MHD_AcceptPolicyCallback apc,
+ void *apc_cls,
+ MHD_AccessHandlerCallback dh,
+ void *dh_cls,
+ ...)
+ {
+ const int on = 1;
+ struct MHD_Daemon *retVal;
- if ((options & MHD_USE_SSL) != 0)
- return NULL;
- if ((port == 0) || (dh == NULL))
- return NULL;
- if ((options & MHD_USE_IPv6) != 0)
- socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0);
- else
- socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0);
- if (socket_fd < 0)
- {
+ /* listeningss sockets used by the daemon */
+ int socket_fd;
+
+ struct sockaddr_in servaddr4;
+ struct sockaddr_in6 servaddr6;
+ const struct sockaddr *servaddr;
+ socklen_t addrlen;
+ va_list ap;
+ enum MHD_OPTION opt;
+
+ if ((port == 0) || (dh == NULL))
+ return NULL;
+ if ((options & MHD_USE_IPv6) != 0)
+ socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0);
+ else
+ socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0);
+ if (socket_fd < 0)
+ {
#if HAVE_MESSAGES
- if ((options & MHD_USE_DEBUG) != 0)
- fprintf (stderr, "Call to socket failed: %s\n", STRERROR (errno));
+ if ((options & MHD_USE_DEBUG) != 0)
+ fprintf(stderr, "Call to socket failed: %s\n", STRERROR (errno));
#endif
- return NULL;
- }
- if ((SETSOCKOPT (socket_fd,
- SOL_SOCKET,
- SO_REUSEADDR,
- &on, sizeof (on)) < 0) && (options & MHD_USE_DEBUG) != 0)
- {
+ return NULL;
+ }
+ if ((SETSOCKOPT (socket_fd,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ &on, sizeof (on)) < 0) && (options & MHD_USE_DEBUG) != 0)
+ {
#if HAVE_MESSAGES
- fprintf (stderr, "setsockopt failed: %s\n", STRERROR (errno));
+ fprintf(stderr, "setsockopt failed: %s\n", STRERROR (errno));
#endif
- }
- if ((options & MHD_USE_IPv6) != 0)
- {
- memset (&servaddr6, 0, sizeof (struct sockaddr_in6));
- servaddr6.sin6_family = AF_INET6;
- servaddr6.sin6_port = htons (port);
- servaddr = (struct sockaddr *) &servaddr6;
- addrlen = sizeof (struct sockaddr_in6);
- }
- else
- {
- memset (&servaddr4, 0, sizeof (struct sockaddr_in));
- servaddr4.sin_family = AF_INET;
- servaddr4.sin_port = htons (port);
- servaddr = (struct sockaddr *) &servaddr4;
- addrlen = sizeof (struct sockaddr_in);
- }
- if (BIND (socket_fd, servaddr, addrlen) < 0)
- {
+ }
+ if ((options & MHD_USE_IPv6) != 0)
+ {
+ memset(&servaddr6, 0, sizeof(struct sockaddr_in6));
+ servaddr6.sin6_family = AF_INET6;
+ servaddr6.sin6_port = htons(port);
+ servaddr = (struct sockaddr *) &servaddr6;
+ addrlen = sizeof(struct sockaddr_in6);
+ }
+ else
+ {
+ memset(&servaddr4, 0, sizeof(struct sockaddr_in));
+ servaddr4.sin_family = AF_INET;
+ servaddr4.sin_port = htons(port);
+ servaddr = (struct sockaddr *) &servaddr4;
+ addrlen = sizeof(struct sockaddr_in);
+ }
+ if (BIND (socket_fd, servaddr, addrlen) < 0)
+ {
#if HAVE_MESSAGES
- if ((options & MHD_USE_DEBUG) != 0)
- fprintf (stderr,
- "Failed to bind to port %u: %s\n", port, STRERROR (errno));
+ if ((options & MHD_USE_DEBUG) != 0)
+ fprintf(stderr,
+ "Failed to bind to port %u: %s\n", port, STRERROR (errno));
#endif
- CLOSE (socket_fd);
- return NULL;
- }
- if (LISTEN (socket_fd, 20) < 0)
- {
+ CLOSE (socket_fd);
+ return NULL;
+ }
+ if (LISTEN (socket_fd, 20) < 0)
+ {
#if HAVE_MESSAGES
- if ((options & MHD_USE_DEBUG) != 0)
- fprintf (stderr,
- "Failed to listen for connections: %s\n", STRERROR (errno));
+ if ((options & MHD_USE_DEBUG) != 0)
+ fprintf(stderr,
+ "Failed to listen for connections: %s\n", STRERROR (errno));
#endif
- CLOSE (socket_fd);
- return NULL;
- }
- retVal = malloc (sizeof (struct MHD_Daemon));
- if (retVal == NULL)
- {
- CLOSE (socket_fd);
- return NULL;
- }
- memset (retVal, 0, sizeof (struct MHD_Daemon));
- retVal->options = options;
- retVal->port = port;
- retVal->apc = apc;
- retVal->apc_cls = apc_cls;
- retVal->socket_fd = socket_fd;
- retVal->default_handler = dh;
- retVal->default_handler_cls = dh_cls;
- retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
- retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
- retVal->connection_timeout = 0; /* no timeout */
- va_start (ap, dh_cls);
- while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION)))
- {
- switch (opt)
- {
+ CLOSE (socket_fd);
+ return NULL;
+ }
+
+ /* allocate the mhd daemon */
+
+ retVal = malloc(sizeof(struct MHD_Daemon));
+
+ if (retVal == NULL)
+ {
+ CLOSE (socket_fd);
+ return NULL;
+ }
+
+ memset(retVal, 0, sizeof(struct MHD_Daemon));
+ retVal->options = options;
+ retVal->port = port;
+ retVal->apc = apc;
+ retVal->apc_cls = apc_cls;
+ retVal->socket_fd = socket_fd;
+ retVal->default_handler = dh;
+ retVal->default_handler_cls = dh_cls;
+ retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
+ retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
+ retVal->connection_timeout = 0; /* no timeout */
+
+ /* initializes the argument pointer variable */
+ va_start (ap, dh_cls);
+
+ /*
+ * loop through daemon options
+ */
+ while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION)))
+ {
+ switch (opt)
+ {
case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
retVal->pool_size = va_arg (ap, unsigned int);
break;
@@ -666,8 +698,7 @@
retVal->connection_timeout = va_arg (ap, unsigned int);
break;
case MHD_OPTION_NOTIFY_COMPLETED:
- retVal->notify_completed =
- va_arg (ap, MHD_RequestCompletedCallback);
+ retVal->notify_completed = va_arg (ap, MHD_RequestCompletedCallback);
retVal->notify_completed_cls = va_arg (ap, void *);
break;
case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
@@ -675,76 +706,76 @@
break;
default:
#if HAVE_MESSAGES
- fprintf (stderr,
- "Invalid MHD_OPTION argument! (Did you terminate the list
with MHD_OPTION_END?)\n");
+ fprintf(stderr,
+ "Invalid MHD_OPTION argument! (Did you terminate the list with
MHD_OPTION_END?)\n");
#endif
- abort ();
- }
- }
- va_end (ap);
- if (((0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
- (0 != (options & MHD_USE_SELECT_INTERNALLY))) &&
- (0 != pthread_create (&retVal->pid, NULL, &MHD_select_thread, retVal)))
- {
+ abort();
+ }
+ }
+ va_end (ap);
+ if (((0 != (options & MHD_USE_THREAD_PER_CONNECTION)) || (0 != (options
+ & MHD_USE_SELECT_INTERNALLY))) && (0 != pthread_create(&retVal->pid,
+ NULL, &MHD_select_thread, retVal)))
+ {
#if HAVE_MESSAGES
- MHD_DLOG (retVal,
- "Failed to create listen thread: %s\n", STRERROR (errno));
+ MHD_DLOG(retVal, "Failed to create listen thread: %s\n",
+ STRERROR (errno));
#endif
- free (retVal);
- CLOSE (socket_fd);
- return NULL;
- }
- return retVal;
-}
+ free(retVal);
+ CLOSE (socket_fd);
+ return NULL;
+ }
+ return retVal;
+ }
+
/**
* Shutdown an http daemon.
*/
-void
-MHD_stop_daemon (struct MHD_Daemon *daemon)
-{
- void *unused;
- int fd;
+void MHD_stop_daemon(struct MHD_Daemon *daemon)
+ {
+ void *unused;
+ int fd;
- if (daemon == NULL)
- return;
- daemon->shutdown = MHD_YES;
- fd = daemon->socket_fd;
- daemon->socket_fd = -1;
+ if (daemon == NULL)
+ return;
+ daemon->shutdown = MHD_YES;
+ fd = daemon->socket_fd;
+ daemon->socket_fd = -1;
#if DEBUG_CLOSE
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
+ MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
#endif
#endif
- CLOSE (fd);
- if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
- (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
- {
- pthread_kill (daemon->pid, SIGALRM);
- pthread_join (daemon->pid, &unused);
- }
- while (daemon->connections != NULL)
- {
- if (-1 != daemon->connections->socket_fd)
- {
+ CLOSE (fd);
+ if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || (0
+ != (daemon->
+ options & MHD_USE_SELECT_INTERNALLY)))
+ {
+ pthread_kill(daemon->pid, SIGALRM);
+ pthread_join(daemon->pid, &unused);
+ }
+ while (daemon->connections != NULL)
+ {
+ if (-1 != daemon->connections->socket_fd)
+ {
#if DEBUG_CLOSE
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "MHD shutdown, closing active connections\n");
+ MHD_DLOG (daemon, "MHD shutdown, closing active connections\n");
#endif
#endif
- if (daemon->notify_completed != NULL)
- daemon->notify_completed (daemon->notify_completed_cls,
- daemon->connections,
- &daemon->connections->client_context,
- MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
- SHUTDOWN (daemon->connections->socket_fd, SHUT_RDWR);
- CLOSE (daemon->connections->socket_fd);
- daemon->connections->socket_fd = -1;
- }
- MHD_cleanup_connections (daemon);
- }
- free (daemon);
-}
+ if (daemon->notify_completed != NULL)
+ daemon->notify_completed(daemon->notify_completed_cls,
+ daemon->connections, &daemon->connections->client_context,
+ MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
+ SHUTDOWN (daemon->connections->socket_fd, SHUT_RDWR);
+ CLOSE (daemon->connections->socket_fd);
+ daemon->connections->socket_fd = -1;
+ }
+ MHD_cleanup_connections(daemon);
+ }
+ free(daemon);
+ }
#ifndef WINDOWS
@@ -752,38 +783,37 @@
static struct sigaction old;
-static void
-sigalrmHandler (int sig)
-{
-}
+static void sigalrmHandler(int sig)
+ {
+ }
/**
* Initialize the signal handler for SIGALRM.
*/
-void __attribute__ ((constructor)) MHD_pthread_handlers_ltdl_init ()
-{
- /* make sure SIGALRM does not kill us */
- memset (&sig, 0, sizeof (struct sigaction));
- memset (&old, 0, sizeof (struct sigaction));
- sig.sa_flags = SA_NODEFER;
- sig.sa_handler = &sigalrmHandler;
- sigaction (SIGALRM, &sig, &old);
-}
+void __attribute__ ((constructor)) MHD_pthread_handlers_ltdl_init()
+ {
+ /* make sure SIGALRM does not kill us */
+ memset(&sig, 0, sizeof(struct sigaction));
+ memset(&old, 0, sizeof(struct sigaction));
+ sig.sa_flags = SA_NODEFER;
+ sig.sa_handler = &sigalrmHandler;
+ sigaction(SIGALRM, &sig, &old);
+ }
-void __attribute__ ((destructor)) MHD_pthread_handlers_ltdl_fini ()
-{
- sigaction (SIGALRM, &old, &sig);
-}
+void __attribute__ ((destructor)) MHD_pthread_handlers_ltdl_fini()
+ {
+ sigaction(SIGALRM, &old, &sig);
+ }
#else
void __attribute__ ((constructor)) MHD_win_ltdl_init ()
-{
- plibc_init ("CRISP", "libmicrohttpd");
-}
+ {
+ plibc_init ("CRISP", "libmicrohttpd");
+ }
void __attribute__ ((destructor)) MHD_win_ltdl_fini ()
-{
- plibc_shutdown ();
-}
+ {
+ plibc_shutdown ();
+ }
#endif
/* end of daemon.c */
Modified: libmicrohttpd/src/daemon/internal.h
===================================================================
--- libmicrohttpd/src/daemon/internal.h 2008-05-24 06:59:29 UTC (rev 6875)
+++ libmicrohttpd/src/daemon/internal.h 2008-05-24 13:59:21 UTC (rev 6876)
@@ -1,21 +1,21 @@
/*
- This file is part of libmicrohttpd
- (C) 2007 Daniel Pittman and Christian Grothoff
+ This file is part of libmicrohttpd
+ (C) 2007 Daniel Pittman and Christian Grothoff
- 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 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.
+ 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
-*/
+ 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 internal.h
@@ -27,7 +27,6 @@
#ifndef INTERNAL_H
#define INTERNAL_H
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -64,101 +63,101 @@
* fprintf-like helper function for logging debug
* messages.
*/
-void MHD_DLOG (const struct MHD_Daemon *daemon, const char *format, ...);
+void MHD_DLOG(const struct MHD_Daemon *daemon, const char *format, ...);
#endif
/**
* Process escape sequences ('+'=space, %HH).
* Updates val in place.
*/
-void MHD_http_unescape (char *val);
+void MHD_http_unescape(char *val);
/**
* Header or cookie in HTTP request or response.
*/
struct MHD_HTTP_Header
-{
- struct MHD_HTTP_Header *next;
+ {
+ struct MHD_HTTP_Header *next;
- char *header;
+ char *header;
- char *value;
+ char *value;
- enum MHD_ValueKind kind;
+ enum MHD_ValueKind kind;
-};
+ };
/**
* Representation of a response.
*/
struct MHD_Response
-{
+ {
- /**
- * Headers to send for the response. Initially
- * the linked list is created in inverse order;
- * the order should be inverted before sending!
- */
- struct MHD_HTTP_Header *first_header;
+ /**
+ * Headers to send for the response. Initially
+ * the linked list is created in inverse order;
+ * the order should be inverted before sending!
+ */
+ struct MHD_HTTP_Header *first_header;
- /**
- * Buffer pointing to data that we are supposed
- * to send as a response.
- */
- char *data;
+ /**
+ * Buffer pointing to data that we are supposed
+ * to send as a response.
+ */
+ char *data;
- /**
- * Closure to give to the content reader
- * free callback.
- */
- void *crc_cls;
+ /**
+ * Closure to give to the content reader
+ * free callback.
+ */
+ void *crc_cls;
- /**
- * How do we get more data? NULL if we are
- * given all of the data up front.
- */
- MHD_ContentReaderCallback crc;
+ /**
+ * How do we get more data? NULL if we are
+ * given all of the data up front.
+ */
+ MHD_ContentReaderCallback crc;
- /**
- * NULL if data must not be freed, otherwise
- * either user-specified callback or "&free".
- */
- MHD_ContentReaderFreeCallback crfc;
+ /**
+ * NULL if data must not be freed, otherwise
+ * either user-specified callback or "&free".
+ */
+ MHD_ContentReaderFreeCallback crfc;
- /**
- * Mutex to synchronize access to data/size and
- * reference counts.
- */
- pthread_mutex_t mutex;
+ /**
+ * Mutex to synchronize access to data/size and
+ * reference counts.
+ */
+ pthread_mutex_t mutex;
- /**
- * Reference count for this response. Free
- * once the counter hits zero.
- */
- unsigned int reference_count;
+ /**
+ * Reference count for this response. Free
+ * once the counter hits zero.
+ */
+ unsigned int reference_count;
- /**
- * Set to -1 if size is not known.
- */
- size_t total_size;
+ /**
+ * Set to -1 if size is not known.
+ */
+ size_t total_size;
- /**
- * Size of data.
- */
- size_t data_size;
+ /**
+ * Size of data.
+ */
+ size_t data_size;
- /**
- * Size of the data buffer.
- */
- size_t data_buffer_size;
+ /**
+ * Size of the data buffer.
+ */
+ size_t data_buffer_size;
- /**
- * At what offset in the stream is the
- * beginning of data located?
- */
- size_t data_start;
+ /**
+ * At what offset in the stream is the
+ * beginning of data located?
+ */
+ size_t data_start;
-};
+ };
/**
* States in a state machine for a connection.
@@ -175,419 +174,438 @@
* requires the write to be complete.
*/
enum MHD_CONNECTION_STATE
-{
- /**
- * Connection just started (no headers received).
- * Waiting for the line with the request type, URL and version.
- */
- MHD_CONNECTION_INIT = 0,
+ {
+ /**
+ * Connection just started (no headers received).
+ * Waiting for the line with the request type, URL and version.
+ */
+ MHD_CONNECTION_INIT = 0,
- /**
- * 1: We got the URL (and request type and version). Wait for a header line.
- */
- MHD_CONNECTION_URL_RECEIVED = MHD_CONNECTION_INIT + 1,
+ /**
+ * 1: We got the URL (and request type and version). Wait for a header
line.
+ */
+ MHD_CONNECTION_URL_RECEIVED = MHD_CONNECTION_INIT + 1,
- /**
- * 2: We got part of a multi-line request header. Wait for the rest.
- */
- MHD_CONNECTION_HEADER_PART_RECEIVED = MHD_CONNECTION_URL_RECEIVED + 1,
+ /**
+ * 2: We got part of a multi-line request header. Wait for the rest.
+ */
+ MHD_CONNECTION_HEADER_PART_RECEIVED = MHD_CONNECTION_URL_RECEIVED + 1,
- /**
- * 3: We got the request headers. Process them.
- */
- MHD_CONNECTION_HEADERS_RECEIVED = MHD_CONNECTION_HEADER_PART_RECEIVED + 1,
+ /**
+ * 3: We got the request headers. Process them.
+ */
+ MHD_CONNECTION_HEADERS_RECEIVED = MHD_CONNECTION_HEADER_PART_RECEIVED + 1,
- /**
- * 4: We have processed the request headers. Send 100 continue.
- */
- MHD_CONNECTION_HEADERS_PROCESSED = MHD_CONNECTION_HEADERS_RECEIVED + 1,
+ /**
+ * 4: We have processed the request headers. Send 100 continue.
+ */
+ MHD_CONNECTION_HEADERS_PROCESSED = MHD_CONNECTION_HEADERS_RECEIVED + 1,
- /**
- * 5: We have processed the headers and need to send 100 CONTINUE.
- */
- MHD_CONNECTION_CONTINUE_SENDING = MHD_CONNECTION_HEADERS_PROCESSED + 1,
+ /**
+ * 5: We have processed the headers and need to send 100 CONTINUE.
+ */
+ MHD_CONNECTION_CONTINUE_SENDING = MHD_CONNECTION_HEADERS_PROCESSED + 1,
- /**
- * 6: We have sent 100 CONTINUE (or do not need to). Read the message body.
- */
- MHD_CONNECTION_CONTINUE_SENT = MHD_CONNECTION_CONTINUE_SENDING + 1,
+ /**
+ * 6: We have sent 100 CONTINUE (or do not need to). Read the message
body.
+ */
+ MHD_CONNECTION_CONTINUE_SENT = MHD_CONNECTION_CONTINUE_SENDING + 1,
- /**
- * 7: We got the request body. Wait for a line of the footer.
- */
- MHD_CONNECTION_BODY_RECEIVED = MHD_CONNECTION_CONTINUE_SENT + 1,
+ /**
+ * 7: We got the request body. Wait for a line of the footer.
+ */
+ MHD_CONNECTION_BODY_RECEIVED = MHD_CONNECTION_CONTINUE_SENT + 1,
- /**
- * 8: We got part of a line of the footer. Wait for the
- * rest.
- */
- MHD_CONNECTION_FOOTER_PART_RECEIVED = MHD_CONNECTION_BODY_RECEIVED + 1,
+ /**
+ * 8: We got part of a line of the footer. Wait for the
+ * rest.
+ */
+ MHD_CONNECTION_FOOTER_PART_RECEIVED = MHD_CONNECTION_BODY_RECEIVED + 1,
- /**
- * 9: We received the entire footer. Wait for a response to be queued
- * and prepare the response headers.
- */
- MHD_CONNECTION_FOOTERS_RECEIVED = MHD_CONNECTION_FOOTER_PART_RECEIVED + 1,
+ /**
+ * 9: We received the entire footer. Wait for a response to be queued
+ * and prepare the response headers.
+ */
+ MHD_CONNECTION_FOOTERS_RECEIVED = MHD_CONNECTION_FOOTER_PART_RECEIVED + 1,
- /**
- * 10: We have prepared the response headers in the writ buffer.
- * Send the response headers.
- */
- MHD_CONNECTION_HEADERS_SENDING = MHD_CONNECTION_FOOTERS_RECEIVED + 1,
+ /**
+ * 10: We have prepared the response headers in the writ buffer.
+ * Send the response headers.
+ */
+ MHD_CONNECTION_HEADERS_SENDING = MHD_CONNECTION_FOOTERS_RECEIVED + 1,
- /**
- * 11: We have sent the response headers. Get ready to send the body.
- */
- MHD_CONNECTION_HEADERS_SENT = MHD_CONNECTION_HEADERS_SENDING + 1,
+ /**
+ * 11: We have sent the response headers. Get ready to send the body.
+ */
+ MHD_CONNECTION_HEADERS_SENT = MHD_CONNECTION_HEADERS_SENDING + 1,
- /**
- * 12: We are ready to send a part of a non-chunked body. Send it.
- */
- MHD_CONNECTION_NORMAL_BODY_READY = MHD_CONNECTION_HEADERS_SENT + 1,
+ /**
+ * 12: We are ready to send a part of a non-chunked body. Send it.
+ */
+ MHD_CONNECTION_NORMAL_BODY_READY = MHD_CONNECTION_HEADERS_SENT + 1,
- /**
- * 13: We are waiting for the client to provide more
- * data of a non-chunked body.
- */
- MHD_CONNECTION_NORMAL_BODY_UNREADY = MHD_CONNECTION_NORMAL_BODY_READY + 1,
+ /**
+ * 13: We are waiting for the client to provide more
+ * data of a non-chunked body.
+ */
+ MHD_CONNECTION_NORMAL_BODY_UNREADY = MHD_CONNECTION_NORMAL_BODY_READY + 1,
- /**
- * 14: We are ready to send a chunk.
- */
- MHD_CONNECTION_CHUNKED_BODY_READY = MHD_CONNECTION_NORMAL_BODY_UNREADY + 1,
+ /**
+ * 14: We are ready to send a chunk.
+ */
+ MHD_CONNECTION_CHUNKED_BODY_READY = MHD_CONNECTION_NORMAL_BODY_UNREADY + 1,
- /**
- * 15: We are waiting for the client to provide a chunk of the body.
- */
- MHD_CONNECTION_CHUNKED_BODY_UNREADY = MHD_CONNECTION_CHUNKED_BODY_READY + 1,
+ /**
+ * 15: We are waiting for the client to provide a chunk of the body.
+ */
+ MHD_CONNECTION_CHUNKED_BODY_UNREADY = MHD_CONNECTION_CHUNKED_BODY_READY +
1,
- /**
- * 16: We have sent the response body. Prepare the footers.
- */
- MHD_CONNECTION_BODY_SENT = MHD_CONNECTION_CHUNKED_BODY_UNREADY + 1,
+ /**
+ * 16: We have sent the response body. Prepare the footers.
+ */
+ MHD_CONNECTION_BODY_SENT = MHD_CONNECTION_CHUNKED_BODY_UNREADY + 1,
- /**
- * 17: We have prepared the response footer. Send it.
- */
- MHD_CONNECTION_FOOTERS_SENDING = MHD_CONNECTION_BODY_SENT + 1,
+ /**
+ * 17: We have prepared the response footer. Send it.
+ */
+ MHD_CONNECTION_FOOTERS_SENDING = MHD_CONNECTION_BODY_SENT + 1,
- /**
- * 18: We have sent the response footer. Shutdown or restart.
- */
- MHD_CONNECTION_FOOTERS_SENT = MHD_CONNECTION_FOOTERS_SENDING + 1,
+ /**
+ * 18: We have sent the response footer. Shutdown or restart.
+ */
+ MHD_CONNECTION_FOOTERS_SENT = MHD_CONNECTION_FOOTERS_SENDING + 1,
- /**
- * 19: This connection is closed (no more activity
- * allowed).
- */
- MHD_CONNECTION_CLOSED = MHD_CONNECTION_FOOTERS_SENT + 1,
+ /**
+ * 19: This connection is closed (no more activity
+ * allowed).
+ */
+ MHD_CONNECTION_CLOSED = MHD_CONNECTION_FOOTERS_SENT + 1,
-};
+ };
+enum MHDS_CONNECTION_STATE
+ {
+ MHDS_CONNECTION_INIT = 0,
+
+ /**
+ * 1: We got the URL (and request type and version). Wait for a header
line.
+ */
+ MHDS_HANDSHAKE_COMPLETE = MHDS_CONNECTION_INIT + 1,
+
+ MHDS_CONNECTION_CONTINUE_SENDING = MHDS_HANDSHAKE_COMPLETE + 1,
+
+ MHDS_CONNECTION_CLOSED = MHDS_CONNECTION_CONTINUE_SENDING + 1
+ };
+
struct MHD_Connection
-{
+ {
- /**
- * This is a linked list.
- */
- struct MHD_Connection *next;
+ /**
+ * This is a linked list.
+ */
+ struct MHD_Connection *next;
- /**
- * Reference to the MHD_Daemon struct.
- */
- struct MHD_Daemon *daemon;
+ /**
+ * Reference to the MHD_Daemon struct.
+ */
+ struct MHD_Daemon *daemon;
- /**
- * Linked list of parsed headers.
- */
- struct MHD_HTTP_Header *headers_received;
+ /**
+ * Linked list of parsed headers.
+ */
+ struct MHD_HTTP_Header *headers_received;
- /**
- * Response to transmit (initially NULL).
- */
- struct MHD_Response *response;
+ /**
+ * Response to transmit (initially NULL).
+ */
+ struct MHD_Response *response;
- /**
- * The memory pool is created whenever we first read
- * from the TCP stream and destroyed at the end of
- * each request (and re-created for the next request).
- * In the meantime, this pointer is NULL. The
- * pool is used for all connection-related data
- * except for the response (which maybe shared between
- * connections) and the IP address (which persists
- * across individual requests).
- */
- struct MemoryPool *pool;
+ /**
+ * The memory pool is created whenever we first read
+ * from the TCP stream and destroyed at the end of
+ * each request (and re-created for the next request).
+ * In the meantime, this pointer is NULL. The
+ * pool is used for all connection-related data
+ * except for the response (which maybe shared between
+ * connections) and the IP address (which persists
+ * across individual requests).
+ */
+ struct MemoryPool *pool;
- /**
- * We allow the main application to associate some
- * pointer with the connection. Here is where we
- * store it. (MHD does not know or care what it
- * is).
- */
- void *client_context;
+ /**
+ * We allow the main application to associate some
+ * pointer with the connection. Here is where we
+ * store it. (MHD does not know or care what it
+ * is).
+ */
+ void *client_context;
- /**
- * Request method. Should be GET/POST/etc. Allocated
- * in pool.
- */
- char *method;
+ /**
+ * Request method. Should be GET/POST/etc. Allocated
+ * in pool.
+ */
+ char *method;
- /**
- * Requested URL (everything after "GET" only). Allocated
- * in pool.
- */
- char *url;
+ /**
+ * Requested URL (everything after "GET" only). Allocated
+ * in pool.
+ */
+ char *url;
- /**
- * HTTP version string (i.e. http/1.1). Allocated
- * in pool.
- */
- char *version;
+ /**
+ * HTTP version string (i.e. http/1.1). Allocated
+ * in pool.
+ */
+ char *version;
- /**
- * Buffer for reading requests. Allocated
- * in pool. Actually one byte larger than
- * read_buffer_size (if non-NULL) to allow for
- * 0-termination.
- */
- char *read_buffer;
+ /**
+ * Buffer for reading requests. Allocated
+ * in pool. Actually one byte larger than
+ * read_buffer_size (if non-NULL) to allow for
+ * 0-termination.
+ */
+ char *read_buffer;
- /**
- * Buffer for writing response (headers only). Allocated
- * in pool.
- */
- char *write_buffer;
+ /**
+ * Buffer for writing response (headers only). Allocated
+ * in pool.
+ */
+ char *write_buffer;
- /**
- * Last incomplete header line during parsing of headers.
- * Allocated in pool. Only valid if state is
- * either HEADER_PART_RECEIVED or FOOTER_PART_RECEIVED.
- */
- char *last;
+ /**
+ * Last incomplete header line during parsing of headers.
+ * Allocated in pool. Only valid if state is
+ * either HEADER_PART_RECEIVED or FOOTER_PART_RECEIVED.
+ */
+ char *last;
- /**
- * Position after the colon on the last incomplete header
- * line during parsing of headers.
- * Allocated in pool. Only valid if state is
- * either HEADER_PART_RECEIVED or FOOTER_PART_RECEIVED.
- */
- char *colon;
+ /**
+ * Position after the colon on the last incomplete header
+ * line during parsing of headers.
+ * Allocated in pool. Only valid if state is
+ * either HEADER_PART_RECEIVED or FOOTER_PART_RECEIVED.
+ */
+ char *colon;
- /**
- * Foreign address (of length addr_len). MALLOCED (not
- * in pool!).
- */
- struct sockaddr_in *addr;
+ /**
+ * Foreign address (of length addr_len). MALLOCED (not
+ * in pool!).
+ */
+ struct sockaddr_in *addr;
- /**
- * Thread for this connection (if we are using
- * one thread per connection).
- */
- pthread_t pid;
+ /**
+ * Thread for this connection (if we are using
+ * one thread per connection).
+ */
+ pthread_t pid;
- /**
- * Size of read_buffer (in bytes). This value indicates
- * how many bytes we're willing to read into the buffer;
- * the real buffer is one byte longer to allow for
- * adding zero-termination (when needed).
- */
- size_t read_buffer_size;
+ /**
+ * Size of read_buffer (in bytes). This value indicates
+ * how many bytes we're willing to read into the buffer;
+ * the real buffer is one byte longer to allow for
+ * adding zero-termination (when needed).
+ */
+ size_t read_buffer_size;
- /**
- * Position where we currently append data in
- * read_buffer (last valid position).
- */
- size_t read_buffer_offset;
+ /**
+ * Position where we currently append data in
+ * read_buffer (last valid position).
+ */
+ size_t read_buffer_offset;
- /**
- * Size of write_buffer (in bytes).
- */
- size_t write_buffer_size;
+ /**
+ * Size of write_buffer (in bytes).
+ */
+ size_t write_buffer_size;
- /**
- * Offset where we are with sending from write_buffer.
- */
- size_t write_buffer_send_offset;
+ /**
+ * Offset where we are with sending from write_buffer.
+ */
+ size_t write_buffer_send_offset;
- /**
- * Last valid location in write_buffer (where do we
- * append and up to where is it safe to send?)
- */
- size_t write_buffer_append_offset;
+ /**
+ * Last valid location in write_buffer (where do we
+ * append and up to where is it safe to send?)
+ */
+ size_t write_buffer_append_offset;
- /**
- * How many more bytes of the body do we expect
- * to read? "-1" for unknown.
- */
- size_t remaining_upload_size;
+ /**
+ * How many more bytes of the body do we expect
+ * to read? "-1" for unknown.
+ */
+ size_t remaining_upload_size;
- /**
- * Current write position in the actual response
- * (excluding headers, content only; should be 0
- * while sending headers).
- */
- size_t response_write_position;
+ /**
+ * Current write position in the actual response
+ * (excluding headers, content only; should be 0
+ * while sending headers).
+ */
+ size_t response_write_position;
- /**
- * Position in the 100 CONTINUE message that
- * we need to send when receiving http 1.1 requests.
- */
- size_t continue_message_write_offset;
+ /**
+ * Position in the 100 CONTINUE message that
+ * we need to send when receiving http 1.1 requests.
+ */
+ size_t continue_message_write_offset;
- /**
- * Length of the foreign address.
- */
- socklen_t addr_len;
+ /**
+ * Length of the foreign address.
+ */
+ socklen_t addr_len;
- /**
- * Last time this connection had any activity
- * (reading or writing).
- */
- time_t last_activity;
+ /**
+ * Last time this connection had any activity
+ * (reading or writing).
+ */
+ time_t last_activity;
- /**
- * Socket for this connection. Set to -1 if
- * this connection has died (daemon should clean
- * up in that case).
- */
- int socket_fd;
+ /**
+ * Socket for this connection. Set to -1 if
+ * this connection has died (daemon should clean
+ * up in that case).
+ */
+ int socket_fd;
- /**
- * Has this socket been closed for reading (i.e.
- * other side closed the connection)? If so,
- * we must completely close the connection once
- * we are done sending our response (and stop
- * trying to read from this socket).
- */
- int read_closed;
+ /**
+ * Has this socket been closed for reading (i.e.
+ * other side closed the connection)? If so,
+ * we must completely close the connection once
+ * we are done sending our response (and stop
+ * trying to read from this socket).
+ */
+ int read_closed;
- /**
- * State in the FSM for this connection.
- */
- enum MHD_CONNECTION_STATE state;
+ /**
+ * State in the FSM for this connection.
+ */
+ enum MHD_CONNECTION_STATE state;
- /**
- * HTTP response code. Only valid if response object
- * is already set.
- */
- unsigned int responseCode;
+ /**
+ * HTTP response code. Only valid if response object
+ * is already set.
+ */
+ unsigned int responseCode;
- /**
- * Set to MHD_YES if the response's content reader
- * callback failed to provide data the last time
- * we tried to read from it. In that case, the
- * write socket should be marked as unready until
- * the CRC call succeeds.
- */
- int response_unready;
+ /**
+ * Set to MHD_YES if the response's content reader
+ * callback failed to provide data the last time
+ * we tried to read from it. In that case, the
+ * write socket should be marked as unready until
+ * the CRC call succeeds.
+ */
+ int response_unready;
- /**
- * Are we sending with chunked encoding?
- */
- int have_chunked_response;
+ /**
+ * Are we sending with chunked encoding?
+ */
+ int have_chunked_response;
- /**
- * Are we receiving with chunked encoding? This will be set to
- * MHD_YES after we parse the headers and are processing the body
- * with chunks. After we are done with the body and we are
- * processing the footers; once the footers are also done, this will
- * be set to MHD_NO again (before the final call to the handler).
- */
- int have_chunked_upload;
+ /**
+ * Are we receiving with chunked encoding? This will be set to
+ * MHD_YES after we parse the headers and are processing the body
+ * with chunks. After we are done with the body and we are
+ * processing the footers; once the footers are also done, this will
+ * be set to MHD_NO again (before the final call to the handler).
+ */
+ int have_chunked_upload;
- /**
- * If we are receiving with chunked encoding, where are we right
- * now? Set to 0 if we are waiting to receive the chunk size;
- * otherwise, this is the size of the current chunk. A value of
- * zero is also used when we're at the end of the chunks.
- */
- unsigned int current_chunk_size;
+ /**
+ * If we are receiving with chunked encoding, where are we right
+ * now? Set to 0 if we are waiting to receive the chunk size;
+ * otherwise, this is the size of the current chunk. A value of
+ * zero is also used when we're at the end of the chunks.
+ */
+ unsigned int current_chunk_size;
- /**
- * If we are receiving with chunked encoding, where are we currently
- * with respect to the current chunk (at what offset / position)?
- */
- unsigned int current_chunk_offset;
+ /**
+ * If we are receiving with chunked encoding, where are we currently
+ * with respect to the current chunk (at what offset / position)?
+ */
+ unsigned int current_chunk_offset;
-};
+ };
+typedef struct MHD_Connection MHD_Connection_t;
-
struct MHD_Daemon
-{
+ {
- /**
- * Callback function for all requests.
- */
- MHD_AccessHandlerCallback default_handler;
+ /**
+ * Callback function for all requests.
+ */
+ MHD_AccessHandlerCallback default_handler;
- /**
- * Closure argument to default_handler.
- */
- void *default_handler_cls;
+ /**
+ * Closure argument to default_handler.
+ */
+ void *default_handler_cls;
- /**
- * Linked list of our current connections.
- */
- struct MHD_Connection *connections;
+ /**
+ * Linked list of our current connections.
+ */
+ struct MHD_Connection *connections;
- MHD_AcceptPolicyCallback apc;
+ /**
+ * Linked list of our current connections.
+ */
+ // TODO switch to a dedicated tls connection struct
+ struct MHD_Connection *tls_connections;
- void *apc_cls;
+ MHD_AcceptPolicyCallback apc;
- MHD_RequestCompletedCallback notify_completed;
+ void *apc_cls;
- void *notify_completed_cls;
+ MHD_RequestCompletedCallback notify_completed;
- /**
- * PID of the select thread (if we have internal select)
- */
- pthread_t pid;
+ void *notify_completed_cls;
- /**
- * Listen socket.
- */
- int socket_fd;
+ /**
+ * PID of the select thread (if we have internal select)
+ */
+ pthread_t pid;
- /**
- * Are we shutting down?
- */
- int shutdown;
+ /**
+ * Listen socket.
+ */
+ int socket_fd;
- /**
- * Size of the per-connection memory pools.
- */
- unsigned int pool_size;
+ /**
+ * Are we shutting down?
+ */
+ int shutdown;
- /**
- * Limit on the number of parallel connections.
- */
- unsigned int max_connections;
+ /**
+ * Size of the per-connection memory pools.
+ */
+ unsigned int pool_size;
- /**
- * After how many seconds of inactivity should
- * connections time out? Zero for no timeout.
- */
- unsigned int connection_timeout;
+ /**
+ * Limit on the number of parallel connections.
+ */
+ unsigned int max_connections;
- /**
- * Maximum number of connections per IP, or 0 for
- * unlimited.
- */
- unsigned int per_ip_connection_limit;
+ /**
+ * After how many seconds of inactivity should
+ * connections time out? Zero for no timeout.
+ */
+ unsigned int connection_timeout;
- /**
- * Daemon's options.
- */
- enum MHD_OPTION options;
+ /**
+ * Maximum number of connections per IP, or 0 for
+ * unlimited.
+ */
+ unsigned int per_ip_connection_limit;
- /**
- * Listen port.
- */
- unsigned short port;
+ /**
+ * Daemon's options.
+ */
+ enum MHD_OPTION options;
-};
+ /**
+ * Listen port.
+ */
+ unsigned short port;
+ };
#endif
Modified: libmicrohttpd/src/examples/Makefile.am
===================================================================
--- libmicrohttpd/src/examples/Makefile.am 2008-05-24 06:59:29 UTC (rev
6875)
+++ libmicrohttpd/src/examples/Makefile.am 2008-05-24 13:59:21 UTC (rev
6876)
@@ -1,10 +1,16 @@
SUBDIRS = .
-INCLUDES = -I$(top_srcdir)/src/include
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
# example programs
-noinst_PROGRAMS = minimal_example querystring_example fileserver_example
fileserver_example_external_select
+noinst_PROGRAMS = \
+https_server_example \
+https_echo_client_example \
+minimal_example \
+querystring_example \
+fileserver_example \
+fileserver_example_external_select
minimal_example_SOURCES = \
minimal_example.c
@@ -21,9 +27,29 @@
fileserver_example_LDADD = \
$(top_builddir)/src/daemon/libmicrohttpd.la
-
fileserver_example_external_select_SOURCES = \
fileserver_example_external_select.c
fileserver_example_external_select_LDADD = \
$(top_builddir)/src/daemon/libmicrohttpd.la
+https_server_example_CPPFLAGS = \
+ $(GNUTLS_CPPFLAGS) \
+ -I$(top_srcdir)/src/daemon
+https_server_example_SOURCES = \
+ https_server_example.c
+https_server_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+https_server_example_LDFLAGS = \
+ -L$(GNUTLS_LIB_PATH) \
+ -lgnutls
+
+https_echo_client_example_CPPFLAGS = \
+ $(GNUTLS_CPPFLAGS) \
+ -I$(top_srcdir)/src/daemon
+https_echo_client_example_SOURCES = \
+ https_echo_client_example.c
+https_echo_client_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+https_echo_client_example_LDFLAGS = \
+ -L$(GNUTLS_LIB_PATH) \
+ -lgnutls
Added: libmicrohttpd/src/examples/https_echo_client_example.c
===================================================================
--- libmicrohttpd/src/examples/https_echo_client_example.c
(rev 0)
+++ libmicrohttpd/src/examples/https_echo_client_example.c 2008-05-24
13:59:21 UTC (rev 6876)
@@ -0,0 +1,153 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ 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.
+
+ 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 libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file https_echo_client.c
+ * @brief a simple echo client to use in conjuction with the echo TLS server.
+ * @author LV-426
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <gnutls/gnutls.h>
+
+#define MAX_BUF 1024
+#define SA struct sockaddr
+#define MSG "GET / HTTP/1.0\r\n\r\n"
+
+extern int tcp_connect (void);
+extern void tcp_close (int sd);
+
+int
+main (int argc, char **argv)
+{
+ int ret, sd, ii, err;
+ gnutls_session_t session;
+ char buffer[MAX_BUF + 1];
+ gnutls_anon_client_credentials_t anoncred;
+
+ struct sockaddr_in servaddr4;
+ const struct sockaddr *servaddr;
+ struct sockaddr_in sa;
+ socklen_t addrlen;
+
+ if (argc < 2)
+ {
+ printf ("Usage : %s SERVER-PORT\n", argv[0]);
+ return 1;
+ }
+
+ gnutls_global_init ();
+
+ gnutls_anon_allocate_client_credentials (&anoncred);
+
+ /* Initialize TLS session */
+ gnutls_init (&session, GNUTLS_CLIENT);
+
+ /* Use default priorities */
+ gnutls_priority_set_direct (session, "PERFORMANCE:+ANON-DH:!ARCFOUR-128",
+ NULL);
+
+ /* put the anonymous credentials to the current session */
+ gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
+
+ sd = socket (AF_INET, SOCK_STREAM, 0);
+ memset (&sa, '\0', sizeof (sa));
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons (atoi (argv[1]));
+ inet_pton (AF_INET, "127.0.0.1", &sa.sin_addr);
+
+ /* connect to the peer */
+ err = connect (sd, (struct sockaddr *) &sa, sizeof (sa));
+ if (err < 0)
+ {
+ fprintf (stderr, "Connect error\n");
+ exit (1);
+ }
+
+ gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
+
+ /* Perform the TLS handshake */
+ ret = gnutls_handshake (session);
+
+ if (ret < 0)
+ {
+ fprintf (stderr, "*** Handshake failed\n");
+ gnutls_perror (ret);
+ goto end;
+ }
+ else
+ {
+ printf ("- Handshake was completed\n");
+ }
+
+ for (;;)
+ {
+ /**/ scanf ("%s", buffer);
+
+ if (strcmp (buffer, "exit") == 0)
+ {
+ gnutls_record_send (session, buffer, strlen (MSG));
+ break;
+ }
+ gnutls_record_send (session, buffer, strlen (MSG));
+
+ ret = gnutls_record_recv (session, buffer, MAX_BUF);
+ if (ret == 0)
+ {
+ printf ("- Peer has closed the TLS connection\n");
+ goto end;
+ }
+ else if (ret < 0)
+ {
+ fprintf (stderr, "*** Error: %s\n", gnutls_strerror (ret));
+ break;
+ }
+
+ printf ("- Received %d bytes: ", ret);
+ for (ii = 0; ii < ret; ii++)
+ {
+ fputc (buffer[ii], stdout);
+ }
+ fputs ("\n", stdout);
+ }
+
+end:
+
+ shutdown (sd, SHUT_RDWR);
+ close (sd);
+
+ gnutls_deinit (session);
+
+ gnutls_anon_free_client_credentials (anoncred);
+
+ gnutls_global_deinit ();
+
+ return 0;
+}
Property changes on: libmicrohttpd/src/examples/https_echo_client_example.c
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: libmicrohttpd/src/examples/https_server_example.c
===================================================================
--- libmicrohttpd/src/examples/https_server_example.c
(rev 0)
+++ libmicrohttpd/src/examples/https_server_example.c 2008-05-24 13:59:21 UTC
(rev 6876)
@@ -0,0 +1,182 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ 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.
+
+ 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 libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file https_server_example.c
+ * @brief a simple echo server using TLS. echo input from client until 'exit'
message is received.
+ * @author LV-426
+ */
+
+#include "config.h"
+#include <microhttpd.h>
+#include "internal.h"
+
+#include <stdlib.h>
+#ifndef MINGW
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+#include <gnutls/gnutls.h>
+
+#define DH_BITS 1024
+#define MAX_BUF 1024
+/* server credintials */
+gnutls_anon_server_credentials_t anoncred;
+
+/* server Diffie-Hellman parameters */
+static gnutls_dh_params_t dh_params;
+
+
+/* Generate Diffie Hellman parameters - for use with DHE kx algorithms. */
+static int
+generate_dh_params (void)
+{
+
+ gnutls_dh_params_init (&dh_params);
+ gnutls_dh_params_generate2 (dh_params, DH_BITS);
+ return 0;
+}
+
+gnutls_session_t
+initialize_tls_session (void)
+{
+ gnutls_session_t session;
+
+ gnutls_init (&session, GNUTLS_SERVER);
+
+ gnutls_priority_set_direct (session, "NORMAL:+ANON-DH", NULL);
+
+ gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
+
+ gnutls_dh_set_prime_bits (session, DH_BITS);
+
+ return session;
+}
+
+/* Accept Policy Callback */
+static int
+TLS_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *upload_data,
+ const char *version, unsigned int *upload_data_size, void **ptr)
+{
+ gnutls_session_t session;
+ static int aptr;
+ struct MHD_Response *response;
+ char buffer[MAX_BUF + 1];
+ int ret;
+
+ printf ("accepted connection from %d\n", connection->addr->sin_addr);
+
+ session = initialize_tls_session ();
+
+ gnutls_transport_set_ptr (session, connection->socket_fd);
+
+ ret = gnutls_handshake (session);
+ if (ret < 0)
+ {
+ /* set connection as closed */
+ connection->socket_fd = 1;
+ gnutls_deinit (session);
+ fprintf (stderr, "*** Handshake has failed (%s)\n\n",
+ gnutls_strerror (ret));
+ return MHD_NO;
+ }
+
+ printf ("TLS Handshake completed\n");
+ connection->state = MHDS_HANDSHAKE_COMPLETE;
+
+ /* simple echo loop. message encryption/decryption is acheived through
'gnutls_record_send'
+ * & gnutls_record_recv calls. */
+ for (;;)
+ {
+ memset (buffer, 0, MAX_BUF + 1);
+ ret = gnutls_record_recv (session, buffer, MAX_BUF);
+
+ if (ret < 0)
+ {
+ fprintf (stderr, "\n*** Received corrupted "
+ "data(%d). Closing the connection.\n\n", ret);
+ break;
+ }
+ else if (ret >= 0)
+ {
+ if (strcmp (buffer, "exit") == 0)
+ {
+ printf ("\n- Peer has closed the GNUTLS connection\n");
+ break;
+ }
+ else
+ {
+ /* echo data back to the client */
+ gnutls_record_send (session, buffer, strlen (buffer));
+ }
+ }
+ }
+ printf ("\n");
+
+ /* mark connection as closed */
+ connection->socket_fd = -1;
+
+ gnutls_deinit (session);
+
+ return ret;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ struct MHD_Daemon *daemon;
+ struct MHD_Daemon *TLS_daemon;
+
+ /* look for HTTPS port argument */
+ if (argc < 4)
+ {
+ printf ("Usage : %s HTTP-PORT SECONDS-TO-RUN HTTPS-PORT\n", argv[0]);
+ return 1;
+ }
+
+ gnutls_global_init ();
+
+ gnutls_anon_allocate_server_credentials (&anoncred);
+
+ generate_dh_params ();
+
+ gnutls_anon_set_server_dh_params (anoncred, dh_params);
+
+ TLS_daemon = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION
+ | MHD_USE_DEBUG | MHD_USE_SSL,
+ atoi (argv[3]), NULL, NULL, &TLS_echo, NULL,
+ MHD_OPTION_END);
+
+ if (TLS_daemon == NULL)
+ return 1;
+ sleep (atoi (argv[2]));
+
+ MHD_stop_daemon (daemon);
+
+ gnutls_anon_free_server_credentials (anoncred);
+
+ gnutls_global_deinit ();
+ return 0;
+}
Property changes on: libmicrohttpd/src/examples/https_server_example.c
___________________________________________________________________
Name: svn:mime-type
+ text/plain
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r6876 - in libmicrohttpd: . src/daemon src/examples,
gnunet <=