summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgnacio Casal Quinteiro <icq@gnome.org>2016-08-17 09:17:49 +0200
committerIgnacio Casal Quinteiro <icq@gnome.org>2016-08-25 15:30:50 +0200
commitd94b56e16e6237a138db2455fadd2ca08809c404 (patch)
tree5877bfd1c222b3e452ebbf73e476ff36660ed95f
parent3f6cbd5714cf8d6f8fa33c08182ac840de0f4705 (diff)
downloadlibsoup-wip/payload-size-3-20.tar.gz
Add max-incoming-payload-size property to the websocket connection.wip/payload-size-3-20
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
-rw-r--r--libsoup/soup-websocket-connection.c85
-rw-r--r--libsoup/soup-websocket-connection.h7
-rw-r--r--tests/websocket-test.c13
3 files changed, 101 insertions, 4 deletions
diff --git a/libsoup/soup-websocket-connection.c b/libsoup/soup-websocket-connection.c
index 622aa689..8901941f 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 515961b6..9d72e13d 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 eb74ea12..722ccbdf 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