libsoup r1013 - in branches/libsoup-2.4: . libsoup tests
- From: danw svn gnome org
- To: svn-commits-list gnome org
- Subject: libsoup r1013 - in branches/libsoup-2.4: . libsoup tests
- Date: Sun, 6 Jan 2008 22:19:25 +0000 (GMT)
Author: danw
Date: Sun Jan 6 22:19:25 2008
New Revision: 1013
URL: http://svn.gnome.org/viewvc/libsoup?rev=1013&view=rev
Log:
* libsoup/soup-server.c (SoupClientContext): Make this opaque.
(soup_client_context_get_socket)
(soup_client_context_get_auth_domain)
(soup_client_context_get_auth_user): New accessors
(soup_server_class_init): Make the signals take a
SoupClientContext rather than a SoupSocket.
(start_request, check_auth, call_handler, request_finished): Clean
these up by using a SoupClientContext to communicate between them.
(soup_server_add_handler): tweak the argument order to match the
gtk standard (callback, user_data, destroynotify).
Modified:
branches/libsoup-2.4/ChangeLog
branches/libsoup-2.4/libsoup/soup-server.c
branches/libsoup-2.4/libsoup/soup-server.h
branches/libsoup-2.4/tests/ntlm-test.c
Modified: branches/libsoup-2.4/ChangeLog
==============================================================================
--- branches/libsoup-2.4/ChangeLog (original)
+++ branches/libsoup-2.4/ChangeLog Sun Jan 6 22:19:25 2008
@@ -1,5 +1,18 @@
2008-01-06 Dan Winship <danw gnome org>
+ * libsoup/soup-server.c (SoupClientContext): Make this opaque.
+ (soup_client_context_get_socket)
+ (soup_client_context_get_auth_domain)
+ (soup_client_context_get_auth_user): New accessors
+ (soup_server_class_init): Make the signals take a
+ SoupClientContext rather than a SoupSocket.
+ (start_request, check_auth, call_handler, request_finished): Clean
+ these up by using a SoupClientContext to communicate between them.
+ (soup_server_add_handler): tweak the argument order to match the
+ gtk standard (callback, user_data, destroynotify).
+
+2008-01-06 Dan Winship <danw gnome org>
+
* libsoup/soup-address.c: remove the "dns_result" signal, which
was just an implementation detail of soup_address_resolve_async().
Modified: branches/libsoup-2.4/libsoup/soup-server.c
==============================================================================
--- branches/libsoup-2.4/libsoup/soup-server.c (original)
+++ branches/libsoup-2.4/libsoup/soup-server.c Sun Jan 6 22:19:25 2008
@@ -37,6 +37,13 @@
static guint signals[LAST_SIGNAL] = { 0 };
+struct SoupClientContext {
+ SoupServer *server;
+ SoupSocket *sock;
+ SoupAuthDomain *auth_domain;
+ char *auth_user;
+};
+
typedef struct {
char *path;
@@ -161,7 +168,7 @@
/**
* SoupServer::request-started
* @server: the server
- * @connection: an (opaque) connection ID
+ * @client: the client context
* @message: the new message
*
* Emitted when the server has started reading a new request.
@@ -170,10 +177,11 @@
* you can usefully do with it is connect to its signals.
*
* If the request is read successfully, this will eventually
- * be followed by a #request-read signal. If a response is
- * then sent, the request processing will end with a
- * #request-finished signal. If a network error occurs, the
- * processing will instead end with #request-aborted.
+ * be followed by a #SoupServer::request_read signal. If a
+ * response is then sent, the request processing will end with
+ * a #SoupServer::request_finished signal. If a network error
+ * occurs, the processing will instead end with
+ * #SoupServer::request_aborted.
**/
signals[REQUEST_STARTED] =
g_signal_new ("request-started",
@@ -189,15 +197,16 @@
/**
* SoupServer::request-read
* @server: the server
- * @connection: an (opaque) connection ID
+ * @client: the client context
* @message: the message
*
* Emitted when the server has successfully read a request.
* @message will have all of its request-side information
- * filled in. This signal is emitted before any handlers are
- * called for the message, and if it sets the message's
- * #status_code, then normal handler processing will be
- * skipped.
+ * filled in, and if the message was authenticated, @client
+ * will have information about that. This signal is emitted
+ * before any handlers are called for the message, and if it
+ * sets the message's #status_code, then normal handler
+ * processing will be skipped.
**/
signals[REQUEST_READ] =
g_signal_new ("request-read",
@@ -213,7 +222,7 @@
/**
* SoupServer::request-finished
* @server: the server
- * @connection: an (opaque) connection ID
+ * @client: the client context
* @message: the message
*
* Emitted when the server has finished writing a response to
@@ -233,19 +242,20 @@
/**
* SoupServer::request-aborted
* @server: the server
- * @connection: an (opaque) connection ID
+ * @client: the client context
* @message: the message
*
* Emitted when processing has failed for a message; this
* could mean either that it could not be read (if
- * #request-read has not been emitted for it yet), or that the
- * response could not be written back (if #request-read has
- * been emitted but #request-finished has not been).
+ * #SoupServer::request_read has not been emitted for it yet),
+ * or that the response could not be written back (if
+ * #SoupServer::request_read has been emitted but
+ * #SoupServer::request_finished has not been).
*
* @message is in an undefined state when this signal is
* emitted; the signal exists primarily to allow the server to
* free any state that it may have allocated in
- * #request-started.
+ * #SoupServer::request_started.
**/
signals[REQUEST_ABORTED] =
g_signal_new ("request-aborted",
@@ -491,23 +501,40 @@
return priv->listen_sock;
}
-static void start_request (SoupServer *, SoupSocket *);
+static void start_request (SoupServer *, SoupClientContext *);
static void
-request_finished (SoupMessage *msg, gpointer sock)
+soup_client_context_cleanup (SoupClientContext *client)
{
- SoupServer *server = g_object_get_data (sock, "SoupServer");
+ if (client->auth_domain) {
+ g_object_unref (client->auth_domain);
+ client->auth_domain = NULL;
+ }
+ if (client->auth_user) {
+ g_free (client->auth_user);
+ client->auth_user = NULL;
+ }
+}
+
+static void
+request_finished (SoupMessage *msg, SoupClientContext *client)
+{
+ SoupServer *server = client->server;
+ SoupSocket *sock = client->sock;
g_signal_emit (server,
msg->status_code == SOUP_STATUS_IO_ERROR ?
signals[REQUEST_ABORTED] : signals[REQUEST_FINISHED],
- 0, sock, msg);
+ 0, client, msg);
+ soup_client_context_cleanup (client);
if (soup_socket_is_connected (sock) && soup_message_is_keepalive (msg)) {
/* Start a new request */
- start_request (server, sock);
- } else
+ start_request (server, client);
+ } else {
soup_socket_disconnect (sock);
+ g_slice_free (SoupClientContext, client);
+ }
g_object_unref (msg);
g_object_unref (sock);
}
@@ -530,30 +557,23 @@
}
static void
-check_auth (SoupMessage *req, SoupSocket *sock)
+check_auth (SoupMessage *req, SoupClientContext *client)
{
- SoupServer *server;
- SoupServerPrivate *priv;
+ SoupServer *server = client->server;
+ SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
SoupAuthDomain *domain;
GSList *iter;
gboolean rejected = FALSE;
char *auth_user;
- server = g_object_get_data (G_OBJECT (sock), "SoupServer");
- priv = SOUP_SERVER_GET_PRIVATE (server);
-
for (iter = priv->auth_domains; iter; iter = iter->next) {
domain = iter->data;
if (soup_auth_domain_covers (domain, req)) {
auth_user = soup_auth_domain_accepts (domain, req);
if (auth_user) {
- g_object_set_data_full (G_OBJECT (req),
- "SoupServer-auth_user",
- auth_user, g_free);
- g_object_set_data (G_OBJECT (req),
- "SoupServer-auth_realm",
- (char *)soup_auth_domain_get_realm (domain));
+ client->auth_domain = g_object_ref (domain);
+ client->auth_user = auth_user;
return;
}
@@ -574,9 +594,9 @@
}
static void
-call_handler (SoupMessage *req, SoupSocket *sock)
+call_handler (SoupMessage *req, SoupClientContext *client)
{
- SoupServer *server;
+ SoupServer *server = client->server;
SoupServerHandler *hand;
SoupURI *uri;
char *path;
@@ -584,8 +604,6 @@
if (req->status_code != 0)
return;
- server = g_object_get_data (G_OBJECT (sock), "SoupServer");
-
uri = soup_message_get_uri (req);
path = g_strdup (uri->path);
soup_uri_decode (path);
@@ -598,15 +616,8 @@
}
if (hand->callback) {
- SoupClientContext ctx;
GHashTable *form_data_set;
- ctx.sock = sock;
- ctx.auth_user = g_object_get_data (G_OBJECT (req),
- "SoupServer-auth_user");
- ctx.auth_realm = g_object_get_data (G_OBJECT (req),
- "SoupServer-auth_realm");
-
if (uri->query)
form_data_set = soup_form_decode_urlencoded (uri->query);
else
@@ -615,7 +626,7 @@
/* Call method handler */
(*hand->callback) (server, req,
path, form_data_set,
- &ctx, hand->user_data);
+ client, hand->user_data);
if (form_data_set)
g_hash_table_destroy (form_data_set);
@@ -625,24 +636,26 @@
}
static void
-start_request (SoupServer *server, SoupSocket *server_sock)
+start_request (SoupServer *server, SoupClientContext *client)
{
SoupMessage *msg;
+ soup_client_context_cleanup (client);
+
/* Listen for another request on this connection */
msg = g_object_new (SOUP_TYPE_MESSAGE, NULL);
soup_message_headers_set_encoding (msg->response_headers,
SOUP_ENCODING_CONTENT_LENGTH);
- g_signal_connect (msg, "got_headers", G_CALLBACK (check_auth), server_sock);
- g_signal_connect (msg, "got_body", G_CALLBACK (call_handler), server_sock);
- g_signal_connect (msg, "finished", G_CALLBACK (request_finished), server_sock);
+ g_signal_connect (msg, "got_headers", G_CALLBACK (check_auth), client);
+ g_signal_connect (msg, "got_body", G_CALLBACK (call_handler), client);
+ g_signal_connect (msg, "finished", G_CALLBACK (request_finished), client);
g_signal_emit (server, signals[REQUEST_STARTED], 0,
- server_sock, msg);
+ client, msg);
- g_object_ref (server_sock);
- soup_message_read_request (msg, server_sock);
+ g_object_ref (client->sock);
+ soup_message_read_request (msg, client->sock);
}
static void
@@ -660,13 +673,14 @@
{
SoupServer *server = user_data;
SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
+ SoupClientContext *client = g_slice_new0 (SoupClientContext);
- g_object_ref (sock);
- g_object_set_data (G_OBJECT (sock), "SoupServer", server);
+ client->server = server;
+ client->sock = g_object_ref (sock);
priv->client_socks = g_slist_prepend (priv->client_socks, sock);
g_signal_connect (sock, "disconnected",
G_CALLBACK (socket_disconnected), server);
- start_request (server, sock);
+ start_request (server, client);
}
/**
@@ -784,8 +798,48 @@
}
/**
+ * SoupClientContext:
+ *
+ * A #SoupClientContext provides additional information about the
+ * client making a particular request. In particular, you can use
+ * soup_client_context_get_auth_domain() and
+ * soup_client_context_get_auth_user() to determine if HTTP
+ * authentication was used successfully.
+ *
+ * soup_client_context_get_address() and/or
+ * soup_client_context_get_host() can be used to get information for
+ * logging or debugging purposes. soup_client_context_get_socket() may
+ * also be of use in some situations (eg, tracking when multiple
+ * requests are made on the same connection).
+ **/
+
+/**
+ * soup_client_context_get_socket:
+ * @client: a #SoupClientContext
+ *
+ * Retrieves the #SoupSocket that @client is associated with.
+ *
+ * If you are using this method to observe when multiple requests are
+ * made on the same persistent HTTP connection (eg, as the ntlm-test
+ * test program does), you will need to pay attention to socket
+ * destruction as well (either by using weak references, or by
+ * connecting to the #SoupSocket::disconnected signal), so that you do
+ * not get fooled when the allocator reuses the memory address of a
+ * previously-destroyed socket to represent a new socket.
+ *
+ * Return value: the #SoupSocket that @client is associated with.
+ **/
+SoupSocket *
+soup_client_context_get_socket (SoupClientContext *client)
+{
+ g_return_val_if_fail (client != NULL, NULL);
+
+ return client->sock;
+}
+
+/**
* soup_client_context_get_address:
- * @context: a #SoupClientContext
+ * @client: a #SoupClientContext
*
* Retrieves the #SoupAddress associated with the remote end
* of a connection.
@@ -794,16 +848,16 @@
* connection.
**/
SoupAddress *
-soup_client_context_get_address (SoupClientContext *context)
+soup_client_context_get_address (SoupClientContext *client)
{
- g_return_val_if_fail (context != NULL, NULL);
+ g_return_val_if_fail (client != NULL, NULL);
- return soup_socket_get_remote_address (context->sock);
+ return soup_socket_get_remote_address (client->sock);
}
/**
* soup_client_context_get_host:
- * @context: a #SoupClientContext
+ * @client: a #SoupClientContext
*
* Retrieves the IP address associated with the remote end of a
* connection. (If you want the actual hostname, you'll have to call
@@ -814,21 +868,59 @@
* connection.
**/
const char *
-soup_client_context_get_host (SoupClientContext *context)
+soup_client_context_get_host (SoupClientContext *client)
{
SoupAddress *address;
- address = soup_client_context_get_address (context);
+ address = soup_client_context_get_address (client);
return soup_address_get_physical (address);
}
/**
+ * soup_client_context_get_auth_domain:
+ * @client: a #SoupClientContext
+ *
+ * Checks whether the request associated with @client has been
+ * authenticated, and if so returns the #SoupAuthDomain that
+ * authenticated it.
+ *
+ * Return value: a #SoupAuthDomain, or %NULL if the request was not
+ * authenticated.
+ **/
+SoupAuthDomain *
+soup_client_context_get_auth_domain (SoupClientContext *client)
+{
+ g_return_val_if_fail (client != NULL, NULL);
+
+ return client->auth_domain;
+}
+
+/**
+ * soup_client_context_get_auth_user:
+ * @client: a #SoupClientContext
+ *
+ * Checks whether the request associated with @client has been
+ * authenticated, and if so returns the username that the client
+ * authenticated as.
+ *
+ * Return value: the authenticated-as user, or %NULL if the request
+ * was not authenticated.
+ **/
+const char *
+soup_client_context_get_auth_user (SoupClientContext *client)
+{
+ g_return_val_if_fail (client != NULL, NULL);
+
+ return client->auth_user;
+}
+
+/**
* SoupServerCallback:
* @server: the #SoupServer
* @msg: the message being processed
* @path: the path component of @msg's Request-URI
* @query: the parsed query component of @msg's Request-URI
- * @context: additional contextual information about the client
+ * @client: additional contextual information about the client
* @user_data: the data passed to @soup_server_add_handler
*
* A callback used to handle requests to a #SoupServer. The callback
@@ -866,20 +958,14 @@
* soup_message_body_complete() to indicate that no more chunks are
* coming.
**/
-typedef void (*SoupServerCallback) (SoupServer *server,
- SoupMessage *msg,
- const char *path,
- GHashTable *query,
- SoupClientContext *context,
- gpointer user_data);
/**
* soup_server_add_handler:
* @server: a #SoupServer
* @path: the toplevel path for the handler
* @callback: callback to invoke for requests under @path
- * @destroy: destroy notifier to free @user_data
* @user_data: data for @callback
+ * @destroy: destroy notifier to free @user_data
*
* Adds a handler to @server for requests under @path. See the
* documentation for #SoupServerCallback for information about
@@ -889,8 +975,8 @@
soup_server_add_handler (SoupServer *server,
const char *path,
SoupServerCallback callback,
- GDestroyNotify destroy,
- gpointer user_data)
+ gpointer user_data,
+ GDestroyNotify destroy)
{
SoupServerPrivate *priv;
SoupServerHandler *hand;
Modified: branches/libsoup-2.4/libsoup/soup-server.h
==============================================================================
--- branches/libsoup-2.4/libsoup/soup-server.h (original)
+++ branches/libsoup-2.4/libsoup/soup-server.h Sun Jan 6 22:19:25 2008
@@ -36,18 +36,12 @@
GType soup_server_get_type (void);
-
-typedef struct {
- SoupSocket *sock;
- const char *auth_user;
- const char *auth_realm;
-} SoupClientContext;
-
+typedef struct SoupClientContext SoupClientContext;
typedef void (*SoupServerCallback) (SoupServer *server,
SoupMessage *msg,
const char *path,
GHashTable *query,
- SoupClientContext *context,
+ SoupClientContext *client,
gpointer user_data);
#define SOUP_SERVER_PORT "port"
@@ -75,8 +69,8 @@
void soup_server_add_handler (SoupServer *serv,
const char *path,
SoupServerCallback callback,
- GDestroyNotify destroy,
- gpointer data);
+ gpointer data,
+ GDestroyNotify destroy);
void soup_server_remove_handler (SoupServer *serv,
const char *path);
@@ -94,8 +88,11 @@
/* Client context */
-SoupAddress *soup_client_context_get_address (SoupClientContext *ctx);
-const char *soup_client_context_get_host (SoupClientContext *ctx);
+SoupSocket *soup_client_context_get_socket (SoupClientContext *client);
+SoupAddress *soup_client_context_get_address (SoupClientContext *client);
+const char *soup_client_context_get_host (SoupClientContext *client);
+SoupAuthDomain *soup_client_context_get_auth_domain (SoupClientContext *client);
+const char *soup_client_context_get_auth_user (SoupClientContext *client);
G_END_DECLS
Modified: branches/libsoup-2.4/tests/ntlm-test.c
==============================================================================
--- branches/libsoup-2.4/tests/ntlm-test.c (original)
+++ branches/libsoup-2.4/tests/ntlm-test.c Sun Jan 6 22:19:25 2008
@@ -59,7 +59,7 @@
static void
server_callback (SoupServer *server, SoupMessage *msg,
const char *path, GHashTable *query,
- SoupClientContext *context, gpointer data)
+ SoupClientContext *client, gpointer data)
{
GHashTable *connections = data;
const char *auth;
@@ -80,7 +80,7 @@
if (strstr (path, "/404"))
not_found = TRUE;
- state = GPOINTER_TO_INT (g_hash_table_lookup (connections, context->sock));
+ state = GPOINTER_TO_INT (g_hash_table_lookup (connections, soup_client_context_get_socket (client)));
auth = soup_message_headers_get (msg->request_headers, "Authorization");
if (auth && !strncmp (auth, "NTLM ", 5)) {
@@ -118,7 +118,7 @@
"Connection", "close");
}
- g_hash_table_insert (connections, context->sock,
+ g_hash_table_insert (connections, soup_client_context_get_socket (client),
GINT_TO_POINTER (state));
}
@@ -373,7 +373,7 @@
exit (1);
}
soup_server_add_handler (server, NULL,
- server_callback, NULL, connections);
+ server_callback, connections, NULL);
soup_server_run_async (server);
loop = g_main_loop_new (NULL, TRUE);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]