summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgnacio Casal Quinteiro <icq@gnome.org>2016-10-18 09:21:59 +0200
committerIgnacio Casal Quinteiro <icq@gnome.org>2016-11-03 18:06:52 +0100
commit6fcd8c529439120282b8f24f49e92cde111929e3 (patch)
tree799b0426e6deae982461681a50c0eb319862d000
parent0554ac66dbcbede67df5e664ce925a29fc711bb1 (diff)
downloadlibsoup-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.c114
-rw-r--r--libsoup/soup-websocket-connection.h7
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__ */