diff options
author | Ignacio Casal Quinteiro <icq@gnome.org> | 2016-10-18 09:21:59 +0200 |
---|---|---|
committer | Ignacio Casal Quinteiro <icq@gnome.org> | 2016-11-03 18:06:52 +0100 |
commit | 6fcd8c529439120282b8f24f49e92cde111929e3 (patch) | |
tree | 799b0426e6deae982461681a50c0eb319862d000 | |
parent | 0554ac66dbcbede67df5e664ce925a29fc711bb1 (diff) | |
download | libsoup-6fcd8c529439120282b8f24f49e92cde111929e3.tar.gz |
websocket: add api to add a keepalive interval
This will send ping messages in that interval of time so the connection
is kept alive.
https://bugzilla.gnome.org/show_bug.cgi?id=773253
-rw-r--r-- | libsoup/soup-websocket-connection.c | 114 | ||||
-rw-r--r-- | libsoup/soup-websocket-connection.h | 7 |
2 files changed, 121 insertions, 0 deletions
diff --git a/libsoup/soup-websocket-connection.c b/libsoup/soup-websocket-connection.c index 46257168..66742a1f 100644 --- a/libsoup/soup-websocket-connection.c +++ b/libsoup/soup-websocket-connection.c @@ -81,6 +81,7 @@ enum { PROP_PROTOCOL, PROP_STATE, PROP_MAX_INCOMING_PAYLOAD_SIZE, + PROP_KEEPALIVE_INTERVAL, }; enum { @@ -107,6 +108,7 @@ struct _SoupWebsocketConnectionPrivate { char *origin; char *protocol; guint64 max_incoming_payload_size; + guint keepalive_interval; gushort peer_close_code; char *peer_close_data; @@ -131,6 +133,8 @@ struct _SoupWebsocketConnectionPrivate { /* Current message being assembled */ guint8 message_opcode; GByteArray *message_data; + + GSource *keepalive_timeout; }; #define MAX_INCOMING_PAYLOAD_SIZE_DEFAULT 128 * 1024 @@ -225,6 +229,18 @@ stop_output (SoupWebsocketConnection *self) } static void +keepalive_stop_timeout (SoupWebsocketConnection *self) +{ + SoupWebsocketConnectionPrivate *pv = self->pv; + + if (pv->keepalive_timeout) { + g_source_destroy (pv->keepalive_timeout); + g_source_unref (pv->keepalive_timeout); + pv->keepalive_timeout = NULL; + } +} + +static void close_io_stop_timeout (SoupWebsocketConnection *self) { SoupWebsocketConnectionPrivate *pv = self->pv; @@ -241,6 +257,7 @@ close_io_stream (SoupWebsocketConnection *self) { SoupWebsocketConnectionPrivate *pv = self->pv; + keepalive_stop_timeout (self); close_io_stop_timeout (self); if (!pv->io_closing) { @@ -411,6 +428,8 @@ send_close (SoupWebsocketConnection *self, send_message (self, flags, 0x08, (guint8 *)buffer, len); self->pv->close_sent = TRUE; + + keepalive_stop_timeout (self); } static void @@ -998,6 +1017,10 @@ soup_websocket_connection_get_property (GObject *object, g_value_set_uint64 (value, pv->max_incoming_payload_size); break; + case PROP_KEEPALIVE_INTERVAL: + g_value_set_uint (value, pv->keepalive_interval); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1042,6 +1065,11 @@ soup_websocket_connection_set_property (GObject *object, pv->max_incoming_payload_size = g_value_get_uint64 (value); break; + case PROP_KEEPALIVE_INTERVAL: + soup_websocket_connection_set_keepalive_interval (self, + g_value_get_uint (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1080,6 +1108,7 @@ soup_websocket_connection_finalize (GObject *object) g_assert (pv->io_closing); g_assert (pv->io_closed); g_assert (!pv->close_timeout); + g_assert (!pv->keepalive_timeout); if (pv->message_data) g_byte_array_free (pv->message_data, TRUE); @@ -1229,6 +1258,26 @@ soup_websocket_connection_class_init (SoupWebsocketConnectionClass *klass) G_PARAM_STATIC_STRINGS)); /** + * SoupWebsocketConnection:keepalive-interval: + * + * Interval in seconds on when to send a ping message which will + * serve as a keepalive message. If set to 0 the keepalive message is + * disabled. + * + * Since: 2.58 + */ + g_object_class_install_property (gobject_class, PROP_KEEPALIVE_INTERVAL, + g_param_spec_uint ("keepalive-interval", + "Keepalive interval", + "Keepalive interval", + 0, + G_MAXUINT, + 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** * SoupWebsocketConnection::message: * @self: the WebSocket * @type: the type of message contents @@ -1647,3 +1696,68 @@ soup_websocket_connection_set_max_incoming_payload_size (SoupWebsocketConnection g_object_notify (G_OBJECT (self), "max-incoming-payload-size"); } } + +/** + * soup_websocket_connection_get_keepalive_interval: + * @self: the WebSocket + * + * Gets the keepalive interval in seconds or 0 if disabled. + * + * Returns: the keepalive interval. + * + * Since: 2.58 + */ +guint +soup_websocket_connection_get_keepalive_interval (SoupWebsocketConnection *self) +{ + SoupWebsocketConnectionPrivate *pv; + + g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), 0); + pv = self->pv; + + return pv->keepalive_interval; +} + +static gboolean +on_queue_ping (gpointer user_data) +{ + SoupWebsocketConnection *self = SOUP_WEBSOCKET_CONNECTION (user_data); + + g_debug ("sending ping message"); + send_message (self, SOUP_WEBSOCKET_QUEUE_NORMAL, 0x09, NULL, 0); + + return G_SOURCE_CONTINUE; +} + +/** + * soup_websocket_connection_set_keepalive_interval: + * @self: the WebSocket + * @interval: the interval to send a ping message or 0 to disable it + * + * Sets the interval in seconds on when to send a ping message which will serve + * as a keepalive message. If set to 0 the keepalive message is disabled. + * + * Since: 2.58 + */ +void +soup_websocket_connection_set_keepalive_interval (SoupWebsocketConnection *self, + guint interval) +{ + SoupWebsocketConnectionPrivate *pv; + + g_return_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self)); + pv = self->pv; + + if (pv->keepalive_interval != interval) { + pv->keepalive_interval = interval; + g_object_notify (G_OBJECT (self), "keepalive-interval"); + + keepalive_stop_timeout (self); + + if (interval > 0) { + pv->keepalive_timeout = g_timeout_source_new_seconds (interval); + g_source_set_callback (pv->keepalive_timeout, on_queue_ping, self, NULL); + g_source_attach (pv->keepalive_timeout, pv->main_context); + } + } +} diff --git a/libsoup/soup-websocket-connection.h b/libsoup/soup-websocket-connection.h index 9d72e13d..ca9a6407 100644 --- a/libsoup/soup-websocket-connection.h +++ b/libsoup/soup-websocket-connection.h @@ -112,6 +112,13 @@ SOUP_AVAILABLE_IN_2_56 void soup_websocket_connection_set_max_incoming_payload_size (SoupWebsocketConnection *self, guint64 max_incoming_payload_size); +SOUP_AVAILABLE_IN_2_58 +guint soup_websocket_connection_get_keepalive_interval (SoupWebsocketConnection *self); + +SOUP_AVAILABLE_IN_2_58 +void soup_websocket_connection_set_keepalive_interval (SoupWebsocketConnection *self, + guint interval); + G_END_DECLS #endif /* __SOUP_WEBSOCKET_CONNECTION_H__ */ |