From 286a3829b63714fa76c9e074080ca6ab660c2aea Mon Sep 17 00:00:00 2001 From: "Jan Alexander Steffens (heftig)" Date: Fri, 14 Feb 2020 12:28:43 +0100 Subject: [PATCH] rtmp2: Improve handling incoming set chunk/window size Reject out-of-spec sizes and warn about suspiciously small sizes. --- gst/rtmp2/rtmp/rtmpchunkstream.c | 1 + gst/rtmp2/rtmp/rtmpchunkstream.h | 1 - gst/rtmp2/rtmp/rtmpclient.c | 3 ++- gst/rtmp2/rtmp/rtmpconnection.c | 53 ++++++++++++++++++++++++++++++++++++---- gst/rtmp2/rtmp/rtmpconnection.h | 7 ++++++ 5 files changed, 58 insertions(+), 7 deletions(-) diff --git a/gst/rtmp2/rtmp/rtmpchunkstream.c b/gst/rtmp2/rtmp/rtmpchunkstream.c index 1ea1064..b0aa1fa 100644 --- a/gst/rtmp2/rtmp/rtmpchunkstream.c +++ b/gst/rtmp2/rtmp/rtmpchunkstream.c @@ -111,6 +111,7 @@ chunk_stream_next_size (GstRtmpChunkStream * cstream, guint32 chunk_size) size = cstream->meta->size; offset = cstream->offset; + g_return_val_if_fail (chunk_size, 0); g_return_val_if_fail (offset <= size, 0); return MIN (size - offset, chunk_size); } diff --git a/gst/rtmp2/rtmp/rtmpchunkstream.h b/gst/rtmp2/rtmp/rtmpchunkstream.h index bcc9b7d..6466f3b 100644 --- a/gst/rtmp2/rtmp/rtmpchunkstream.h +++ b/gst/rtmp2/rtmp/rtmpchunkstream.h @@ -25,7 +25,6 @@ G_BEGIN_DECLS -#define GST_RTMP_DEFAULT_CHUNK_SIZE 128 #define GST_RTMP_CHUNK_STREAM_PROTOCOL 2 typedef struct _GstRtmpChunkStream GstRtmpChunkStream; diff --git a/gst/rtmp2/rtmp/rtmpclient.c b/gst/rtmp2/rtmp/rtmpclient.c index 657482c..f95994f 100644 --- a/gst/rtmp2/rtmp/rtmpclient.c +++ b/gst/rtmp2/rtmp/rtmpclient.c @@ -1011,7 +1011,8 @@ send_create_stream (GTask * task) "FCPublish", command_object, stream_name, NULL); } else { /* Matches librtmp */ - gst_rtmp_connection_request_window_size (connection, 2500000); + gst_rtmp_connection_request_window_size (connection, + GST_RTMP_DEFAULT_WINDOW_ACK_SIZE); send_set_buffer_length (connection, 0, 300); } diff --git a/gst/rtmp2/rtmp/rtmpconnection.c b/gst/rtmp2/rtmp/rtmpconnection.c index b438658..c27bdfe 100644 --- a/gst/rtmp2/rtmp/rtmpconnection.c +++ b/gst/rtmp2/rtmp/rtmpconnection.c @@ -111,6 +111,10 @@ static void gst_rtmp_connection_handle_user_control (GstRtmpConnection * sc, GstBuffer * buffer); static void gst_rtmp_connection_handle_message (GstRtmpConnection * sc, GstBuffer * buffer); +static void gst_rtmp_connection_handle_set_chunk_size (GstRtmpConnection * self, + guint32 in_chunk_size); +static void gst_rtmp_connection_handle_window_ack_size (GstRtmpConnection * + self, guint32 in_chunk_size); static void gst_rtmp_connection_send_ack (GstRtmpConnection * connection); static void @@ -658,9 +662,9 @@ gst_rtmp_connection_handle_protocol_control (GstRtmpConnection * connection, switch (pc.type) { case GST_RTMP_MESSAGE_TYPE_SET_CHUNK_SIZE: - GST_INFO_OBJECT (connection, "new chunk size %" G_GUINT32_FORMAT, + GST_INFO_OBJECT (connection, "incoming chunk size %" G_GUINT32_FORMAT, pc.param); - connection->in_chunk_size = pc.param; + gst_rtmp_connection_handle_set_chunk_size (connection, pc.param); break; case GST_RTMP_MESSAGE_TYPE_ABORT_MESSAGE: @@ -675,9 +679,9 @@ gst_rtmp_connection_handle_protocol_control (GstRtmpConnection * connection, break; case GST_RTMP_MESSAGE_TYPE_WINDOW_ACK_SIZE: - GST_INFO_OBJECT (connection, "window ack size: %" G_GUINT32_FORMAT, - pc.param); - connection->in_window_ack_size = pc.param; + GST_INFO_OBJECT (connection, + "incoming window ack size: %" G_GUINT32_FORMAT, pc.param); + gst_rtmp_connection_handle_window_ack_size (connection, pc.param); break; case GST_RTMP_MESSAGE_TYPE_SET_PEER_BANDWIDTH: @@ -752,6 +756,45 @@ gst_rtmp_connection_handle_user_control (GstRtmpConnection * connection, } } +static void +gst_rtmp_connection_handle_set_chunk_size (GstRtmpConnection * self, + guint32 chunk_size) +{ + if (chunk_size < GST_RTMP_MINIMUM_CHUNK_SIZE) { + GST_ERROR_OBJECT (self, + "peer requested chunk size %" G_GUINT32_FORMAT "; too small", + chunk_size); + return; + } + + if (chunk_size > GST_RTMP_MAXIMUM_CHUNK_SIZE) { + GST_ERROR_OBJECT (self, + "peer requested chunk size %" G_GUINT32_FORMAT "; too large", + chunk_size); + return; + } + + if (chunk_size < GST_RTMP_DEFAULT_CHUNK_SIZE) { + GST_WARNING_OBJECT (self, + "peer requested small chunk size %" G_GUINT32_FORMAT, chunk_size); + } + + self->in_chunk_size = chunk_size; +} + +static void +gst_rtmp_connection_handle_window_ack_size (GstRtmpConnection * self, + guint32 window_ack_size) +{ + if (window_ack_size < GST_RTMP_DEFAULT_WINDOW_ACK_SIZE) { + GST_WARNING_OBJECT (self, + "peer requested small window ack size %" G_GUINT32_FORMAT, + window_ack_size); + } + + self->in_window_ack_size = window_ack_size; +} + static gboolean is_command_response (const gchar * command_name) { diff --git a/gst/rtmp2/rtmp/rtmpconnection.h b/gst/rtmp2/rtmp/rtmpconnection.h index 5175144..f4c4b96 100644 --- a/gst/rtmp2/rtmp/rtmpconnection.h +++ b/gst/rtmp2/rtmp/rtmpconnection.h @@ -32,6 +32,13 @@ G_BEGIN_DECLS #define GST_RTMP_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTMP_CONNECTION,GstRtmpConnection)) #define GST_IS_RTMP_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTMP_CONNECTION)) +#define GST_RTMP_DEFAULT_CHUNK_SIZE 128 +#define GST_RTMP_MINIMUM_CHUNK_SIZE 1 +#define GST_RTMP_MAXIMUM_CHUNK_SIZE 0x7FFFFFFF + +/* Matches librtmp */ +#define GST_RTMP_DEFAULT_WINDOW_ACK_SIZE 2500000 + typedef struct _GstRtmpConnection GstRtmpConnection; typedef void (*GstRtmpConnectionFunc) -- 2.7.4