diff -up libsoup-2.56.0/libsoup/soup-auth-negotiate.c.negotiate-internals libsoup-2.56.0/libsoup/soup-auth-negotiate.c --- libsoup-2.56.0/libsoup/soup-auth-negotiate.c.negotiate-internals 2016-09-16 17:14:27.000000000 +0200 +++ libsoup-2.56.0/libsoup/soup-auth-negotiate.c 2017-06-20 14:34:42.018592998 +0200 @@ -83,11 +83,6 @@ typedef struct { typedef struct { gboolean is_authenticated; - - gulong message_finished_signal_id; - gulong message_got_headers_signal_id; - - SoupNegotiateConnectionState *conn_state; } SoupAuthNegotiatePrivate; #define SOUP_AUTH_NEGOTIATE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH_NEGOTIATE, SoupAuthNegotiatePrivate)) @@ -108,7 +103,6 @@ static GSList *blacklisted_uris; static void parse_uris_from_env_variable (const gchar *env_variable, GSList **list); static void check_server_response (SoupMessage *msg, gpointer auth); -static void remove_server_response_handler (SoupMessage *msg, gpointer auth); static const char spnego_OID[] = "\x2b\x06\x01\x05\x05\x02"; static const gss_OID_desc gss_mech_spnego = { sizeof (spnego_OID) - 1, (void *) &spnego_OID }; @@ -116,12 +110,10 @@ static const gss_OID_desc gss_mech_spneg static gpointer soup_auth_negotiate_create_connection_state (SoupConnectionAuth *auth) { - SoupAuthNegotiatePrivate *priv = SOUP_AUTH_NEGOTIATE_GET_PRIVATE (auth); SoupNegotiateConnectionState *conn; conn = g_slice_new0 (SoupNegotiateConnectionState); conn->state = SOUP_NEGOTIATE_NEW; - priv->conn_state = conn; return conn; } @@ -137,14 +129,11 @@ static void soup_auth_negotiate_free_connection_state (SoupConnectionAuth *auth, gpointer state) { - SoupAuthNegotiate *negotiate = SOUP_AUTH_NEGOTIATE (auth); - SoupAuthNegotiatePrivate *priv = SOUP_AUTH_NEGOTIATE_GET_PRIVATE (negotiate); SoupNegotiateConnectionState *conn = state; free_connection_state_data (conn); g_slice_free (SoupNegotiateConnectionState, conn); - priv->conn_state = NULL; } static GSList * @@ -226,7 +215,6 @@ soup_auth_negotiate_update_connection (S #ifdef LIBSOUP_HAVE_GSSAPI gboolean success = TRUE; SoupNegotiateConnectionState *conn = state; - SoupAuthNegotiatePrivate *priv = SOUP_AUTH_NEGOTIATE_GET_PRIVATE (auth); GError *err = NULL; if (!check_auth_trusted_uri (auth, msg)) { @@ -245,24 +233,19 @@ soup_auth_negotiate_update_connection (S conn->state = SOUP_NEGOTIATE_RECEIVED_CHALLENGE; if (soup_gss_build_response (conn, SOUP_AUTH (auth), &err)) { - /* Register the callbacks just once */ - if (priv->message_finished_signal_id == 0) { - gulong id = 0; - id = g_signal_connect (msg, - "finished", - G_CALLBACK (remove_server_response_handler), - auth); - priv->message_finished_signal_id = id; - } - - if (priv->message_got_headers_signal_id == 0) { - gulong id = 0; + /* Connect the signal only once per message */ + if (!g_object_get_data (G_OBJECT (msg), "negotiate-got-headers-connected")) { /* Wait for the 2xx response to verify server response */ - id = g_signal_connect (msg, + g_signal_connect_data (msg, "got_headers", G_CALLBACK (check_server_response), - auth); - priv->message_got_headers_signal_id = id; + g_object_ref (auth), + (GClosureNotify) g_object_unref, + 0); + /* Mark that the signal was connected */ + g_object_set_data (G_OBJECT (msg), + "negotiate-got-headers-connected", + GINT_TO_POINTER (1)); } goto out; } else { @@ -333,7 +316,11 @@ check_server_response (SoupMessage *msg, GError *err = NULL; SoupAuthNegotiate *negotiate = auth; SoupAuthNegotiatePrivate *priv = SOUP_AUTH_NEGOTIATE_GET_PRIVATE (negotiate); - SoupNegotiateConnectionState *conn = priv->conn_state; + SoupNegotiateConnectionState *conn; + + conn = soup_connection_auth_get_connection_state_for_message (SOUP_CONNECTION_AUTH (auth), msg); + if (!conn) + return; if (auth != soup_message_get_auth (msg)) return; @@ -365,19 +352,6 @@ check_server_response (SoupMessage *msg, g_clear_error (&err); } -static void -remove_server_response_handler (SoupMessage *msg, gpointer auth) -{ - SoupAuthNegotiate *negotiate = auth; - SoupAuthNegotiatePrivate *priv = SOUP_AUTH_NEGOTIATE_GET_PRIVATE (negotiate); - - g_signal_handler_disconnect (msg, priv->message_got_headers_signal_id); - priv->message_got_headers_signal_id = 0; - - g_signal_handler_disconnect (msg, priv->message_finished_signal_id); - priv->message_finished_signal_id = 0; -} - /* Check if scheme://host:port from message matches the given URI. */ static gint match_base_uri (SoupURI *list_uri, SoupURI *msg_uri) diff -up libsoup-2.56.0/libsoup/soup-connection-auth.c.negotiate-internals libsoup-2.56.0/libsoup/soup-connection-auth.c --- libsoup-2.56.0/libsoup/soup-connection-auth.c.negotiate-internals 2016-02-05 16:05:33.000000000 +0100 +++ libsoup-2.56.0/libsoup/soup-connection-auth.c 2017-06-20 14:31:00.333517935 +0200 @@ -71,12 +71,31 @@ soup_connection_auth_finalize (GObject * G_OBJECT_CLASS (soup_connection_auth_parent_class)->finalize (object); } -static gpointer -get_connection_state_for_message (SoupConnectionAuth *auth, SoupMessage *msg) + +/** + * soup_connection_auth_get_connection_state_for_message: + * @auth: a #SoupConnectionAuth + * @msg: a #SoupMessage + * + * Returns an associated connection state object for the given @auth and @msg. + * + * This function is only useful from within implementations of SoupConnectionAuth + * subclasses. + * + * Return value: (transfer none): the connection state + * + * Since: 2.56 + **/ +gpointer +soup_connection_auth_get_connection_state_for_message (SoupConnectionAuth *auth, + SoupMessage *msg) { SoupConnection *conn; gpointer state; + g_return_val_if_fail (SOUP_IS_CONNECTION_AUTH (auth), NULL); + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL); + conn = soup_message_get_connection (msg); state = g_hash_table_lookup (auth->priv->conns, conn); if (state) @@ -98,7 +117,7 @@ soup_connection_auth_update (SoupAuth GHashTable *auth_params) { SoupConnectionAuth *cauth = SOUP_CONNECTION_AUTH (auth); - gpointer conn = get_connection_state_for_message (cauth, msg); + gpointer conn = soup_connection_auth_get_connection_state_for_message (cauth, msg); GHashTableIter iter; GString *auth_header; gpointer key, value; @@ -140,7 +159,7 @@ soup_connection_auth_get_authorization ( SoupMessage *msg) { SoupConnectionAuth *cauth = SOUP_CONNECTION_AUTH (auth); - gpointer conn = get_connection_state_for_message (cauth, msg); + gpointer conn = soup_connection_auth_get_connection_state_for_message (cauth, msg); return SOUP_CONNECTION_AUTH_GET_CLASS (auth)-> get_connection_authorization (cauth, msg, conn); @@ -151,7 +170,7 @@ soup_connection_auth_is_ready (SoupAuth SoupMessage *msg) { SoupConnectionAuth *cauth = SOUP_CONNECTION_AUTH (auth); - gpointer conn = get_connection_state_for_message (cauth, msg); + gpointer conn = soup_connection_auth_get_connection_state_for_message (cauth, msg); return SOUP_CONNECTION_AUTH_GET_CLASS (auth)-> is_connection_ready (SOUP_CONNECTION_AUTH (auth), msg, conn); diff -up libsoup-2.56.0/libsoup/soup-connection-auth.h.negotiate-internals libsoup-2.56.0/libsoup/soup-connection-auth.h --- libsoup-2.56.0/libsoup/soup-connection-auth.h.negotiate-internals 2016-09-16 17:14:27.000000000 +0200 +++ libsoup-2.56.0/libsoup/soup-connection-auth.h 2017-06-20 14:31:00.333517935 +0200 @@ -46,6 +46,10 @@ typedef struct { GType soup_connection_auth_get_type (void); +SOUP_AVAILABLE_IN_2_56 +gpointer soup_connection_auth_get_connection_state_for_message + (SoupConnectionAuth *auth, + SoupMessage *message); G_END_DECLS #endif /* SOUP_CONNECTION_AUTH_H */