aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-03-04 09:33:32 +0000
committerChristian Grothoff <christian@grothoff.org>2011-03-04 09:33:32 +0000
commitf7ae5a3412f828cb9a7622f21b28b584b65adc32 (patch)
treebea91693cf3ab1e18d14f86d8434b331193b1c3f
parent45a0a30893f77a38a8add8a64c3650387840a335 (diff)
downloadlibmicrohttpd-f7ae5a3412f828cb9a7622f21b28b584b65adc32.tar.gz
libmicrohttpd-f7ae5a3412f828cb9a7622f21b28b584b65adc32.zip
adding API to handle #1661 (allow externally created connections)
-rw-r--r--ChangeLog6
-rw-r--r--configure.ac4
-rw-r--r--doc/microhttpd-tutorial.texi4
-rw-r--r--doc/microhttpd.texi32
-rw-r--r--src/daemon/daemon.c146
-rw-r--r--src/include/microhttpd.h29
6 files changed, 163 insertions, 58 deletions
diff --git a/ChangeLog b/ChangeLog
index fa0da138..2a67dd67 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
1Fri Mar 4 10:24:04 CET 2011
2 Added new API to allow MHD server to initiate connection to
3 client (special use-case for servers behind NAT), thereby
4 addressing #1661 (externally created connections).
5 Releasing libmicrohttpd 0.9.8. -CG
6
1Fri Mar 4 10:07:18 CET 2011 7Fri Mar 4 10:07:18 CET 2011
2 Avoid using a pipe for signalling as well, just use server 8 Avoid using a pipe for signalling as well, just use server
3 socket shutdown (also for thread-per-connection). -CG 9 socket shutdown (also for thread-per-connection). -CG
diff --git a/configure.ac b/configure.ac
index 1b136cf6..b79ee827 100644
--- a/configure.ac
+++ b/configure.ac
@@ -27,9 +27,9 @@ AM_CONFIG_HEADER([MHD_config.h])
27AC_CONFIG_MACRO_DIR([m4]) 27AC_CONFIG_MACRO_DIR([m4])
28AH_TOP([#define _GNU_SOURCE 1]) 28AH_TOP([#define _GNU_SOURCE 1])
29 29
30LIB_VERSION_CURRENT=15 30LIB_VERSION_CURRENT=16
31LIB_VERSION_REVISION=0 31LIB_VERSION_REVISION=0
32LIB_VERSION_AGE=5 32LIB_VERSION_AGE=6
33AC_SUBST(LIB_VERSION_CURRENT) 33AC_SUBST(LIB_VERSION_CURRENT)
34AC_SUBST(LIB_VERSION_REVISION) 34AC_SUBST(LIB_VERSION_REVISION)
35AC_SUBST(LIB_VERSION_AGE) 35AC_SUBST(LIB_VERSION_AGE)
diff --git a/doc/microhttpd-tutorial.texi b/doc/microhttpd-tutorial.texi
index b4f19a34..020b1e2a 100644
--- a/doc/microhttpd-tutorial.texi
+++ b/doc/microhttpd-tutorial.texi
@@ -3,8 +3,8 @@
3@setfilename microhttpd-tutorial.info 3@setfilename microhttpd-tutorial.info
4@set UPDATED 28 Feb 2010 4@set UPDATED 28 Feb 2010
5@set UPDATED-MONTH Feb 2010 5@set UPDATED-MONTH Feb 2010
6@set EDITION 0.9.7 6@set EDITION 0.9.8
7@set VERSION 0.9.7 7@set VERSION 0.9.8
8@settitle A tutorial for GNU libmicrohttpd 8@settitle A tutorial for GNU libmicrohttpd
9 9
10@dircategory GNU Libraries 10@dircategory GNU Libraries
diff --git a/doc/microhttpd.texi b/doc/microhttpd.texi
index 86ed2481..ab8c5c9e 100644
--- a/doc/microhttpd.texi
+++ b/doc/microhttpd.texi
@@ -9,7 +9,7 @@ header file @file{microhttpd.h}.
9 9
10@noindent 10@noindent
11 11
12Copyright @copyright{} 2007, 2008, 2009, 2010 Christian Grothoff 12Copyright @copyright{} 2007, 2008, 2009, 2010, 2011 Christian Grothoff
13 13
14@quotation 14@quotation
15Permission is granted to copy, distribute and/or modify this document 15Permission is granted to copy, distribute and/or modify this document
@@ -1100,6 +1100,36 @@ started with the right options for this call.
1100@end deftypefun 1100@end deftypefun
1101 1101
1102 1102
1103@deftypefun void MHD_add_connection (struct MHD_Daemon *daemon, int client_socket, const struct sockaddr *addr, socklen_t addrlen)
1104Add another client connection to the set of connections
1105managed by MHD. This API is usually not needed (since
1106MHD will accept inbound connections on the server socket).
1107Use this API in special cases, for example if your HTTP
1108server is behind NAT and needs to connect out to the
1109HTTP client.
1110
1111The given client socket will be managed (and closed!) by MHD after
1112this call and must no longer be used directly by the application
1113afterwards.
1114
1115@table @var
1116@item daemon
1117daemon that manages the connection
1118@item client_socket
1119socket to manage (MHD will expect to receive an HTTP request from this socket next).
1120@item addr
1121IP address of the client
1122@item addrlen
1123number of bytes in addr
1124@end table
1125
1126This function will return @code{MHD_YES} on success,
1127@code{MHD_NO} if this daemon could
1128not handle the connection (i.e. malloc failed, etc).
1129The socket will be closed in any case.
1130@end deftypefun
1131
1132
1103@c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1133@c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1104 1134
1105@c ----------------------------------------------------------- 1135@c -----------------------------------------------------------
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c
index f12f8207..54b73f9b 100644
--- a/src/daemon/daemon.c
+++ b/src/daemon/daemon.c
@@ -860,60 +860,52 @@ create_thread (pthread_t * thread,
860 860
861 861
862/** 862/**
863 * Accept an incoming connection and create the MHD_Connection object for 863 * Add another client connection to the set of connections
864 * it. This function also enforces policy by way of checking with the 864 * managed by MHD. This API is usually not needed (since
865 * accept policy callback. 865 * MHD will accept inbound connections on the server socket).
866 * 866 * Use this API in special cases, for example if your HTTP
867 * @param daemon handle with the listen socket 867 * server is behind NAT and needs to connect out to the
868 * @return MHD_YES on success 868 * HTTP client.
869 *
870 * The given client socket will be managed (and closed!) by MHD after
871 * this call and must no longer be used directly by the application
872 * afterwards.
873 *
874 * Per-IP connection limits are ignored when using this API.
875 *
876 * @param daemon daemon that manages the connection
877 * @param client_socket socket to manage (MHD will expect
878 * to receive an HTTP request from this socket next).
879 * @param addr IP address of the client
880 * @param addrlen number of bytes in addr
881 * @return MHD_YES on success, MHD_NO if this daemon could
882 * not handle the connection (i.e. malloc failed, etc).
883 * The socket will be closed in any case.
869 */ 884 */
870static int 885int
871MHD_accept_connection (struct MHD_Daemon *daemon) 886MHD_add_connection (struct MHD_Daemon *daemon,
887 int client_socket,
888 const struct sockaddr *addr,
889 socklen_t addrlen)
872{ 890{
873 struct MHD_Connection *connection; 891 struct MHD_Connection *connection;
874#if HAVE_INET6
875 struct sockaddr_in6 addrstorage;
876#else
877 struct sockaddr_in addrstorage;
878#endif
879 struct sockaddr *addr = (struct sockaddr *) &addrstorage;
880 socklen_t addrlen;
881 int s;
882 int res_thread_create; 892 int res_thread_create;
883#if OSX 893#if OSX
884 static int on = 1; 894 static int on = 1;
885#endif 895#endif
886 896
887 addrlen = sizeof (addrstorage);
888 memset (addr, 0, sizeof (addrstorage));
889
890 s = ACCEPT (daemon->socket_fd, addr, &addrlen);
891 if ((s == -1) || (addrlen <= 0))
892 {
893#if HAVE_MESSAGES
894 /* This could be a common occurance with multiple worker threads */
895 if ((EAGAIN != errno) && (EWOULDBLOCK != errno))
896 MHD_DLOG (daemon, "Error accepting connection: %s\n", STRERROR (errno));
897#endif
898 if (s != -1)
899 {
900 SHUTDOWN (s, SHUT_RDWR);
901 CLOSE (s);
902 /* just in case */
903 }
904 return MHD_NO;
905 }
906#ifndef WINDOWS 897#ifndef WINDOWS
907 if ( (s >= FD_SETSIZE) && 898 if ( (client_socket >= FD_SETSIZE) &&
908 (0 == (daemon->options & MHD_USE_POLL)) ) 899 (0 == (daemon->options & MHD_USE_POLL)) )
909 { 900 {
910#if HAVE_MESSAGES 901#if HAVE_MESSAGES
911 MHD_DLOG (daemon, 902 MHD_DLOG (daemon,
912 "Socket descriptor larger than FD_SETSIZE: %d > %d\n", 903 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
913 s, 904 client_socket,
914 FD_SETSIZE); 905 FD_SETSIZE);
915#endif 906#endif
916 CLOSE (s); 907 SHUTDOWN (client_socket, SHUT_RDWR);
908 CLOSE (client_socket);
917 return MHD_NO; 909 return MHD_NO;
918 } 910 }
919#endif 911#endif
@@ -932,8 +924,8 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
932 MHD_DLOG (daemon, 924 MHD_DLOG (daemon,
933 "Server reached connection limit (closing inbound connection)\n"); 925 "Server reached connection limit (closing inbound connection)\n");
934#endif 926#endif
935 SHUTDOWN (s, SHUT_RDWR); 927 SHUTDOWN (client_socket, SHUT_RDWR);
936 CLOSE (s); 928 CLOSE (client_socket);
937 return MHD_NO; 929 return MHD_NO;
938 } 930 }
939 931
@@ -946,11 +938,12 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
946 MHD_DLOG (daemon, "Connection rejected, closing connection\n"); 938 MHD_DLOG (daemon, "Connection rejected, closing connection\n");
947#endif 939#endif
948#endif 940#endif
949 SHUTDOWN (s, SHUT_RDWR); 941 SHUTDOWN (client_socket, SHUT_RDWR);
950 CLOSE (s); 942 CLOSE (client_socket);
951 MHD_ip_limit_del (daemon, addr, addrlen); 943 MHD_ip_limit_del (daemon, addr, addrlen);
952 return MHD_YES; 944 return MHD_YES;
953 } 945 }
946
954#if OSX 947#if OSX
955#ifdef SOL_SOCKET 948#ifdef SOL_SOCKET
956#ifdef SO_NOSIGPIPE 949#ifdef SO_NOSIGPIPE
@@ -958,14 +951,15 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
958#endif 951#endif
959#endif 952#endif
960#endif 953#endif
954
961 connection = malloc (sizeof (struct MHD_Connection)); 955 connection = malloc (sizeof (struct MHD_Connection));
962 if (NULL == connection) 956 if (NULL == connection)
963 { 957 {
964#if HAVE_MESSAGES 958#if HAVE_MESSAGES
965 MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno)); 959 MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
966#endif 960#endif
967 SHUTDOWN (s, SHUT_RDWR); 961 SHUTDOWN (client_socket, SHUT_RDWR);
968 CLOSE (s); 962 CLOSE (client_socket);
969 MHD_ip_limit_del (daemon, addr, addrlen); 963 MHD_ip_limit_del (daemon, addr, addrlen);
970 return MHD_NO; 964 return MHD_NO;
971 } 965 }
@@ -977,15 +971,15 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
977#if HAVE_MESSAGES 971#if HAVE_MESSAGES
978 MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno)); 972 MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
979#endif 973#endif
980 SHUTDOWN (s, SHUT_RDWR); 974 SHUTDOWN (client_socket, SHUT_RDWR);
981 CLOSE (s); 975 CLOSE (client_socket);
982 MHD_ip_limit_del (daemon, addr, addrlen); 976 MHD_ip_limit_del (daemon, addr, addrlen);
983 free (connection); 977 free (connection);
984 return MHD_NO; 978 return MHD_NO;
985 } 979 }
986 memcpy (connection->addr, addr, addrlen); 980 memcpy (connection->addr, addr, addrlen);
987 connection->addr_len = addrlen; 981 connection->addr_len = addrlen;
988 connection->socket_fd = s; 982 connection->socket_fd = client_socket;
989 connection->daemon = daemon; 983 connection->daemon = daemon;
990 connection->last_activity = time (NULL); 984 connection->last_activity = time (NULL);
991 985
@@ -1022,8 +1016,8 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
1022 "Failed to setup TLS credentials: unknown credential type %d\n", 1016 "Failed to setup TLS credentials: unknown credential type %d\n",
1023 connection->daemon->cred_type); 1017 connection->daemon->cred_type);
1024#endif 1018#endif
1025 SHUTDOWN (s, SHUT_RDWR); 1019 SHUTDOWN (client_socket, SHUT_RDWR);
1026 CLOSE (s); 1020 CLOSE (client_socket);
1027 MHD_ip_limit_del (daemon, addr, addrlen); 1021 MHD_ip_limit_del (daemon, addr, addrlen);
1028 free (connection->addr); 1022 free (connection->addr);
1029 free (connection); 1023 free (connection);
@@ -1062,8 +1056,8 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
1062 MHD_DLOG (daemon, "Failed to create a thread: %s\n", 1056 MHD_DLOG (daemon, "Failed to create a thread: %s\n",
1063 STRERROR (res_thread_create)); 1057 STRERROR (res_thread_create));
1064#endif 1058#endif
1065 SHUTDOWN (s, SHUT_RDWR); 1059 SHUTDOWN (client_socket, SHUT_RDWR);
1066 CLOSE (s); 1060 CLOSE (client_socket);
1067 MHD_ip_limit_del (daemon, addr, addrlen); 1061 MHD_ip_limit_del (daemon, addr, addrlen);
1068 free (connection->addr); 1062 free (connection->addr);
1069 free (connection); 1063 free (connection);
@@ -1073,7 +1067,55 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
1073 connection->next = daemon->connections; 1067 connection->next = daemon->connections;
1074 daemon->connections = connection; 1068 daemon->connections = connection;
1075 daemon->max_connections--; 1069 daemon->max_connections--;
1076 return MHD_YES; 1070 return MHD_YES;
1071}
1072
1073
1074/**
1075 * Accept an incoming connection and create the MHD_Connection object for
1076 * it. This function also enforces policy by way of checking with the
1077 * accept policy callback.
1078 *
1079 * @param daemon handle with the listen socket
1080 * @return MHD_YES on success
1081 */
1082static int
1083MHD_accept_connection (struct MHD_Daemon *daemon)
1084{
1085#if HAVE_INET6
1086 struct sockaddr_in6 addrstorage;
1087#else
1088 struct sockaddr_in addrstorage;
1089#endif
1090 struct sockaddr *addr = (struct sockaddr *) &addrstorage;
1091 socklen_t addrlen;
1092 int s;
1093
1094 addrlen = sizeof (addrstorage);
1095 memset (addr, 0, sizeof (addrstorage));
1096 s = ACCEPT (daemon->socket_fd, addr, &addrlen);
1097 if ((s == -1) || (addrlen <= 0))
1098 {
1099#if HAVE_MESSAGES
1100 /* This could be a common occurance with multiple worker threads */
1101 if ((EAGAIN != errno) && (EWOULDBLOCK != errno))
1102 MHD_DLOG (daemon, "Error accepting connection: %s\n", STRERROR (errno));
1103#endif
1104 if (s != -1)
1105 {
1106 SHUTDOWN (s, SHUT_RDWR);
1107 CLOSE (s);
1108 /* just in case */
1109 }
1110 return MHD_NO;
1111 }
1112#if HAVE_MESSAGES
1113#if DEBUG_CONNECT
1114 MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
1115#endif
1116#endif
1117 return MHD_add_connection (daemon, s,
1118 addr, addrlen);
1077} 1119}
1078 1120
1079/** 1121/**
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index 3f3b61de..9537c962 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -106,7 +106,7 @@ extern "C"
106/** 106/**
107 * Current version of the library. 107 * Current version of the library.
108 */ 108 */
109#define MHD_VERSION 0x00090703 109#define MHD_VERSION 0x00090800
110 110
111/** 111/**
112 * MHD-internal return code for "YES". 112 * MHD-internal return code for "YES".
@@ -1035,6 +1035,33 @@ void MHD_stop_daemon (struct MHD_Daemon *daemon);
1035 1035
1036 1036
1037/** 1037/**
1038 * Add another client connection to the set of connections
1039 * managed by MHD. This API is usually not needed (since
1040 * MHD will accept inbound connections on the server socket).
1041 * Use this API in special cases, for example if your HTTP
1042 * server is behind NAT and needs to connect out to the
1043 * HTTP client.
1044 *
1045 * The given client socket will be managed (and closed!) by MHD after
1046 * this call and must no longer be used directly by the application
1047 * afterwards.
1048 *
1049 * @param daemon daemon that manages the connection
1050 * @param client_socket socket to manage (MHD will expect
1051 * to receive an HTTP request from this socket next).
1052 * @param addr IP address of the client
1053 * @param addrlen number of bytes in addr
1054 * @return MHD_YES on success, MHD_NO if this daemon could
1055 * not handle the connection (i.e. malloc failed, etc).
1056 * The socket will be closed in any case.
1057 */
1058int MHD_add_connection (struct MHD_Daemon *daemon,
1059 int client_socket,
1060 const struct sockaddr *addr,
1061 socklen_t addrlen);
1062
1063
1064/**
1038 * Obtain the select sets for this daemon. 1065 * Obtain the select sets for this daemon.
1039 * 1066 *
1040 * @param daemon daemon to get sets from 1067 * @param daemon daemon to get sets from