[libsoup/wip/keepalive: 2/2] websocket: add api to add a keepalive interval



commit a4d097593e2ec058774446a927e5a4234905c265
Author: Ignacio Casal Quinteiro <icq gnome org>
Date:   Tue Oct 18 09:21:59 2016 +0200

    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

 libsoup/soup-websocket-connection.c |  111 +++++++++++++++++++++++++++++++++++
 libsoup/soup-websocket-connection.h |    7 ++
 2 files changed, 118 insertions(+), 0 deletions(-)
---
diff --git a/libsoup/soup-websocket-connection.c b/libsoup/soup-websocket-connection.c
index 4625716..8494733 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;
+       gint 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) {
@@ -998,6 +1015,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_int (value, pv->keepalive_interval);
+               break;
+
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
@@ -1042,6 +1063,10 @@ soup_websocket_connection_set_property (GObject *object,
                pv->max_incoming_payload_size = g_value_get_uint64 (value);
                break;
 
+       case PROP_KEEPALIVE_INTERVAL:
+               pv->keepalive_interval = g_value_get_int (value);
+               break;
+
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
@@ -1080,6 +1105,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 +1255,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 -1 the keepalive message is
+        * disabled.
+        *
+        * Since: 2.58
+        */
+       g_object_class_install_property (gobject_class, PROP_KEEPALIVE_INTERVAL,
+                                        g_param_spec_int ("keepalive-interval",
+                                                          "Keepalive interval",
+                                                          "Keepalive interval",
+                                                          -1,
+                                                          G_MAXINT,
+                                                          -1,
+                                                          G_PARAM_READWRITE |
+                                                          G_PARAM_CONSTRUCT |
+                                                          G_PARAM_STATIC_STRINGS));
+
+       /**
         * SoupWebsocketConnection::message:
         * @self: the WebSocket
         * @type: the type of message contents
@@ -1647,3 +1693,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 -1 if disabled.
+ *
+ * Returns: the keepalive interval.
+ *
+ * Since: 2.58
+ */
+gint
+soup_websocket_connection_get_keepalive_interval (SoupWebsocketConnection *self)
+{
+       SoupWebsocketConnectionPrivate *pv;
+
+       g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), -1);
+       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_URGENT, 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 -1 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 -1 the keepalive message is disabled.
+ *
+ * Since: 2.58
+ */
+void
+soup_websocket_connection_set_keepalive_interval (SoupWebsocketConnection *self,
+                                                  gint                     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 9d72e13..4532b58 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
+gint                soup_websocket_connection_get_keepalive_interval (SoupWebsocketConnection *self);
+
+SOUP_AVAILABLE_IN_2_58
+void                soup_websocket_connection_set_keepalive_interval (SoupWebsocketConnection *self,
+                                                                      gint                     interval);
+
 G_END_DECLS
 
 #endif /* __SOUP_WEBSOCKET_CONNECTION_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]