[libsoup] Add max-incoming-payload-size property to the websocket connection.



commit d4c6819e7791e98d07d830927d5f55f935dc0b09
Author: Ignacio Casal Quinteiro <icq gnome org>
Date:   Wed Aug 17 09:17:49 2016 +0200

    Add max-incoming-payload-size property to the websocket connection.
    
    This allows to change the limit for the payload of websocket packets.
    Also add the corresponding unit test.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=770022

 libsoup/soup-websocket-connection.c |   85 +++++++++++++++++++++++++++++++++--
 libsoup/soup-websocket-connection.h |    7 +++
 tests/websocket-test.c              |   13 +++++
 3 files changed, 101 insertions(+), 4 deletions(-)
---
diff --git a/libsoup/soup-websocket-connection.c b/libsoup/soup-websocket-connection.c
index 622aa68..8901941 100644
--- a/libsoup/soup-websocket-connection.c
+++ b/libsoup/soup-websocket-connection.c
@@ -80,6 +80,7 @@ enum {
        PROP_ORIGIN,
        PROP_PROTOCOL,
        PROP_STATE,
+       PROP_MAX_INCOMING_PAYLOAD_SIZE,
 };
 
 enum {
@@ -105,6 +106,7 @@ struct _SoupWebsocketConnectionPrivate {
        SoupURI *uri;
        char *origin;
        char *protocol;
+       guint64 max_incoming_payload_size;
 
        gushort peer_close_code;
        char *peer_close_data;
@@ -131,7 +133,7 @@ struct _SoupWebsocketConnectionPrivate {
        GByteArray *message_data;
 };
 
-#define MAX_PAYLOAD   128 * 1024
+#define MAX_INCOMING_PAYLOAD_SIZE_DEFAULT   128 * 1024
 
 G_DEFINE_TYPE (SoupWebsocketConnection, soup_websocket_connection, G_TYPE_OBJECT)
 
@@ -500,9 +502,9 @@ too_big_error_and_close (SoupWebsocketConnection *self,
                                     self->pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER ?
                                     "Received extremely large WebSocket data from the client" :
                                     "Received extremely large WebSocket data from the server");
-       g_debug ("%s is trying to frame of size %" G_GUINT64_FORMAT " or greater, but max supported size is 
128KiB",
+       g_debug ("%s is trying to frame of size %" G_GUINT64_FORMAT " or greater, but max supported size is 
%" G_GUINT64_FORMAT,
                 self->pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER ? "server" : "client",
-                payload_len);
+                payload_len, self->pv->max_incoming_payload_size);
        emit_error_and_close (self, error, TRUE);
 
        /* The input is in an invalid state now */
@@ -728,7 +730,8 @@ process_frame (SoupWebsocketConnection *self)
        }
 
        /* Safety valve */
-       if (payload_len >= MAX_PAYLOAD) {
+       if (self->pv->max_incoming_payload_size > 0 &&
+           payload_len >= self->pv->max_incoming_payload_size) {
                too_big_error_and_close (self, payload_len);
                return FALSE;
        }
@@ -963,6 +966,7 @@ soup_websocket_connection_get_property (GObject *object,
                                        GParamSpec *pspec)
 {
        SoupWebsocketConnection *self = SOUP_WEBSOCKET_CONNECTION (object);
+       SoupWebsocketConnectionPrivate *pv = self->pv;
 
        switch (prop_id) {
        case PROP_IO_STREAM:
@@ -989,6 +993,10 @@ soup_websocket_connection_get_property (GObject *object,
                g_value_set_enum (value, soup_websocket_connection_get_state (self));
                break;
 
+       case PROP_MAX_INCOMING_PAYLOAD_SIZE:
+               g_value_set_uint64 (value, pv->max_incoming_payload_size);
+               break;
+
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
@@ -1029,6 +1037,10 @@ soup_websocket_connection_set_property (GObject *object,
                pv->protocol = g_value_dup_string (value);
                break;
 
+       case PROP_MAX_INCOMING_PAYLOAD_SIZE:
+               pv->max_incoming_payload_size = g_value_get_uint64 (value);
+               break;
+
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
@@ -1197,6 +1209,25 @@ soup_websocket_connection_class_init (SoupWebsocketConnectionClass *klass)
                                                            G_PARAM_STATIC_STRINGS));
 
        /**
+        * SoupWebsocketConnection:max-incoming-payload-size:
+        *
+        * The maximum payload size for incoming packets the protocol expects
+        * or 0 to not limit it.
+        *
+        * Since: 2.56
+        */
+       g_object_class_install_property (gobject_class, PROP_MAX_INCOMING_PAYLOAD_SIZE,
+                                        g_param_spec_uint64 ("max-incoming-payload-size",
+                                                             "Max incoming payload size",
+                                                             "Max incoming payload size ",
+                                                             0,
+                                                             G_MAXUINT64,
+                                                             MAX_INCOMING_PAYLOAD_SIZE_DEFAULT,
+                                                             G_PARAM_READWRITE |
+                                                             G_PARAM_CONSTRUCT |
+                                                             G_PARAM_STATIC_STRINGS));
+
+       /**
         * SoupWebsocketConnection::message:
         * @self: the WebSocket
         * @type: the type of message contents
@@ -1569,3 +1600,49 @@ soup_websocket_connection_close (SoupWebsocketConnection *self,
        send_close (self, flags, code, data);
        close_io_after_timeout (self);
 }
+
+/**
+ * soup_websocket_connection_get_max_incoming_payload_size:
+ * @self: the WebSocket
+ *
+ * Gets the maximum payload size allowed for incoming packets.
+ *
+ * Returns: the maximum payload size.
+ *
+ * Since: 2.56
+ */
+guint64
+soup_websocket_connection_get_max_incoming_payload_size (SoupWebsocketConnection *self)
+{
+       SoupWebsocketConnectionPrivate *pv;
+
+       g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), MAX_INCOMING_PAYLOAD_SIZE_DEFAULT);
+       pv = self->pv;
+
+       return pv->max_incoming_payload_size;
+}
+
+/**
+ * soup_websocket_connection_set_max_incoming_payload_size:
+ * @self: the WebSocket
+ * @max_incoming_payload_size: the maximum payload size
+ *
+ * Sets the maximum payload size allowed for incoming packets. It
+ * does not limit the outgoing packet size.
+ *
+ * Since: 2.56
+ */
+void
+soup_websocket_connection_set_max_incoming_payload_size (SoupWebsocketConnection *self,
+                                                         guint64                  max_incoming_payload_size)
+{
+       SoupWebsocketConnectionPrivate *pv;
+
+       g_return_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self));
+       pv = self->pv;
+
+       if (pv->max_incoming_payload_size != max_incoming_payload_size) {
+               pv->max_incoming_payload_size = max_incoming_payload_size;
+               g_object_notify (G_OBJECT (self), "max-incoming-payload-size");
+       }
+}
diff --git a/libsoup/soup-websocket-connection.h b/libsoup/soup-websocket-connection.h
index 515961b..9d72e13 100644
--- a/libsoup/soup-websocket-connection.h
+++ b/libsoup/soup-websocket-connection.h
@@ -105,6 +105,13 @@ void                soup_websocket_connection_close          (SoupWebsocketConne
                                                              gushort code,
                                                              const char *data);
 
+SOUP_AVAILABLE_IN_2_56
+guint64             soup_websocket_connection_get_max_incoming_payload_size (SoupWebsocketConnection *self);
+
+SOUP_AVAILABLE_IN_2_56
+void                soup_websocket_connection_set_max_incoming_payload_size (SoupWebsocketConnection *self,
+                                                                             guint64                  
max_incoming_payload_size);
+
 G_END_DECLS
 
 #endif /* __SOUP_WEBSOCKET_CONNECTION_H__ */
diff --git a/tests/websocket-test.c b/tests/websocket-test.c
index eb74ea1..722ccbd 100644
--- a/tests/websocket-test.c
+++ b/tests/websocket-test.c
@@ -380,6 +380,19 @@ test_send_big_packets (Test *test,
        g_assert (g_bytes_equal (sent, received));
        g_bytes_unref (sent);
        g_bytes_unref (received);
+       received = NULL;
+
+       soup_websocket_connection_set_max_incoming_payload_size (test->client, 1000 * 1000 + 1);
+       g_assert (soup_websocket_connection_get_max_incoming_payload_size (test->client) == (1000 * 1000 + 
1));
+       soup_websocket_connection_set_max_incoming_payload_size (test->server, 1000 * 1000 + 1);
+       g_assert (soup_websocket_connection_get_max_incoming_payload_size (test->server) == (1000 * 1000 + 
1));
+
+       sent = g_bytes_new_take (g_strnfill (1000 * 1000, '?'), 1000 * 1000);
+       soup_websocket_connection_send_text (test->server, g_bytes_get_data (sent, NULL));
+       WAIT_UNTIL (received != NULL);
+       g_assert (g_bytes_equal (sent, received));
+       g_bytes_unref (sent);
+       g_bytes_unref (received);
 }
 
 static void


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