Skip to content
Commits on Source (28)
......@@ -33,7 +33,7 @@ RUN dnf update -y \
&& dnf clean all \
&& python2.7 -m ensurepip \
&& pip2.7 install virtualenv autobahntestsuite \
&& pip3 install quart gi-docgen
&& pip3 install gi-docgen
# We need glib 2.70
RUN git clone https://gitlab.gnome.org/GNOME/glib.git \
......
Changes in libsoup from 3.1.2 to 3.1.3:
* Fix compile error when `SOUP_VERSION_MAX_ALLOWED` is defined [Patrick Griffis]
Changes in libsoup from 3.1.1 to 3.1.2:
* Replace HTTP/2 tests using Quart with internal HTTP/2 server tests [Carlos Garcia Campos]
* Improve version macros including adding ability to define `SOUP_DISABLE_DEPRECATION_WARNINGS` [Emmanuele Bassi]
Changes in libsoup from 3.0.7 to 3.1.1:
* Reintroduce some thread-safety to SoupSession (see https://libsoup.org/libsoup-3.0/client-thread-safety.html) [Carlos Garcia Campos]
......
[library]
namespace = "Soup"
version = "@VERSION@"
browse_url = "https://gitlab.gnome.org/GNOME/libsoup"
repository_url = "https://gitlab.gnome.org/GNOME/libsoup.git"
docs_url = "https://gnome.pages.gitlab.gnome.org/libsoup/libsoup-3.0/"
docs_url = "https://libsoup.org/libsoup-3.0/"
website_url = "https://libsoup.org/"
authors = "Dan Winship, Claudio Saavedra, Patrick Griffis, and Carlos Garcia Campos"
license = "LGPL-2.0-or-later"
......
......@@ -190,7 +190,7 @@ tunnel_connected_cb (GObject *object,
SOUP_MEMORY_COPY,
error->message, strlen (error->message));
g_error_free (error);
soup_server_unpause_message (tunnel->self, tunnel->msg);
soup_server_message_unpause (tunnel->msg);
tunnel_close (tunnel);
return;
}
......@@ -199,7 +199,7 @@ tunnel_connected_cb (GObject *object,
tunnel->server.ostream = g_io_stream_get_output_stream (tunnel->server.iostream);
soup_server_message_set_status (tunnel->msg, SOUP_STATUS_OK, NULL);
soup_server_unpause_message (tunnel->self, tunnel->msg);
soup_server_message_unpause (tunnel->msg);
g_signal_connect (tunnel->msg, "finished",
G_CALLBACK (start_tunnel), tunnel);
}
......@@ -211,7 +211,7 @@ try_tunnel (SoupServer *server, SoupServerMessage *msg)
GUri *dest_uri;
GSocketClient *sclient;
soup_server_pause_message (server, msg);
soup_server_message_pause (msg);
tunnel = g_new0 (Tunnel, 1);
tunnel->self = g_object_ref (server);
......@@ -241,7 +241,7 @@ send_headers (SoupMessage *from, SoupServerMessage *to)
soup_message_headers_foreach (soup_message_get_response_headers (from), copy_header,
soup_server_message_get_response_headers (to));
soup_message_headers_remove (soup_server_message_get_response_headers (to), "Content-Length");
soup_server_unpause_message (server, to);
soup_server_message_unpause (to);
}
static void
......@@ -262,7 +262,7 @@ stream_read (GObject *source, GAsyncResult *result, gpointer user_data)
if (error) {
g_print ("[%p] failed to read body: %s\n\n", server_msg, error->message);
soup_server_message_set_status (server_msg, SOUP_STATUS_INTERNAL_SERVER_ERROR, NULL);
soup_server_unpause_message (server, server_msg);
soup_server_message_unpause (server_msg);
g_error_free (error);
return;
}
......@@ -274,7 +274,7 @@ stream_read (GObject *source, GAsyncResult *result, gpointer user_data)
g_signal_handlers_disconnect_by_func (server_msg, client_msg_failed, client_cancellable);
soup_message_body_complete (soup_server_message_get_response_body (server_msg));
soup_server_unpause_message (server, server_msg);
soup_server_message_unpause (server_msg);
g_object_unref (server_msg);
return;
}
......@@ -284,7 +284,7 @@ stream_read (GObject *source, GAsyncResult *result, gpointer user_data)
SoupMessageBody *body = soup_server_message_get_response_body (server_msg);
soup_message_body_append_bytes (body, bytes);
soup_server_unpause_message (server, server_msg);
soup_server_message_unpause (server_msg);
g_bytes_unref (bytes);
......@@ -303,7 +303,7 @@ client_message_sent (GObject *source, GAsyncResult *result, gpointer user_data)
if (error) {
g_print ("[%p] failed to read body: %s\n\n", server_msg, error->message);
soup_server_message_set_status (server_msg, SOUP_STATUS_INTERNAL_SERVER_ERROR, NULL);
soup_server_unpause_message (server, server_msg);
soup_server_message_unpause (server_msg);
g_error_free (error);
return;
}
......@@ -365,7 +365,7 @@ server_callback (SoupServer *server, SoupServerMessage *msg,
// Keep the server message alive until the client one is finished
g_object_ref (msg);
soup_server_pause_message (server, msg);
soup_server_message_pause (msg);
}
static gboolean
......
......@@ -17,16 +17,9 @@
<maintainer>
<foaf:Person>
<foaf:name>Dan Winship</foaf:name>
<foaf:mbox rdf:resource="mailto:danw@gnome.org" />
<gnome:userid>danw</gnome:userid>
</foaf:Person>
</maintainer>
<maintainer>
<foaf:Person>
<foaf:name>Claudio Saavedra</foaf:name>
<foaf:mbox rdf:resource="mailto:csaavedra@igalia.com" />
<gnome:userid>csaavedra</gnome:userid>
<foaf:name>Carlos Garcia Campos</foaf:name>
<foaf:mbox rdf:resource="mailto:cgarcia@igalia.com" />
<gnome:userid>carlosgc</gnome:userid>
</foaf:Person>
</maintainer>
<maintainer>
......
......@@ -50,11 +50,11 @@ for version in versions:
* A macro used to indicate a symbol was deprecated in this version with a replacement.
*/
#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_{major_version}_{minor_version}
# define SOUP_DEPRECATED_IN_{major_version}_{minor_version} G_DEPRECATED
# define SOUP_DEPRECATED_IN_{major_version}_{minor_version}_FOR(f) G_DEPRECATED_FOR(f)
# define SOUP_DEPRECATED_IN_{major_version}_{minor_version} SOUP_DEPRECATED
# define SOUP_DEPRECATED_IN_{major_version}_{minor_version}_FOR(f) SOUP_DEPRECATED_FOR(f)
#else
# define SOUP_DEPRECATED_IN_{major_version}_{minor_version}
# define SOUP_DEPRECATED_IN_{major_version}_{minor_version}_FOR(f)
# define SOUP_DEPRECATED_IN_{major_version}_{minor_version} _SOUP_EXTERN
# define SOUP_DEPRECATED_IN_{major_version}_{minor_version}_FOR(f) _SOUP_EXTERN
#endif
/**
......@@ -62,7 +62,7 @@ for version in versions:
* A macro used to indicate a symbol is available in this version or later.
*/
#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_{major_version}_{minor_version}
# define SOUP_AVAILABLE_IN_{major_version}_{minor_version} G_UNAVAILABLE({major_version}, {minor_version}) _SOUP_EXTERN
# define SOUP_AVAILABLE_IN_{major_version}_{minor_version} SOUP_UNAVAILABLE({major_version}, {minor_version})
#else
# define SOUP_AVAILABLE_IN_{major_version}_{minor_version} _SOUP_EXTERN
#endif
......
......@@ -40,25 +40,13 @@
#include "soup-client-input-stream.h"
#include "soup-logger-private.h"
#include "soup-uri-utils-private.h"
#include "soup-http2-utils.h"
#include "content-decoder/soup-content-decoder.h"
#include "soup-body-input-stream-http2.h"
#include <nghttp2/nghttp2.h>
#define FRAME_HEADER_SIZE 9
typedef enum {
STATE_NONE,
STATE_WRITE_HEADERS,
STATE_WRITE_DATA,
STATE_WRITE_DONE,
STATE_READ_HEADERS,
STATE_READ_DATA_START,
STATE_READ_DATA,
STATE_READ_DONE,
} SoupHTTP2IOState;
typedef struct {
SoupClientMessageIO iface;
......@@ -127,93 +115,6 @@ typedef struct {
static void soup_client_message_io_http2_finished (SoupClientMessageIO *iface, SoupMessage *msg);
static ssize_t on_data_source_read_callback (nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data);
static void
NGCHECK (int return_code)
{
if (return_code == NGHTTP2_ERR_NOMEM)
g_abort ();
else if (return_code < 0)
g_debug ("Unhandled NGHTTP2 Error: %s", nghttp2_strerror (return_code));
}
static const char *
frame_type_to_string (nghttp2_frame_type type)
{
switch (type) {
case NGHTTP2_DATA:
return "DATA";
case NGHTTP2_HEADERS:
return "HEADERS";
case NGHTTP2_PRIORITY:
return "PRIORITY";
case NGHTTP2_RST_STREAM:
return "RST_STREAM";
case NGHTTP2_SETTINGS:
return "SETTINGS";
case NGHTTP2_PING:
return "PING";
case NGHTTP2_GOAWAY:
return "GOAWAY";
case NGHTTP2_WINDOW_UPDATE:
return "WINDOW_UPDATE";
/* LCOV_EXCL_START */
case NGHTTP2_PUSH_PROMISE:
return "PUSH_PROMISE";
case NGHTTP2_CONTINUATION:
return "CONTINUATION";
case NGHTTP2_ALTSVC:
return "ALTSVC";
case NGHTTP2_ORIGIN:
return "ORIGIN";
default:
g_warn_if_reached ();
return "UNKNOWN";
/* LCOV_EXCL_STOP */
}
}
static const char *
headers_category_to_string (nghttp2_headers_category catergory)
{
switch (catergory) {
case NGHTTP2_HCAT_REQUEST:
return "REQUEST";
case NGHTTP2_HCAT_RESPONSE:
return "RESPONSE";
case NGHTTP2_HCAT_PUSH_RESPONSE:
return "PUSH_RESPONSE";
case NGHTTP2_HCAT_HEADERS:
return "HEADERS";
}
g_assert_not_reached ();
}
static const char *
state_to_string (SoupHTTP2IOState state)
{
switch (state) {
case STATE_NONE:
return "NONE";
case STATE_WRITE_HEADERS:
return "WRITE_HEADERS";
case STATE_WRITE_DATA:
return "WRITE_DATA";
case STATE_WRITE_DONE:
return "WRITE_DONE";
case STATE_READ_HEADERS:
return "READ_HEADERS";
case STATE_READ_DATA_START:
return "READ_DATA_START";
case STATE_READ_DATA:
return "READ_DATA";
case STATE_READ_DONE:
return "READ_DONE";
default:
g_assert_not_reached ();
return "";
}
}
G_GNUC_PRINTF(3, 0)
static void
h2_debug (SoupClientMessageIOHTTP2 *io,
......@@ -236,7 +137,7 @@ h2_debug (SoupClientMessageIOHTTP2 *io,
stream_id = data->stream_id;
g_assert (io);
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "[C%" G_GUINT64_FORMAT "-S%u] [%s] %s", io->connection_id, stream_id, data ? state_to_string (data->state) : "-", message);
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "[CLIENT] [C%" G_GUINT64_FORMAT "-S%u] [%s] %s", io->connection_id, stream_id, data ? soup_http2_io_state_to_string (data->state) : "-", message);
g_free (message);
}
......@@ -288,20 +189,20 @@ advance_state_from (SoupHTTP2MessageData *data,
{
if (data->state != from) {
g_warning ("Unexpected state changed %s -> %s, expected to be from %s",
state_to_string (data->state), state_to_string (to),
state_to_string (from));
soup_http2_io_state_to_string (data->state), soup_http2_io_state_to_string (to),
soup_http2_io_state_to_string (from));
}
/* State never goes backwards */
if (to < data->state) {
g_warning ("Unexpected state changed %s -> %s, expected %s -> %s\n",
state_to_string (data->state), state_to_string (to),
state_to_string (from), state_to_string (to));
soup_http2_io_state_to_string (data->state), soup_http2_io_state_to_string (to),
soup_http2_io_state_to_string (from), soup_http2_io_state_to_string (to));
return;
}
h2_debug (data->io, data, "[SESSION] State %s -> %s",
state_to_string (data->state), state_to_string (to));
soup_http2_io_state_to_string (data->state), soup_http2_io_state_to_string (to));
data->state = to;
}
......@@ -617,7 +518,7 @@ on_begin_frame_callback (nghttp2_session *session,
{
SoupHTTP2MessageData *data = nghttp2_session_get_stream_user_data (session, hd->stream_id);
h2_debug (user_data, data, "[RECV] [%s] Beginning", frame_type_to_string (hd->type));
h2_debug (user_data, data, "[RECV] [%s] Beginning", soup_http2_frame_type_to_string (hd->type));
if (!data)
return 0;
......@@ -688,7 +589,7 @@ on_frame_recv_callback (nghttp2_session *session,
io->in_callback++;
if (frame->hd.stream_id == 0) {
h2_debug (io, NULL, "[RECV] [%s] Received (%u)", frame_type_to_string (frame->hd.type), frame->hd.flags);
h2_debug (io, NULL, "[RECV] [%s] Received (%u)", soup_http2_frame_type_to_string (frame->hd.type), frame->hd.flags);
switch (frame->hd.type) {
case NGHTTP2_GOAWAY:
......@@ -711,7 +612,7 @@ on_frame_recv_callback (nghttp2_session *session,
}
data = nghttp2_session_get_stream_user_data (session, frame->hd.stream_id);
h2_debug (io, data, "[RECV] [%s] Received (%u)", frame_type_to_string (frame->hd.type), frame->hd.flags);
h2_debug (io, data, "[RECV] [%s] Received (%u)", soup_http2_frame_type_to_string (frame->hd.type), frame->hd.flags);
if (!data) {
if (!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) && frame->hd.type != NGHTTP2_RST_STREAM)
......@@ -728,7 +629,7 @@ on_frame_recv_callback (nghttp2_session *session,
data->metrics->response_header_bytes_received += frame->hd.length + FRAME_HEADER_SIZE;
h2_debug (io, data, "[HEADERS] category=%s status=%u",
headers_category_to_string (frame->headers.cat), status);
soup_http2_headers_category_to_string (frame->headers.cat), status);
switch (frame->headers.cat) {
case NGHTTP2_HCAT_HEADERS:
if (!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS)) {
......@@ -885,7 +786,7 @@ on_frame_send_callback (nghttp2_session *session,
case NGHTTP2_HEADERS:
g_assert (data);
h2_debug (io, data, "[SEND] [HEADERS] category=%s finished=%d",
headers_category_to_string (frame->headers.cat),
soup_http2_headers_category_to_string (frame->headers.cat),
(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS) ? 1 : 0);
if (data->metrics)
......@@ -930,7 +831,7 @@ on_frame_send_callback (nghttp2_session *session,
break;
case NGHTTP2_GOAWAY:
h2_debug (io, data, "[SEND] [%s]", frame_type_to_string (frame->hd.type));
h2_debug (io, data, "[SEND] [%s]", soup_http2_frame_type_to_string (frame->hd.type));
io->goaway_sent = TRUE;
if (io->close_task) {
GSource *source;
......@@ -944,7 +845,7 @@ on_frame_send_callback (nghttp2_session *session,
}
break;
default:
h2_debug (io, data, "[SEND] [%s]", frame_type_to_string (frame->hd.type));
h2_debug (io, data, "[SEND] [%s]", soup_http2_frame_type_to_string (frame->hd.type));
break;
}
......@@ -985,7 +886,7 @@ on_frame_not_send_callback (nghttp2_session *session,
SoupClientMessageIOHTTP2 *io = user_data;
SoupHTTP2MessageData *data = nghttp2_session_get_stream_user_data (session, frame->hd.stream_id);
h2_debug (io, data, "[SEND] [%s] Failed: %s", frame_type_to_string (frame->hd.type),
h2_debug (io, data, "[SEND] [%s] Failed: %s", soup_http2_frame_type_to_string (frame->hd.type),
nghttp2_strerror (lib_error_code));
if (lib_error_code == NGHTTP2_ERR_SESSION_CLOSING)
......@@ -1327,24 +1228,6 @@ request_header_is_valid (const char *name)
return !g_hash_table_contains (invalid_request_headers, name);
}
#define MAKE_NV(NAME, VALUE, VALUELEN) \
{ \
(uint8_t *)NAME, (uint8_t *)VALUE, strlen (NAME), VALUELEN, \
NGHTTP2_NV_FLAG_NONE \
}
#define MAKE_NV2(NAME, VALUE) \
{ \
(uint8_t *)NAME, (uint8_t *)VALUE, strlen (NAME), strlen (VALUE), \
NGHTTP2_NV_FLAG_NONE \
}
#define MAKE_NV3(NAME, VALUE, FLAGS) \
{ \
(uint8_t *)NAME, (uint8_t *)VALUE, strlen (NAME), strlen (VALUE), \
FLAGS \
}
static void
send_message_request (SoupMessage *msg,
SoupClientMessageIOHTTP2 *io,
......@@ -1871,33 +1754,10 @@ static const SoupClientMessageIOFuncs io_funcs = {
soup_client_message_io_http2_owner_changed
};
G_GNUC_PRINTF(1, 0)
static void
debug_nghttp2 (const char *format,
va_list args)
{
char *message;
gsize len;
if (g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, "nghttp2"))
return;
message = g_strdup_vprintf (format, args);
len = strlen (message);
if (len >= 1 && message[len - 1] == '\n')
message[len - 1] = '\0';
g_log ("nghttp2", G_LOG_LEVEL_DEBUG, "[NGHTTP2] %s", message);
g_free (message);
}
static void
soup_client_message_io_http2_init (SoupClientMessageIOHTTP2 *io)
{
static gsize nghttp2_debug_init = 0;
if (g_once_init_enter (&nghttp2_debug_init)) {
nghttp2_set_debug_vprintf_callback(debug_nghttp2);
g_once_init_leave (&nghttp2_debug_init, 1);
}
soup_http2_debug_init ();
nghttp2_session_callbacks *callbacks;
NGCHECK (nghttp2_session_callbacks_new (&callbacks));
......
......@@ -42,15 +42,18 @@ soup_sources = [
'http2/soup-client-message-io-http2.c',
'http2/soup-body-input-stream-http2.c',
'server/http1/soup-server-message-io-http1.c',
'server/http2/soup-server-message-io-http2.c',
'server/soup-auth-domain.c',
'server/soup-auth-domain-basic.c',
'server/soup-auth-domain-digest.c',
'server/soup-listener.c',
'server/soup-message-body.c',
'server/soup-path-map.c',
'server/soup-server.c',
'server/soup-server-io.c',
'server/soup-server-connection.c',
'server/soup-server-message.c',
'server/soup-socket.c',
'server/soup-server-message-io.c',
'websocket/soup-websocket.c',
'websocket/soup-websocket-connection.c',
......@@ -67,6 +70,7 @@ soup_sources = [
'soup-form.c',
'soup-headers.c',
'soup-header-names.c',
'soup-http2-utils.c',
'soup-init.c',
'soup-io-stream.c',
'soup-logger.c',
......@@ -200,6 +204,8 @@ libsoup_includes = [
'http1',
'http2',
'server',
'server/http1',
'server/http2',
'websocket',
'.'
]),
......@@ -212,7 +218,6 @@ libsoup = library('soup-@0@'.format(apiversion),
soup_enums,
],
version : libversion,
soversion : soversion,
darwin_versions: darwin_versions,
c_args : libsoup_c_args,
include_directories : libsoup_includes,
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2022 Igalia S.L.
*/
#pragma once
#include "soup-server-connection.h"
#include "soup-server-message-io.h"
SoupServerMessageIO *soup_server_message_io_http1_new (SoupServerConnection *conn,
SoupServerMessage *msg,
SoupMessageIOStartedFn started_cb,
gpointer user_data);
This diff is collapsed.
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2022 Igalia S.L.
*/
#pragma once
#include "soup-server-connection.h"
#include "soup-server-message-io.h"
SoupServerMessageIO *soup_server_message_io_http2_new (SoupServerConnection *conn,
SoupServerMessage *msg,
SoupMessageIOStartedFn started_cb,
gpointer user_data);
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/*
* soup-listener.c: Socket listening networking code.
*
* Copyright (C) 2022 Igalia S.L.
* Copyright (C) 2000-2003, Ximian, Inc.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <glib/gi18n-lib.h>
#include <gio/gnetworking.h>
#include "soup-listener.h"
#include "soup.h"
#include "soup-io-stream.h"
#include "soup-server-connection.h"
enum {
NEW_CONNECTION,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
enum {
PROP_0,
PROP_SOCKET,
PROP_TLS_CERTIFICATE,
PROP_TLS_DATABASE,
PROP_TLS_AUTH_MODE,
LAST_PROPERTY
};
static GParamSpec *properties[LAST_PROPERTY] = { NULL, };
struct _SoupListener {
GObject parent_instance;
};
typedef struct {
GSocket *socket;
GIOStream *conn;
GIOStream *iostream;
GInetSocketAddress *local_addr;
GTlsCertificate *tls_certificate;
GTlsDatabase *tls_database;
GTlsAuthenticationMode tls_auth_mode;
GSource *source;
} SoupListenerPrivate;
G_DEFINE_FINAL_TYPE_WITH_PRIVATE (SoupListener, soup_listener, G_TYPE_OBJECT)
static void
soup_listener_init (SoupListener *listener)
{
}
static gboolean
listen_watch (GObject *pollable,
SoupListener *listener)
{
SoupListenerPrivate *priv = soup_listener_get_instance_private (listener);
GSocket *socket;
SoupServerConnection *conn;
socket = g_socket_accept (priv->socket, NULL, NULL);
if (!socket)
return G_SOURCE_REMOVE;
conn = soup_server_connection_new (socket, priv->tls_certificate, priv->tls_database, priv->tls_auth_mode);
g_signal_emit (listener, signals[NEW_CONNECTION], 0, conn);
g_object_unref (conn);
return G_SOURCE_CONTINUE;
}
static void
soup_listener_constructed (GObject *object)
{
SoupListener *listener = SOUP_LISTENER (object);
SoupListenerPrivate *priv = soup_listener_get_instance_private (listener);
g_socket_set_option (priv->socket, IPPROTO_TCP, TCP_NODELAY, TRUE, NULL);
priv->conn = (GIOStream *)g_socket_connection_factory_create_connection (priv->socket);
priv->iostream = soup_io_stream_new (priv->conn, FALSE);
priv->source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (g_io_stream_get_input_stream (priv->iostream)), NULL);
g_source_set_callback (priv->source, (GSourceFunc)listen_watch, listener, NULL);
g_source_attach (priv->source, g_main_context_get_thread_default ());
G_OBJECT_CLASS (soup_listener_parent_class)->constructed (object);
}
static void
soup_listener_finalize (GObject *object)
{
SoupListener *listener = SOUP_LISTENER (object);
SoupListenerPrivate *priv = soup_listener_get_instance_private (listener);
if (priv->conn) {
g_io_stream_close (priv->conn, NULL, NULL);
g_clear_object (&priv->conn);
}
g_clear_object (&priv->socket);
g_clear_object (&priv->iostream);
g_clear_object (&priv->tls_certificate);
g_clear_object (&priv->tls_database);
if (priv->source) {
g_source_destroy (priv->source);
g_source_unref (priv->source);
}
G_OBJECT_CLASS (soup_listener_parent_class)->finalize (object);
}
static void
soup_listener_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
SoupListener *listener = SOUP_LISTENER (object);
SoupListenerPrivate *priv = soup_listener_get_instance_private (listener);
switch (prop_id) {
case PROP_SOCKET:
priv->socket = g_value_dup_object (value);
break;
case PROP_TLS_CERTIFICATE:
priv->tls_certificate = g_value_dup_object (value);
break;
case PROP_TLS_DATABASE:
priv->tls_database = g_value_dup_object (value);
break;
case PROP_TLS_AUTH_MODE:
priv->tls_auth_mode = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
soup_listener_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
SoupListener *listener = SOUP_LISTENER (object);
SoupListenerPrivate *priv = soup_listener_get_instance_private (listener);
switch (prop_id) {
case PROP_SOCKET:
g_value_set_object (value, priv->socket);
break;
case PROP_TLS_CERTIFICATE:
g_value_set_object (value, priv->tls_certificate);
break;
case PROP_TLS_DATABASE:
g_value_set_object (value, priv->tls_database);
break;
case PROP_TLS_AUTH_MODE:
g_value_set_enum (value, priv->tls_auth_mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
soup_listener_class_init (SoupListenerClass *listener_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (listener_class);
object_class->constructed = soup_listener_constructed;
object_class->finalize = soup_listener_finalize;
object_class->set_property = soup_listener_set_property;
object_class->get_property = soup_listener_get_property;
/**
* SoupListener::new-connection:
* @listener: the listener
* @conn: the new connection
*
* Emitted when a listening socket receives a new connection.
*
* You must ref the @new if you want to keep it; otherwise it
* will be destroyed after the signal is emitted.
**/
signals[NEW_CONNECTION] =
g_signal_new ("new-connection",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 1,
SOUP_TYPE_SERVER_CONNECTION);
/* properties */
properties[PROP_SOCKET] =
g_param_spec_object ("socket",
"Socket",
"The underlying GSocket",
G_TYPE_SOCKET,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
properties[PROP_TLS_CERTIFICATE] =
g_param_spec_object ("tls-certificate",
"TLS Certificate",
"The server TLS certificate",
G_TYPE_TLS_CERTIFICATE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
properties[PROP_TLS_DATABASE] =
g_param_spec_object ("tls-database",
"TLS Database",
"The server TLS database",
G_TYPE_TLS_DATABASE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
properties[PROP_TLS_AUTH_MODE] =
g_param_spec_enum ("tls-auth-mode",
"TLS Authentication Mode",
"The server TLS authentication mode",
G_TYPE_TLS_AUTHENTICATION_MODE,
G_TLS_AUTHENTICATION_NONE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, LAST_PROPERTY, properties);
}
SoupListener *
soup_listener_new (GSocket *socket,
GError **error)
{
int listening;
g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
if (!g_socket_get_option (socket, SOL_SOCKET, SO_ACCEPTCONN, &listening, error)) {
g_prefix_error (error, _("Could not import existing socket: "));
return NULL;
}
if (!listening && !g_socket_is_connected (socket)) {
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Can’t import unconnected socket"));
return NULL;
}
return g_object_new (SOUP_TYPE_LISTENER, "socket", socket, NULL);
}
SoupListener *
soup_listener_new_for_address (GSocketAddress *address,
GError **error)
{
GSocket *socket;
GSocketFamily family;
SoupListener *listener;
g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
family = g_socket_address_get_family (address);
socket = g_socket_new (family, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, error);
if (!socket)
return NULL;
if (family == G_SOCKET_FAMILY_IPV6) {
GError *option_error = NULL;
g_socket_set_option (socket, IPPROTO_IPV6, IPV6_V6ONLY, TRUE, &option_error);
if (option_error) {
g_warning ("Failed to set IPv6 only on socket: %s", option_error->message);
g_error_free (option_error);
}
}
if (!g_socket_bind (socket, address, TRUE, error)) {
g_object_unref (socket);
return NULL;
}
if (!g_socket_listen (socket, error)) {
g_object_unref (socket);
return NULL;
}
listener = g_object_new (SOUP_TYPE_LISTENER, "socket", socket, NULL);
g_object_unref (socket);
return listener;
}
GSocket *
soup_listener_get_socket (SoupListener *listener)
{
SoupListenerPrivate *priv;
g_return_val_if_fail (SOUP_IS_LISTENER (listener), NULL);
priv = soup_listener_get_instance_private (listener);
return priv->socket;
}
void
soup_listener_disconnect (SoupListener *listener)
{
SoupListenerPrivate *priv;
g_return_if_fail (SOUP_IS_LISTENER (listener));
priv = soup_listener_get_instance_private (listener);
g_clear_object (&priv->socket);
if (priv->conn) {
g_io_stream_close (priv->conn, NULL, NULL);
g_clear_object (&priv->conn);
}
}
gboolean
soup_listener_is_ssl (SoupListener *listener)
{
SoupListenerPrivate *priv;
g_return_val_if_fail (SOUP_IS_LISTENER (listener), FALSE);
priv = soup_listener_get_instance_private (listener);
return priv->tls_certificate != NULL;
}
GInetSocketAddress *
soup_listener_get_address (SoupListener *listener)
{
SoupListenerPrivate *priv;
g_return_val_if_fail (SOUP_IS_LISTENER (listener), NULL);
priv = soup_listener_get_instance_private (listener);
if (!priv->local_addr) {
GError *error = NULL;
priv->local_addr = G_INET_SOCKET_ADDRESS (g_socket_get_local_address (priv->socket, &error));
if (priv->local_addr == NULL) {
g_warning ("%s: %s", G_STRLOC, error->message);
g_error_free (error);
return NULL;
}
}
return priv->local_addr;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2022 Igalia S.L.
* Copyright (C) 2000-2003, Ximian, Inc.
*/
#pragma once
#include "soup-types.h"
G_BEGIN_DECLS
#define SOUP_TYPE_LISTENER (soup_listener_get_type ())
G_DECLARE_FINAL_TYPE (SoupListener, soup_listener, SOUP, LISTENER, GObject)
SoupListener *soup_listener_new (GSocket *socket,
GError **error);
SoupListener *soup_listener_new_for_address (GSocketAddress *address,
GError **error);
void soup_listener_disconnect (SoupListener *listener);
gboolean soup_listener_is_ssl (SoupListener *listener);
GSocket *soup_listener_get_socket (SoupListener *listener);
GInetSocketAddress *soup_listener_get_address (SoupListener *listener);
G_END_DECLS
This diff is collapsed.
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2022 Igalia S.L.
* Copyright (C) 2000-2003, Ximian, Inc.
*/
#pragma once
#include "soup-types.h"
#include "soup-server-message-io.h"
#include <gio/gio.h>
G_BEGIN_DECLS
#define SOUP_TYPE_SERVER_CONNECTION (soup_server_connection_get_type ())
G_DECLARE_FINAL_TYPE (SoupServerConnection, soup_server_connection, SOUP, SERVER_CONNECTION, GObject)
SoupServerConnection *soup_server_connection_new (GSocket *socket,
GTlsCertificate *tls_certificate,
GTlsDatabase *tls_database,
GTlsAuthenticationMode tls_auth_mode);
SoupServerConnection *soup_server_connection_new_for_connection (GIOStream *connection,
GSocketAddress *local_addr,
GSocketAddress *remote_addr);
void soup_server_connection_set_advertise_http2 (SoupServerConnection *conn,
gboolean advertise_http2);
void soup_server_connection_accepted (SoupServerConnection *conn);
SoupServerMessageIO *soup_server_connection_get_io_data (SoupServerConnection *conn);
gboolean soup_server_connection_is_ssl (SoupServerConnection *conn);
void soup_server_connection_disconnect (SoupServerConnection *conn);
gboolean soup_server_connection_is_connected (SoupServerConnection *conn);
GSocket *soup_server_connection_get_socket (SoupServerConnection *conn);
GSocket *soup_server_connection_steal_socket (SoupServerConnection *conn);
GIOStream *soup_server_connection_get_iostream (SoupServerConnection *conn);
GSocketAddress *soup_server_connection_get_local_address (SoupServerConnection *conn);
GSocketAddress *soup_server_connection_get_remote_address (SoupServerConnection *conn);
GTlsCertificate *soup_server_connection_get_tls_peer_certificate (SoupServerConnection *conn);
GTlsCertificateFlags soup_server_connection_get_tls_peer_certificate_errors (SoupServerConnection *conn);
G_END_DECLS
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2022 Igalia S.L.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "soup-server-message-io.h"
void
soup_server_message_io_destroy (SoupServerMessageIO *io)
{
if (!io)
return;
io->funcs->destroy (io);
}
void
soup_server_message_io_finished (SoupServerMessageIO *io,
SoupServerMessage *msg)
{
io->funcs->finished (io, msg);
}
GIOStream *
soup_server_message_io_steal (SoupServerMessageIO *io)
{
return io->funcs->steal (io);
}
void
soup_server_message_io_read_request (SoupServerMessageIO *io,
SoupServerMessage *msg,
SoupMessageIOCompletionFn completion_cb,
gpointer user_data)
{
io->funcs->read_request (io, msg, completion_cb, user_data);
}
void
soup_server_message_io_pause (SoupServerMessageIO *io,
SoupServerMessage *msg)
{
io->funcs->pause (io, msg);
}
void
soup_server_message_io_unpause (SoupServerMessageIO *io,
SoupServerMessage *msg)
{
io->funcs->unpause (io, msg);
}
gboolean
soup_server_message_io_is_paused (SoupServerMessageIO *io,
SoupServerMessage *msg)
{
return io->funcs->is_paused (io, msg);
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2022 Igalia S.L.
*/
#pragma once
#include "soup-server-message.h"
#include "soup-message-io-completion.h"
typedef struct _SoupServerMessageIO SoupServerMessageIO;
typedef struct {
void (*destroy) (SoupServerMessageIO *io);
void (*finished) (SoupServerMessageIO *io,
SoupServerMessage *msg);
GIOStream *(*steal) (SoupServerMessageIO *io);
void (*read_request) (SoupServerMessageIO *io,
SoupServerMessage *msg,
SoupMessageIOCompletionFn completion_cb,
gpointer user_data);
void (*pause) (SoupServerMessageIO *io,
SoupServerMessage *msg);
void (*unpause) (SoupServerMessageIO *io,
SoupServerMessage *msg);
gboolean (*is_paused) (SoupServerMessageIO *io,
SoupServerMessage *msg);
} SoupServerMessageIOFuncs;
struct _SoupServerMessageIO {
const SoupServerMessageIOFuncs *funcs;
};
typedef void (* SoupMessageIOStartedFn) (SoupServerMessage *msg,
gpointer user_data);
void soup_server_message_io_destroy (SoupServerMessageIO *io);
void soup_server_message_io_finished (SoupServerMessageIO *io,
SoupServerMessage *msg);
GIOStream *soup_server_message_io_steal (SoupServerMessageIO *io);
void soup_server_message_io_read_request (SoupServerMessageIO *io,
SoupServerMessage *msg,
SoupMessageIOCompletionFn completion_cb,
gpointer user_data);
void soup_server_message_io_pause (SoupServerMessageIO *io,
SoupServerMessage *msg);
void soup_server_message_io_unpause (SoupServerMessageIO *io,
SoupServerMessage *msg);
gboolean soup_server_message_io_is_paused (SoupServerMessageIO *io,
SoupServerMessage *msg);
......@@ -8,23 +8,20 @@
#include "soup-server-message.h"
#include "soup-auth-domain.h"
#include "soup-message-io-data.h"
#include "soup-socket.h"
#include "soup-server-connection.h"
SoupServerMessage *soup_server_message_new (SoupSocket *sock);
SoupServerMessage *soup_server_message_new (SoupServerConnection *conn);
void soup_server_message_set_uri (SoupServerMessage *msg,
GUri *uri);
void soup_server_message_set_method (SoupServerMessage *msg,
const char *method);
SoupSocket *soup_server_message_get_soup_socket (SoupServerMessage *msg);
SoupServerConnection *soup_server_message_get_connection (SoupServerMessage *msg);
void soup_server_message_set_auth (SoupServerMessage *msg,
SoupAuthDomain *domain,
char *user);
gboolean soup_server_message_is_keepalive (SoupServerMessage *msg);
GIOStream *soup_server_message_io_steal (SoupServerMessage *msg);
void soup_server_message_io_pause (SoupServerMessage *msg);
void soup_server_message_io_unpause (SoupServerMessage *msg);
gboolean soup_server_message_is_io_paused (SoupServerMessage *msg);
void soup_server_message_io_finished (SoupServerMessage *msg);
void soup_server_message_finish (SoupServerMessage *msg);
void soup_server_message_cleanup_response (SoupServerMessage *msg);
void soup_server_message_wrote_informational (SoupServerMessage *msg);
void soup_server_message_wrote_headers (SoupServerMessage *msg);
......@@ -40,13 +37,11 @@ void soup_server_message_finished (SoupServerMessage
void soup_server_message_read_request (SoupServerMessage *msg,
SoupMessageIOCompletionFn completion_cb,
gpointer user_data);
void soup_server_message_set_options_ping (SoupServerMessage *msg,
gboolean is_options_ping);
typedef struct _SoupServerMessageIOData SoupServerMessageIOData;
void soup_server_message_io_data_free (SoupServerMessageIOData *io);
void soup_server_message_set_io_data (SoupServerMessage *msg,
SoupServerMessageIOData *io);
SoupServerMessageIOData *soup_server_message_get_io_data (SoupServerMessage *msg);
SoupServerMessageIO *soup_server_message_get_io_data (SoupServerMessage *msg);
#endif /* __SOUP_SERVER_MESSAGE_PRIVATE_H__ */
......@@ -15,7 +15,6 @@
#include "soup-connection.h"
#include "soup-server-message-private.h"
#include "soup-message-headers-private.h"
#include "soup-socket.h"
#include "soup-uri-utils-private.h"
/**
......@@ -38,14 +37,11 @@
struct _SoupServerMessage {
GObject parent;
SoupSocket *sock;
GSocket *gsock;
SoupServerConnection *conn;
SoupAuthDomain *auth_domain;
char *auth_user;
GSocketAddress *remote_addr;
char *remote_ip;
GSocketAddress *local_addr;
const char *method;
SoupHTTPVersion http_version;
......@@ -62,7 +58,7 @@ struct _SoupServerMessage {
SoupMessageBody *response_body;
SoupMessageHeaders *response_headers;
SoupServerMessageIOData *io_data;
SoupServerMessageIO *io_data;
gboolean options_ping;
......@@ -87,6 +83,7 @@ enum {
GOT_CHUNK,
GOT_BODY,
CONNECTED,
DISCONNECTED,
FINISHED,
......@@ -123,18 +120,13 @@ soup_server_message_finalize (GObject *object)
{
SoupServerMessage *msg = SOUP_SERVER_MESSAGE (object);
soup_server_message_io_data_free (msg->io_data);
g_clear_object (&msg->auth_domain);
g_clear_pointer (&msg->auth_user, g_free);
g_clear_object (&msg->remote_addr);
g_clear_object (&msg->local_addr);
if (msg->sock) {
g_signal_handlers_disconnect_by_data (msg->sock, msg);
g_object_unref (msg->sock);
if (msg->conn) {
g_signal_handlers_disconnect_by_data (msg->conn, msg);
g_object_unref (msg->conn);
}
g_clear_object (&msg->gsock);
g_clear_pointer (&msg->remote_ip, g_free);
g_clear_pointer (&msg->uri, g_uri_unref);
......@@ -327,6 +319,20 @@ soup_server_message_class_init (SoupServerMessageClass *klass)
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
/**
* SoupServerMessage::connected:
* @msg: the message
*
* Emitted when the @msg's socket is connected and the TLS handshake completed.
*/
signals[CONNECTED] =
g_signal_new ("connected",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
/**
* SoupServerMessage::disconnected:
......@@ -403,15 +409,24 @@ soup_server_message_class_init (SoupServerMessageClass *klass)
}
static void
socket_disconnected (SoupServerMessage *msg)
connection_connected (SoupServerMessage *msg)
{
g_assert (!msg->io_data);
msg->io_data = soup_server_connection_get_io_data (msg->conn);
g_signal_emit (msg, signals[CONNECTED], 0);
}
static void
connection_disconnected (SoupServerMessage *msg)
{
msg->io_data = NULL;
g_signal_emit (msg, signals[DISCONNECTED], 0);
}
static gboolean
socket_accept_certificate (SoupServerMessage *msg,
GTlsCertificate *tls_certificate,
GTlsCertificateFlags *tls_errors)
connection_accept_certificate (SoupServerMessage *msg,
GTlsCertificate *tls_certificate,
GTlsCertificateFlags *tls_errors)
{
gboolean accept = FALSE;
......@@ -436,33 +451,34 @@ soup_server_message_set_tls_peer_certificate (SoupServerMessage *msg,
}
static void
re_emit_tls_certificate_changed (SoupServerMessage *msg,
GParamSpec *pspec,
SoupSocket *sock)
re_emit_tls_certificate_changed (SoupServerMessage *msg,
GParamSpec *pspec,
SoupServerConnection *conn)
{
soup_server_message_set_tls_peer_certificate (msg,
soup_socket_get_tls_certificate (sock),
soup_socket_get_tls_certificate_errors (sock));
soup_server_connection_get_tls_peer_certificate (conn),
soup_server_connection_get_tls_peer_certificate_errors (conn));
}
SoupServerMessage *
soup_server_message_new (SoupSocket *sock)
soup_server_message_new (SoupServerConnection *conn)
{
SoupServerMessage *msg;
msg = g_object_new (SOUP_TYPE_SERVER_MESSAGE, NULL);
msg->sock = g_object_ref (sock);
msg->gsock = soup_socket_get_gsocket (sock);
if (msg->gsock)
g_object_ref (msg->gsock);
msg->conn = g_object_ref (conn);
msg->io_data = soup_server_connection_get_io_data (msg->conn);
g_signal_connect_object (sock, "disconnected",
G_CALLBACK (socket_disconnected),
g_signal_connect_object (conn, "connected",
G_CALLBACK (connection_connected),
msg, G_CONNECT_SWAPPED);
g_signal_connect_object (sock, "accept-certificate",
G_CALLBACK (socket_accept_certificate),
g_signal_connect_object (conn, "disconnected",
G_CALLBACK (connection_disconnected),
msg, G_CONNECT_SWAPPED);
g_signal_connect_object (sock, "notify::tls-certificate",
g_signal_connect_object (conn, "accept-certificate",
G_CALLBACK (connection_accept_certificate),
msg, G_CONNECT_SWAPPED);
g_signal_connect_object (conn, "notify::tls-certificate",
G_CALLBACK (re_emit_tls_certificate_changed),
msg, G_CONNECT_SWAPPED);
......@@ -478,10 +494,10 @@ soup_server_message_set_uri (SoupServerMessage *msg,
msg->uri = soup_uri_copy_with_normalized_flags (uri);
}
SoupSocket *
soup_server_message_get_soup_socket (SoupServerMessage *msg)
SoupServerConnection *
soup_server_message_get_connection (SoupServerMessage *msg)
{
return msg->sock;
return msg->conn;
}
void
......@@ -501,6 +517,9 @@ soup_server_message_set_auth (SoupServerMessage *msg,
gboolean
soup_server_message_is_keepalive (SoupServerMessage *msg)
{
if (msg->http_version == SOUP_HTTP_2_0)
return TRUE;
if (msg->status_code == SOUP_STATUS_OK && msg->method == SOUP_METHOD_CONNECT)
return TRUE;
......@@ -536,19 +555,76 @@ soup_server_message_is_keepalive (SoupServerMessage *msg)
}
void
soup_server_message_set_io_data (SoupServerMessage *msg,
SoupServerMessageIOData *io)
soup_server_message_read_request (SoupServerMessage *msg,
SoupMessageIOCompletionFn completion_cb,
gpointer user_data)
{
soup_server_message_io_data_free (msg->io_data);
msg->io_data = io;
soup_server_message_io_read_request (msg->io_data, msg, completion_cb, user_data);
}
SoupServerMessageIOData *
SoupServerMessageIO *
soup_server_message_get_io_data (SoupServerMessage *msg)
{
return msg->io_data;
}
/**
* soup_server_message_pause:
* @msg: a SoupServerMessage
*
* Pauses I/O on @msg.
*
* This can be used when you need to return from the server handler without
* having the full response ready yet. Use [method@ServerMessage.unpause] to
* resume I/O.
*
* Since: 3.2
*/
void
soup_server_message_pause (SoupServerMessage *msg)
{
g_return_if_fail (SOUP_IS_SERVER_MESSAGE (msg));
g_return_if_fail (msg->io_data != NULL);
soup_server_message_io_pause (msg->io_data, msg);
}
/**
* soup_server_message_unpause:
* @msg: a SoupServerMessage
*
* Resumes I/O on @msg.
*
* Use this to resume after calling [method@ServerMessage.pause], or after
* adding a new chunk to a chunked response. I/O won't actually resume until you
* return to the main loop.
*
* Since: 3.2
*/
void
soup_server_message_unpause (SoupServerMessage *msg)
{
g_return_if_fail (SOUP_IS_SERVER_MESSAGE (msg));
g_return_if_fail (msg->io_data != NULL);
soup_server_message_io_unpause (msg->io_data, msg);
}
gboolean
soup_server_message_is_io_paused (SoupServerMessage *msg)
{
return msg->io_data && soup_server_message_io_is_paused (msg->io_data, msg);
}
void
soup_server_message_finish (SoupServerMessage *msg)
{
if (!msg->io_data)
return;
soup_server_message_io_finished (g_steal_pointer (&msg->io_data), msg);
}
void
soup_server_message_cleanup_response (SoupServerMessage *msg)
{
......@@ -930,7 +1006,7 @@ soup_server_message_get_socket (SoupServerMessage *msg)
{
g_return_val_if_fail (SOUP_IS_SERVER_MESSAGE (msg), NULL);
return msg->gsock;
return soup_server_connection_get_socket (msg->conn);
}
/**
......@@ -949,14 +1025,7 @@ soup_server_message_get_remote_address (SoupServerMessage *msg)
{
g_return_val_if_fail (SOUP_IS_SERVER_MESSAGE (msg), NULL);
if (msg->remote_addr)
return msg->remote_addr;
msg->remote_addr = msg->gsock ?
g_socket_get_remote_address (msg->gsock, NULL) :
G_SOCKET_ADDRESS (g_object_ref (soup_socket_get_remote_address (msg->sock)));
return msg->remote_addr;
return soup_server_connection_get_remote_address (msg->conn);
}
/**
......@@ -975,14 +1044,7 @@ soup_server_message_get_local_address (SoupServerMessage *msg)
{
g_return_val_if_fail (SOUP_IS_SERVER_MESSAGE (msg), NULL);
if (msg->local_addr)
return msg->local_addr;
msg->local_addr = msg->gsock ?
g_socket_get_local_address (msg->gsock, NULL) :
G_SOCKET_ADDRESS (g_object_ref (soup_socket_get_local_address (msg->sock)));
return msg->local_addr;
return soup_server_connection_get_local_address (msg->conn);
}
/**
......@@ -1001,21 +1063,15 @@ soup_server_message_get_remote_host (SoupServerMessage *msg)
{
g_return_val_if_fail (SOUP_IS_SERVER_MESSAGE (msg), NULL);
if (msg->remote_ip)
return msg->remote_ip;
if (msg->gsock) {
GSocketAddress *addr = soup_server_message_get_remote_address (msg);
if (!msg->remote_ip) {
GSocketAddress *addr = soup_server_connection_get_remote_address (msg->conn);
GInetAddress *iaddr;
if (!addr || !G_IS_INET_SOCKET_ADDRESS (addr))
return NULL;
iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr));
msg->remote_ip = g_inet_address_to_string (iaddr);
} else {
GInetSocketAddress *addr = G_INET_SOCKET_ADDRESS (soup_socket_get_remote_address (msg->sock));
GInetAddress *inet_addr = g_inet_socket_address_get_address (addr);
msg->remote_ip = g_inet_address_to_string (inet_addr);
}
return msg->remote_ip;
......@@ -1047,16 +1103,16 @@ soup_server_message_steal_connection (SoupServerMessage *msg)
GIOStream *stream;
g_object_ref (msg);
stream = soup_server_message_io_steal (msg);
stream = msg->io_data ? soup_server_message_io_steal (g_steal_pointer (&msg->io_data)) : NULL;
if (stream) {
g_object_set_data_full (G_OBJECT (stream), "GSocket",
soup_socket_steal_gsocket (msg->sock),
soup_server_connection_steal_socket (msg->conn),
g_object_unref);
}
g_signal_handlers_disconnect_by_data (msg, msg->sock);
g_signal_handlers_disconnect_by_data (msg, msg->conn);
socket_disconnected (msg);
connection_disconnected (msg);
g_object_unref (msg);
return stream;
......