summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Graveley <alex@ximian.com>2001-02-28 22:27:58 +0000
committeralex <alex>2001-02-28 22:27:58 +0000
commit5ea4f1603bf282a30a22fef77b4a486373b51ebf (patch)
treeb0afb2f30bd779cabd37f88cceeadbdb37b71a57
parentf2016ef52170cedff0e8110e9150610357da764a (diff)
downloadlibsoup-5ea4f1603bf282a30a22fef77b4a486373b51ebf.tar.gz
glib idle callback which calls waitpid (nonblockingously) on all the
2001-02-28 Alex Graveley <alex@ximian.com> * src/soup-core/soup-ssl.c (soup_ssl_idle_waitpid): glib idle callback which calls waitpid (nonblockingously) on all the soup-ssl-proxy children to make sure their resources are freed. (soup_ssl_get_iochannel): execute soup-ssl-proxy, setting up STDIN and STDOUT to point to the fd we will return a GIOChannel for, also passing the security policy and the destination socket fd number in the environments SECURITY_POLICY and SOCKFD, respectively. * src/soup-core/soup-ssl-proxy.c: Created. This is a small SSL proxy executable, licensed GPL, which allows us to use OpenSSL and NSS without requiring applications which link with libsoup to have to comply with the licenses of those SSL libraries. * src/soup-core/soup-server.c (soup_server_register): add handler to list. * src/soup-core/soup-queue.c (soup_queue_write_async): ignore SIGPIPE and handle errno. * src/soup-core/soup-misc.c (soup_set_security_policy): move from soup-ssl.c. (soup_get_security_policy): add. * src/soup-core/soup-context.c (soup_connection_get_iochannel): setup TCP socket before getting an SSL wrapper channel. * src/soup-core/Makefile.am (INCLUDES): add -DBINDIR (libsoup_la_SOURCES): remove ssl backends (soup_ssl_proxy_SOURCES): create soup-ssl-proxy * src/soup-core/.cvsignore: add soup-ssl-proxy
-rw-r--r--ChangeLog35
-rw-r--r--libsoup/.cvsignore1
-rw-r--r--libsoup/Makefile.am14
-rw-r--r--libsoup/soup-context.c4
-rw-r--r--libsoup/soup-misc.c16
-rw-r--r--libsoup/soup-misc.h18
-rw-r--r--libsoup/soup-queue.c115
-rw-r--r--libsoup/soup-server.c4
-rw-r--r--libsoup/soup-server.h9
-rw-r--r--libsoup/soup-socks.c2
-rw-r--r--libsoup/soup-ssl.c133
11 files changed, 219 insertions, 132 deletions
diff --git a/ChangeLog b/ChangeLog
index 46625d63..ebb96070 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+2001-02-28 Alex Graveley <alex@ximian.com>
+
+ * src/soup-core/soup-ssl.c (soup_ssl_idle_waitpid): glib idle
+ callback which calls waitpid (nonblockingously) on all the
+ soup-ssl-proxy children to make sure their resources are freed.
+ (soup_ssl_get_iochannel): execute soup-ssl-proxy, setting up STDIN
+ and STDOUT to point to the fd we will return a GIOChannel for,
+ also passing the security policy and the destination socket fd
+ number in the environments SECURITY_POLICY and SOCKFD,
+ respectively.
+
+ * src/soup-core/soup-ssl-proxy.c: Created. This is a small SSL
+ proxy executable, licensed GPL, which allows us to use OpenSSL and
+ NSS without requiring applications which link with libsoup to have
+ to comply with the licenses of those SSL libraries.
+
+ * src/soup-core/soup-server.c (soup_server_register): add handler
+ to list.
+
+ * src/soup-core/soup-queue.c (soup_queue_write_async): ignore
+ SIGPIPE and handle errno.
+
+ * src/soup-core/soup-misc.c (soup_set_security_policy): move from
+ soup-ssl.c.
+ (soup_get_security_policy): add.
+
+ * src/soup-core/soup-context.c (soup_connection_get_iochannel):
+ setup TCP socket before getting an SSL wrapper channel.
+
+ * src/soup-core/Makefile.am (INCLUDES): add -DBINDIR
+ (libsoup_la_SOURCES): remove ssl backends
+ (soup_ssl_proxy_SOURCES): create soup-ssl-proxy
+
+ * src/soup-core/.cvsignore: add soup-ssl-proxy
+
2001-02-28 Dick Porter <dick@ximian.com>
* src/soup-wsdl/wsdl-trace.[ch]: New file of better debugging routines.
diff --git a/libsoup/.cvsignore b/libsoup/.cvsignore
index 69fb0bd8..20ed541c 100644
--- a/libsoup/.cvsignore
+++ b/libsoup/.cvsignore
@@ -4,3 +4,4 @@
.libs
Makefile
Makefile.in
+soup-ssl-proxy
diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am
index af81fee6..554964e9 100644
--- a/libsoup/Makefile.am
+++ b/libsoup/Makefile.am
@@ -5,6 +5,7 @@
INCLUDES = \
-DG_LOG_DOMAIN=\"SOUP\" \
-DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DBINDIR=\"$(bindir)\" \
@SOUP_DEBUG_FLAGS@
soupincludedir = $(includedir)/soup
@@ -19,10 +20,6 @@ libsoup_la_SOURCES = \
soup-headers.c \
soup-message.c \
soup-misc.c \
- soup-nss.h \
- soup-nss.c \
- soup-openssl.h \
- soup-openssl.c \
soup-private.h \
soup-queue.c \
soup-serializer.c \
@@ -43,5 +40,14 @@ soupinclude_HEADERS = \
soup-server.h \
soup-uri.h
+bin_PROGRAMS = soup-ssl-proxy
+
+soup_ssl_proxy_SOURCES = \
+ soup-nss.h \
+ soup-nss.c \
+ soup-openssl.h \
+ soup-openssl.c \
+ soup-ssl-proxy.c
+
EXTRA_DIST =
diff --git a/libsoup/soup-context.c b/libsoup/soup-context.c
index db2643d6..2c3349fa 100644
--- a/libsoup/soup-context.c
+++ b/libsoup/soup-context.c
@@ -407,10 +407,10 @@ soup_connection_get_iochannel (SoupConnection *conn)
if (!conn->channel) {
conn->channel = gnet_tcp_socket_get_iochannel (conn->socket);
+ soup_connection_setup_socket (conn->channel);
+
if (conn->context->protocol == SOUP_PROTOCOL_SHTTP)
conn->channel = soup_ssl_get_iochannel (conn->channel);
-
- soup_connection_setup_socket (conn->channel);
} else
g_io_channel_ref (conn->channel);
diff --git a/libsoup/soup-misc.c b/libsoup/soup-misc.c
index 6a7f1ce1..cf1f629b 100644
--- a/libsoup/soup-misc.c
+++ b/libsoup/soup-misc.c
@@ -24,6 +24,8 @@ static guint max_connections = 0;
static SoupContext *proxy_context = NULL;
+static SoupSecurityPolicy ssl_security_level = SOUP_SECURITY_DOMESTIC;
+
void
soup_set_proxy (SoupContext *context)
{
@@ -52,6 +54,18 @@ soup_get_connection_limit (void)
return max_connections;
}
+void
+soup_set_security_policy (SoupSecurityPolicy policy)
+{
+ ssl_security_level = policy;
+}
+
+SoupSecurityPolicy
+soup_get_security_policy (void)
+{
+ return ssl_security_level;
+}
+
guint
soup_str_case_hash (gconstpointer key)
@@ -325,7 +339,7 @@ soup_load_config (gchar *config_file)
}
/* Load system global config */
- soup_load_config_internal (SYSCONFDIR G_DIR_SEPARATOR_S "/souprc",
+ soup_load_config_internal (SYSCONFDIR G_DIR_SEPARATOR_S "souprc",
TRUE);
/* Load requested file or user local config */
diff --git a/libsoup/soup-misc.h b/libsoup/soup-misc.h
index 4b699988..a2b3ac40 100644
--- a/libsoup/soup-misc.h
+++ b/libsoup/soup-misc.h
@@ -17,15 +17,15 @@
#include "soup-message.h"
#include "soup-uri.h"
-void soup_set_proxy (SoupContext *ctx);
+void soup_load_config (gchar *config_file);
-SoupContext *soup_get_proxy (void);
+void soup_set_proxy (SoupContext *ctx);
-void soup_set_connection_limit (guint max_conn);
+SoupContext *soup_get_proxy (void);
-guint soup_get_connection_limit (void);
+void soup_set_connection_limit (guint max_conn);
-void soup_load_config (gchar *config_file);
+guint soup_get_connection_limit (void);
typedef enum {
SOUP_SECURITY_DOMESTIC = 1,
@@ -33,12 +33,14 @@ typedef enum {
SOUP_SECURITY_FRANCE = 3
} SoupSecurityPolicy;
-void soup_set_security_policy (SoupSecurityPolicy policy);
+void soup_set_security_policy (SoupSecurityPolicy policy);
+
+SoupSecurityPolicy soup_get_security_policy (void);
/* Useful debugging routines */
-void soup_debug_print_headers (SoupMessage *req);
+void soup_debug_print_headers (SoupMessage *req);
-void soup_debug_print_uri (SoupUri *uri);
+void soup_debug_print_uri (SoupUri *uri);
#endif /* SOUP_MISC_H */
diff --git a/libsoup/soup-queue.c b/libsoup/soup-queue.c
index 9cad717e..835ce69d 100644
--- a/libsoup/soup-queue.c
+++ b/libsoup/soup-queue.c
@@ -13,6 +13,8 @@
#include <glib.h>
#include <string.h>
#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
#include "soup-queue.h"
#include "soup-context.h"
@@ -233,6 +235,52 @@ soup_queue_read_async (GIOChannel* iochannel,
return TRUE;
}
+static gboolean
+soup_queue_error_async (GIOChannel* iochannel,
+ GIOCondition condition,
+ SoupMessage *req)
+{
+ gboolean conn_closed = soup_connection_is_keep_alive (req->priv->conn);
+
+ soup_connection_set_keep_alive (req->priv->conn, FALSE);
+
+ switch (req->status) {
+ case SOUP_STATUS_IDLE:
+ case SOUP_STATUS_QUEUED:
+ case SOUP_STATUS_FINISHED:
+ break;
+ case SOUP_STATUS_CONNECTING:
+ soup_message_issue_callback (req, SOUP_ERROR_CANT_CONNECT);
+ break;
+ case SOUP_STATUS_SENDING_REQUEST:
+ if (req->priv->req_header &&
+ req->priv->req_header->len >= req->priv->write_len) {
+ g_warning ("Requeueing request which failed in "
+ "the sending headers phase");
+ soup_queue_message (req,
+ req->priv->callback,
+ req->priv->user_data);
+ break;
+ }
+
+ soup_message_issue_callback (req, SOUP_ERROR_IO);
+ break;
+ case SOUP_STATUS_READING_RESPONSE:
+ if (req->priv->header_len && !conn_closed) {
+ soup_finish_read (req);
+ break;
+ }
+
+ soup_message_issue_callback (req, SOUP_ERROR_IO);
+ break;
+ default:
+ soup_message_issue_callback (req, SOUP_ERROR_IO);
+ break;
+ }
+
+ return FALSE;
+}
+
static void
soup_encode_http_auth (SoupUri *uri, GString *header, gboolean proxy_auth)
{
@@ -389,6 +437,7 @@ soup_queue_write_async (GIOChannel* iochannel,
GIOError error;
gchar *write_buf;
guint write_len;
+ void *pipe_handler;
if (!req->priv->req_header)
req->priv->req_header = soup_get_request_header (req);
@@ -396,7 +445,10 @@ soup_queue_write_async (GIOChannel* iochannel,
head_len = req->priv->req_header->len;
body_len = req->request.length;
total_len = head_len + body_len;
- total_written = req->priv->write_len;
+ total_written = req->priv->write_len;
+
+ pipe_handler = signal (SIGPIPE, SIG_IGN);
+ errno = 0;
WRITE_SOME_MORE:
if (total_written < head_len) {
@@ -415,12 +467,14 @@ soup_queue_write_async (GIOChannel* iochannel,
write_len,
&bytes_written);
- if (error == G_IO_ERROR_AGAIN)
+ if (error == G_IO_ERROR_AGAIN) {
+ signal (SIGPIPE, pipe_handler);
return TRUE;
-
- if (error != G_IO_ERROR_NONE) {
- soup_message_issue_callback (req, SOUP_ERROR_IO);
- return FALSE;
+ }
+
+ if (errno != 0 || error != G_IO_ERROR_NONE) {
+ soup_queue_error_async (iochannel, G_IO_HUP, req);
+ goto DONE_WRITING;
}
total_written = (req->priv->write_len += bytes_written);
@@ -432,56 +486,13 @@ soup_queue_write_async (GIOChannel* iochannel,
G_IO_IN,
(GIOFunc) soup_queue_read_async,
req);
- return FALSE;
+ goto DONE_WRITING;
}
goto WRITE_SOME_MORE;
-}
-
-
-static gboolean
-soup_queue_error_async (GIOChannel* iochannel,
- GIOCondition condition,
- SoupMessage *req)
-{
- gboolean conn_closed = soup_connection_is_keep_alive (req->priv->conn);
-
- soup_connection_set_keep_alive (req->priv->conn, FALSE);
-
- switch (req->status) {
- case SOUP_STATUS_IDLE:
- case SOUP_STATUS_QUEUED:
- case SOUP_STATUS_FINISHED:
- break;
- case SOUP_STATUS_CONNECTING:
- soup_message_issue_callback (req, SOUP_ERROR_CANT_CONNECT);
- break;
- case SOUP_STATUS_SENDING_REQUEST:
- if (req->priv->req_header &&
- req->priv->req_header->len >= req->priv->write_len) {
- g_warning ("Requeueing request which failed in "
- "the sending headers phase");
- soup_queue_message (req,
- req->priv->callback,
- req->priv->user_data);
- break;
- }
-
- soup_message_issue_callback (req, SOUP_ERROR_IO);
- break;
- case SOUP_STATUS_READING_RESPONSE:
- if (req->priv->header_len && !conn_closed) {
- soup_finish_read (req);
- break;
- }
-
- soup_message_issue_callback (req, SOUP_ERROR_IO);
- break;
- default:
- soup_message_issue_callback (req, SOUP_ERROR_IO);
- break;
- }
+ DONE_WRITING:
+ signal (SIGPIPE, pipe_handler);
return FALSE;
}
diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c
index dfd9e0b5..deed5c71 100644
--- a/libsoup/soup-server.c
+++ b/libsoup/soup-server.c
@@ -36,6 +36,8 @@ soup_server_register (const gchar *methodname,
hand->methodname = g_strdup (methodname);
hand->cb = cb;
hand->user_data = user_data;
+
+ server_handlers = g_slist_prepend (server_handlers, hand);
}
static void
@@ -189,7 +191,7 @@ soup_server_error_cb (GIOChannel *iochannel,
return FALSE;
}
-void
+void
soup_server_main (void)
{
GIOChannel *chan = g_io_channel_unix_new (STDIN_FILENO);
diff --git a/libsoup/soup-server.h b/libsoup/soup-server.h
index 8fb3ad79..fe2afb2e 100644
--- a/libsoup/soup-server.h
+++ b/libsoup/soup-server.h
@@ -27,8 +27,17 @@ void soup_server_unregister_by_cb (SoupServerCallbackFn cb);
void soup_server_unregister_by_data (gpointer user_data);
+/* CGI Server methods */
+
void soup_server_main (void);
void soup_server_main_quit (void);
+
+/* Apache module initializtion */
+
+typedef void (*SoupServerInit) (void);
+
+/* Implement soup_server_init() in your library. */
+
#endif /* SOUP_SERVER_H */
diff --git a/libsoup/soup-socks.c b/libsoup/soup-socks.c
index 50142929..0dfb768b 100644
--- a/libsoup/soup-socks.c
+++ b/libsoup/soup-socks.c
@@ -18,7 +18,7 @@
struct _GInetAddr {
gchar* name;
- struct sockaddr sa;
+ struct sockaddr_in sa;
guint ref_count;
};
diff --git a/libsoup/soup-ssl.c b/libsoup/soup-ssl.c
index 48af0461..d831be1e 100644
--- a/libsoup/soup-ssl.c
+++ b/libsoup/soup-ssl.c
@@ -9,84 +9,91 @@
*/
#include <config.h>
-#include <gmodule.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <fcntl.h>
#include "soup-ssl.h"
+#include "soup-misc.h"
-#ifdef HAVE_SECURITY_SSL_H
-#include "soup-nss.h"
-#endif
-
-#ifdef HAVE_OPENSSL_SSL_H
-#include "soup-openssl.h"
-#endif
-
-static gint ssl_library = 0; /* -1 = fail,
- 0 = first time,
- 1 = nss,
- 2 = openssl */
-static SoupSecurityPolicy ssl_security_level = SOUP_SECURITY_DOMESTIC;
-
-void
-soup_set_security_policy (SoupSecurityPolicy policy)
+static gboolean
+soup_ssl_idle_waitpid (gpointer ppid)
{
- ssl_security_level = policy;
+ int pid = waitpid (GPOINTER_TO_INT (ppid), NULL, WNOHANG);
- switch (ssl_library) {
- case -1:
- case 0:
- break;
-#ifdef HAVE_SECURITY_SSL_H
- case 1:
- soup_nss_set_security_policy (policy);
- break;
-#endif
-#ifdef HAVE_OPENSSL_SSL_H
- case 2:
- soup_openssl_set_security_policy (policy);
- break;
-#endif
- }
+ if (pid == 0) return TRUE;
+ return FALSE;
}
-static void
-soup_ssl_init (void)
+GIOChannel *
+soup_ssl_get_iochannel (GIOChannel *sock)
{
- ssl_library = -1;
+ GIOChannel *new_chan;
+ int sock_fd;
+ int pid;
+ int pair[2], flags;
- if (!g_module_supported ()) return;
+ g_return_val_if_fail (sock != NULL, NULL);
-#ifdef HAVE_SECURITY_SSL_H
- if (ssl_library == -1) ssl_library = soup_nss_init () ? 1 : -1;
-#endif
+ g_io_channel_ref (sock);
-#ifdef HAVE_OPENSSL_SSL_H
- if (ssl_library == -1) ssl_library = soup_openssl_init () ? 2 : -1;
-#endif
+ if (!(sock_fd = g_io_channel_unix_get_fd (sock))) goto ERROR_ARGS;
+ flags = fcntl(sock_fd, F_GETFD, 0);
+ fcntl (sock_fd, F_SETFD, flags & ~FD_CLOEXEC);
+
+ if (socketpair (PF_UNIX, SOCK_STREAM, 0, pair) != 0) goto ERROR_ARGS;
- if (ssl_library == -1) return;
+ fflush (stdin);
+ fflush (stdout);
- soup_set_security_policy (ssl_security_level);
-}
+ pid = fork ();
-GIOChannel *
-soup_ssl_get_iochannel (GIOChannel *sock)
-{
- switch (ssl_library) {
+ switch (pid) {
case -1:
- g_warning ("SSL Not Supported.");
- return NULL;
+ goto ERROR;
case 0:
- default:
- soup_ssl_init ();
- return soup_ssl_get_iochannel (sock);
-#ifdef HAVE_SECURITY_SSL_H
- case 1:
- return soup_nss_get_iochannel (sock);
-#endif
-#ifdef HAVE_OPENSSL_SSL_H
- case 2:
- return soup_openssl_get_iochannel (sock);
-#endif
+ close (pair [1]);
+
+ dup2 (pair [0], STDIN_FILENO);
+ dup2 (pair [0], STDOUT_FILENO);
+
+ close (pair [0]);
+
+ putenv (g_strdup_printf ("SOCKFD=%d", sock_fd));
+ putenv (g_strdup_printf ("SECURITY_POLICY=%d",
+ soup_get_security_policy ()));
+
+ execl (BINDIR G_DIR_SEPARATOR_S "soup-ssl-proxy",
+ BINDIR G_DIR_SEPARATOR_S "soup-ssl-proxy",
+ NULL);
+
+ execl ("soup-ssl-proxy", "soup-ssl-proxy", NULL);
+
+ g_error ("Error executing SSL Proxy\n");
}
+
+ close (pair [0]);
+
+ g_idle_add (soup_ssl_idle_waitpid, GINT_TO_POINTER (pid));
+
+ flags = fcntl(pair [1], F_GETFL, 0);
+ fcntl (pair [1], F_SETFL, flags & O_NONBLOCK);
+
+ new_chan = g_io_channel_unix_new (pair [1]);
+
+ /* FIXME: Why is this needed?? */
+ g_io_channel_ref (new_chan);
+ return new_chan;
+
+ ERROR:
+ close (pair [0]);
+ close (pair [1]);
+ ERROR_ARGS:
+ g_io_channel_unref (sock);
+ return NULL;
}