Commit 6fcd8c52 authored by Ignacio Casal Quinteiro's avatar Ignacio Casal Quinteiro
Browse files

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
parent 0554ac66
......@@ -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
......@@ -224,6 +228,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)
{
......@@ -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);
......@@ -1228,6 +1257,26 @@ soup_websocket_connection_class_init (SoupWebsocketConnectionClass *klass)
G_PARAM_CONSTRUCT |
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
......@@ -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);
}
}
}
......@@ -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__ */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment