GNOME Bugzilla – Bug 648551
[PATCH]Able to pass-in o pre-constructed listen socket to soup_server_new
Last modified: 2012-01-10 16:19:09 UTC
From 77eb437d5bcb745e75d14627f3d24085f60682a2 Mon Sep 17 00:00:00 2001 From: microcai <microcai@fedoraproject.org> Date: Sun, 24 Apr 2011 20:10:58 +0800 Subject: [PATCH] This make libsoup based app systemd socket activation capable. First, construt soupsocket, then manully call it with soup_socket_listen_fd(), then pass soupsocket to soup_server_new. This is maybe a suggestion, you guys may have better idea/API. But the idea is simple, make libsoup based application able to do systemd socket activation, of Xinetd activation. --- libsoup/soup-server.c | 33 +++++++++++++++++++++++++-------- libsoup/soup-server.h | 1 + libsoup/soup-socket.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 8 deletions(-) diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c index d56efd1..1829f45 100644 --- a/libsoup/soup-server.c +++ b/libsoup/soup-server.c @@ -130,6 +130,7 @@ enum { PROP_ASYNC_CONTEXT, PROP_RAW_PATHS, PROP_SERVER_HEADER, + PROP_LISTEN_SOCKET, LAST_PROP }; @@ -446,6 +447,14 @@ soup_server_class_init (SoupServerClass *server_class) "Server header", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, PROP_LISTEN_SOCKET, + g_param_spec_object (SOUP_SERVER_LISTEN_SOCKET, + "Listen socket", + "Listen socket", + SOUP_TYPE_SOCKET, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); } static GObject * @@ -478,14 +487,16 @@ constructor (GType type, } } - priv->listen_sock = - soup_socket_new (SOUP_SOCKET_LOCAL_ADDRESS, priv->interface, - SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_creds, - SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context, - NULL); - if (!soup_socket_listen (priv->listen_sock)) { - g_object_unref (server); - return NULL; + if(!priv->listen_sock){ + priv->listen_sock = + soup_socket_new (SOUP_SOCKET_LOCAL_ADDRESS, priv->interface, + SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_creds, + SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context, + NULL); + if (!soup_socket_listen (priv->listen_sock)) { + g_object_unref (server); + return NULL; + } } /* Re-resolve the interface address, in particular in case @@ -548,6 +559,9 @@ set_property (GObject *object, guint prop_id, } else priv->server_header = g_strdup (header); break; + case PROP_LISTEN_SOCKET: + priv->listen_sock = g_value_get_object(value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -582,6 +596,9 @@ get_property (GObject *object, guint prop_id, case PROP_SERVER_HEADER: g_value_set_string (value, priv->server_header); break; + case PROP_LISTEN_SOCKET: + g_value_set_object(value,priv->listen_sock); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/libsoup/soup-server.h b/libsoup/soup-server.h index 4ea17ad..3f630da 100644 --- a/libsoup/soup-server.h +++ b/libsoup/soup-server.h @@ -63,6 +63,7 @@ typedef void (*SoupServerCallback) (SoupServer *server, #define SOUP_SERVER_ASYNC_CONTEXT "async-context" #define SOUP_SERVER_RAW_PATHS "raw-paths" #define SOUP_SERVER_SERVER_HEADER "server-header" +#define SOUP_SERVER_LISTEN_SOCKET "listen-socket" SoupServer *soup_server_new (const char *optname1, ...) G_GNUC_NULL_TERMINATED; diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index 8d11841..ffbc883 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -854,6 +854,55 @@ soup_socket_listen (SoupSocket *sock) return FALSE; } + +/** + * soup_socket_listen_fd: + * @sock: a server #SoupSocket (which must not already be connected or + * listening) + * @fd: a native socket fd, that is already listen on an address + * + * Makes @sock start listening on the passing fd + * + **/ +void +soup_socket_listen_fd (SoupSocket *sock,int fd) + +{ + SoupSocketPrivate *priv; + + g_return_if_fail (SOUP_IS_SOCKET (sock)); + priv = SOUP_SOCKET_GET_PRIVATE (sock); + g_return_if_fail (priv->gsock == NULL); + + priv->is_server = TRUE; + + /* @local_addr may have its port set to 0. So we intentionally + * don't store it in priv->local_addr, so that if the + * caller calls soup_socket_get_local_address() later, we'll + * have to make a new addr by calling getsockname(), which + * will have the right port number. + */ + + priv->gsock = g_socket_new_from_fd(fd,NULL); + + if (!priv->gsock) + goto cant_listen; + + finish_socket_setup (priv); + + /* Force local_addr to be re-resolved now */ + g_object_unref (priv->local_addr); + priv->local_addr = NULL; + + priv->watch_src = soup_socket_create_watch (priv, G_IO_IN, + listen_watch, sock, + NULL); + return ; + + cant_listen: + if (priv->conn) + disconnect_internal (sock); +} static void soup_socket_peer_certificate_changed (GObject *conn, GParamSpec *pspec, gpointer sock) -- 1.7.5.rc1
It looks as though this was requested already in Bug #621138. *** This bug has been marked as a duplicate of bug 621138 ***