adding API to handle #1661 (allow externally created connections)

This commit is contained in:
Christian Grothoff
2011-03-04 09:33:32 +00:00
parent 45a0a30893
commit f7ae5a3412
6 changed files with 163 additions and 58 deletions
+6
View File
@@ -1,3 +1,9 @@
Fri Mar 4 10:24:04 CET 2011
Added new API to allow MHD server to initiate connection to
client (special use-case for servers behind NAT), thereby
addressing #1661 (externally created connections).
Releasing libmicrohttpd 0.9.8. -CG
Fri Mar 4 10:07:18 CET 2011
Avoid using a pipe for signalling as well, just use server
socket shutdown (also for thread-per-connection). -CG
+2 -2
View File
@@ -27,9 +27,9 @@ AM_CONFIG_HEADER([MHD_config.h])
AC_CONFIG_MACRO_DIR([m4])
AH_TOP([#define _GNU_SOURCE 1])
LIB_VERSION_CURRENT=15
LIB_VERSION_CURRENT=16
LIB_VERSION_REVISION=0
LIB_VERSION_AGE=5
LIB_VERSION_AGE=6
AC_SUBST(LIB_VERSION_CURRENT)
AC_SUBST(LIB_VERSION_REVISION)
AC_SUBST(LIB_VERSION_AGE)
+2 -2
View File
@@ -3,8 +3,8 @@
@setfilename microhttpd-tutorial.info
@set UPDATED 28 Feb 2010
@set UPDATED-MONTH Feb 2010
@set EDITION 0.9.7
@set VERSION 0.9.7
@set EDITION 0.9.8
@set VERSION 0.9.8
@settitle A tutorial for GNU libmicrohttpd
@dircategory GNU Libraries
+31 -1
View File
@@ -9,7 +9,7 @@ header file @file{microhttpd.h}.
@noindent
Copyright @copyright{} 2007, 2008, 2009, 2010 Christian Grothoff
Copyright @copyright{} 2007, 2008, 2009, 2010, 2011 Christian Grothoff
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -1100,6 +1100,36 @@ started with the right options for this call.
@end deftypefun
@deftypefun void MHD_add_connection (struct MHD_Daemon *daemon, int client_socket, const struct sockaddr *addr, socklen_t addrlen)
Add another client connection to the set of connections
managed by MHD. This API is usually not needed (since
MHD will accept inbound connections on the server socket).
Use this API in special cases, for example if your HTTP
server is behind NAT and needs to connect out to the
HTTP client.
The given client socket will be managed (and closed!) by MHD after
this call and must no longer be used directly by the application
afterwards.
@table @var
@item daemon
daemon that manages the connection
@item client_socket
socket to manage (MHD will expect to receive an HTTP request from this socket next).
@item addr
IP address of the client
@item addrlen
number of bytes in addr
@end table
This function will return @code{MHD_YES} on success,
@code{MHD_NO} if this daemon could
not handle the connection (i.e. malloc failed, etc).
The socket will be closed in any case.
@end deftypefun
@c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@c -----------------------------------------------------------
+94 -52
View File
@@ -860,60 +860,52 @@ create_thread (pthread_t * thread,
/**
* 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.
*
* @param daemon handle with the listen socket
* @return MHD_YES on success
* Add another client connection to the set of connections
* managed by MHD. This API is usually not needed (since
* MHD will accept inbound connections on the server socket).
* Use this API in special cases, for example if your HTTP
* server is behind NAT and needs to connect out to the
* HTTP client.
*
* The given client socket will be managed (and closed!) by MHD after
* this call and must no longer be used directly by the application
* afterwards.
*
* Per-IP connection limits are ignored when using this API.
*
* @param daemon daemon that manages the connection
* @param client_socket socket to manage (MHD will expect
* to receive an HTTP request from this socket next).
* @param addr IP address of the client
* @param addrlen number of bytes in addr
* @return MHD_YES on success, MHD_NO if this daemon could
* not handle the connection (i.e. malloc failed, etc).
* The socket will be closed in any case.
*/
static int
MHD_accept_connection (struct MHD_Daemon *daemon)
int
MHD_add_connection (struct MHD_Daemon *daemon,
int client_socket,
const struct sockaddr *addr,
socklen_t addrlen)
{
struct MHD_Connection *connection;
#if HAVE_INET6
struct sockaddr_in6 addrstorage;
#else
struct sockaddr_in addrstorage;
#endif
struct sockaddr *addr = (struct sockaddr *) &addrstorage;
socklen_t addrlen;
int s;
int res_thread_create;
#if OSX
static int on = 1;
#endif
addrlen = sizeof (addrstorage);
memset (addr, 0, sizeof (addrstorage));
s = ACCEPT (daemon->socket_fd, addr, &addrlen);
if ((s == -1) || (addrlen <= 0))
{
#if HAVE_MESSAGES
/* This could be a common occurance with multiple worker threads */
if ((EAGAIN != errno) && (EWOULDBLOCK != 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;
}
#ifndef WINDOWS
if ( (s >= FD_SETSIZE) &&
if ( (client_socket >= FD_SETSIZE) &&
(0 == (daemon->options & MHD_USE_POLL)) )
{
#if HAVE_MESSAGES
MHD_DLOG (daemon,
"Socket descriptor larger than FD_SETSIZE: %d > %d\n",
s,
client_socket,
FD_SETSIZE);
#endif
CLOSE (s);
SHUTDOWN (client_socket, SHUT_RDWR);
CLOSE (client_socket);
return MHD_NO;
}
#endif
@@ -932,8 +924,8 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
MHD_DLOG (daemon,
"Server reached connection limit (closing inbound connection)\n");
#endif
SHUTDOWN (s, SHUT_RDWR);
CLOSE (s);
SHUTDOWN (client_socket, SHUT_RDWR);
CLOSE (client_socket);
return MHD_NO;
}
@@ -946,11 +938,12 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
MHD_DLOG (daemon, "Connection rejected, closing connection\n");
#endif
#endif
SHUTDOWN (s, SHUT_RDWR);
CLOSE (s);
SHUTDOWN (client_socket, SHUT_RDWR);
CLOSE (client_socket);
MHD_ip_limit_del (daemon, addr, addrlen);
return MHD_YES;
}
#if OSX
#ifdef SOL_SOCKET
#ifdef SO_NOSIGPIPE
@@ -958,14 +951,15 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
#endif
#endif
#endif
connection = malloc (sizeof (struct MHD_Connection));
if (NULL == connection)
{
#if HAVE_MESSAGES
MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
#endif
SHUTDOWN (s, SHUT_RDWR);
CLOSE (s);
SHUTDOWN (client_socket, SHUT_RDWR);
CLOSE (client_socket);
MHD_ip_limit_del (daemon, addr, addrlen);
return MHD_NO;
}
@@ -977,15 +971,15 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
#if HAVE_MESSAGES
MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
#endif
SHUTDOWN (s, SHUT_RDWR);
CLOSE (s);
SHUTDOWN (client_socket, SHUT_RDWR);
CLOSE (client_socket);
MHD_ip_limit_del (daemon, addr, addrlen);
free (connection);
return MHD_NO;
}
memcpy (connection->addr, addr, addrlen);
connection->addr_len = addrlen;
connection->socket_fd = s;
connection->socket_fd = client_socket;
connection->daemon = daemon;
connection->last_activity = time (NULL);
@@ -1022,8 +1016,8 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
"Failed to setup TLS credentials: unknown credential type %d\n",
connection->daemon->cred_type);
#endif
SHUTDOWN (s, SHUT_RDWR);
CLOSE (s);
SHUTDOWN (client_socket, SHUT_RDWR);
CLOSE (client_socket);
MHD_ip_limit_del (daemon, addr, addrlen);
free (connection->addr);
free (connection);
@@ -1062,8 +1056,8 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
MHD_DLOG (daemon, "Failed to create a thread: %s\n",
STRERROR (res_thread_create));
#endif
SHUTDOWN (s, SHUT_RDWR);
CLOSE (s);
SHUTDOWN (client_socket, SHUT_RDWR);
CLOSE (client_socket);
MHD_ip_limit_del (daemon, addr, addrlen);
free (connection->addr);
free (connection);
@@ -1073,7 +1067,55 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
connection->next = daemon->connections;
daemon->connections = connection;
daemon->max_connections--;
return MHD_YES;
return MHD_YES;
}
/**
* 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.
*
* @param daemon handle with the listen socket
* @return MHD_YES on success
*/
static int
MHD_accept_connection (struct MHD_Daemon *daemon)
{
#if HAVE_INET6
struct sockaddr_in6 addrstorage;
#else
struct sockaddr_in addrstorage;
#endif
struct sockaddr *addr = (struct sockaddr *) &addrstorage;
socklen_t addrlen;
int s;
addrlen = sizeof (addrstorage);
memset (addr, 0, sizeof (addrstorage));
s = ACCEPT (daemon->socket_fd, addr, &addrlen);
if ((s == -1) || (addrlen <= 0))
{
#if HAVE_MESSAGES
/* This could be a common occurance with multiple worker threads */
if ((EAGAIN != errno) && (EWOULDBLOCK != 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 HAVE_MESSAGES
#if DEBUG_CONNECT
MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
#endif
#endif
return MHD_add_connection (daemon, s,
addr, addrlen);
}
/**
+28 -1
View File
@@ -106,7 +106,7 @@ extern "C"
/**
* Current version of the library.
*/
#define MHD_VERSION 0x00090703
#define MHD_VERSION 0x00090800
/**
* MHD-internal return code for "YES".
@@ -1034,6 +1034,33 @@ struct MHD_Daemon *MHD_start_daemon (unsigned int flags,
void MHD_stop_daemon (struct MHD_Daemon *daemon);
/**
* Add another client connection to the set of connections
* managed by MHD. This API is usually not needed (since
* MHD will accept inbound connections on the server socket).
* Use this API in special cases, for example if your HTTP
* server is behind NAT and needs to connect out to the
* HTTP client.
*
* The given client socket will be managed (and closed!) by MHD after
* this call and must no longer be used directly by the application
* afterwards.
*
* @param daemon daemon that manages the connection
* @param client_socket socket to manage (MHD will expect
* to receive an HTTP request from this socket next).
* @param addr IP address of the client
* @param addrlen number of bytes in addr
* @return MHD_YES on success, MHD_NO if this daemon could
* not handle the connection (i.e. malloc failed, etc).
* The socket will be closed in any case.
*/
int MHD_add_connection (struct MHD_Daemon *daemon,
int client_socket,
const struct sockaddr *addr,
socklen_t addrlen);
/**
* Obtain the select sets for this daemon.
*