rtsp-client: Handle Content-Length limitation

Add functionality to limit the Content-Length.
API addition, Enhancement.

Define an appropriate request size limit and reject requests
exceeding the limit with response status 413 Request Entity Too Large

Related to !182
This commit is contained in:
Kristofer Bjorkstrom 2019-03-27 16:21:03 +01:00 committed by Sebastian Dröge
parent f586450b99
commit b578628dc1
4 changed files with 180 additions and 0 deletions

View file

@ -103,6 +103,8 @@ struct _GstRTSPClientPrivate
gboolean drop_backlog;
guint content_length_limit;
guint rtsp_ctrl_timeout_id;
guint rtsp_ctrl_timeout_cnt;
@ -609,6 +611,7 @@ gst_rtsp_client_init (GstRTSPClient * client)
priv->pipelined_requests = g_hash_table_new_full (g_str_hash,
g_str_equal, g_free, g_free);
priv->tstate = TUNNEL_STATE_UNKNOWN;
priv->content_length_limit = G_MAXUINT;
}
static GstRTSPFilterResult
@ -3983,6 +3986,57 @@ gst_rtsp_client_get_mount_points (GstRTSPClient * client)
return result;
}
/**
* gst_rtsp_client_set_content_length_limit:
* @client: a #GstRTSPClient
* @limit: Content-Length limit
*
* Configure @client to use the specified Content-Length limit.
*
* Define an appropriate request size limit and reject requests exceeding the
* limit with response status 413 Request Entity Too Large
*
* Since: 1.18
*/
void
gst_rtsp_client_set_content_length_limit (GstRTSPClient * client, guint limit)
{
GstRTSPClientPrivate *priv;
g_return_if_fail (GST_IS_RTSP_CLIENT (client));
priv = client->priv;
g_mutex_lock (&priv->lock);
priv->content_length_limit = limit;
g_mutex_unlock (&priv->lock);
}
/**
* gst_rtsp_client_get_content_length_limit:
* @client: a #GstRTSPClient
*
* Get the Content-Length limit of @client.
*
* Returns: the Content-Length limit.
*
* Since: 1.18
*/
guint
gst_rtsp_client_get_content_length_limit (GstRTSPClient * client)
{
GstRTSPClientPrivate *priv;
glong content_length_limit;
g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), -1);
priv = client->priv;
g_mutex_lock (&priv->lock);
content_length_limit = priv->content_length_limit;
g_mutex_unlock (&priv->lock);
return content_length_limit;
}
/**
* gst_rtsp_client_set_auth:
* @client: a #GstRTSPClient
@ -4122,6 +4176,8 @@ gst_rtsp_client_set_connection (GstRTSPClient * client,
priv = client->priv;
gst_rtsp_connection_set_content_length_limit (conn,
priv->content_length_limit);
read_socket = gst_rtsp_connection_get_read_socket (conn);
if (!(address = g_socket_get_local_address (read_socket, &error)))
@ -4492,7 +4548,39 @@ error_full (GstRTSPWatch * watch, GstRTSPResult result,
{
GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
gchar *str;
GstRTSPContext sctx = { NULL }, *ctx;
GstRTSPClientPrivate *priv;
GstRTSPMessage response = { 0 };
priv = client->priv;
if (!(ctx = gst_rtsp_context_get_current ())) {
ctx = &sctx;
ctx->auth = priv->auth;
gst_rtsp_context_push_current (ctx);
}
ctx->conn = priv->connection;
ctx->client = client;
ctx->request = message;
ctx->method = GST_RTSP_INVALID;
ctx->response = &response;
/* only return error response if it is a request */
if (!message || message->type != GST_RTSP_MESSAGE_REQUEST)
goto done;
if (result == GST_RTSP_ENOMEM) {
send_generic_response (client, GST_RTSP_STS_REQUEST_ENTITY_TOO_LARGE, ctx);
goto done;
}
if (result == GST_RTSP_EPARSE) {
send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
goto done;
}
done:
if (ctx == &sctx)
gst_rtsp_context_pop_current (ctx);
str = gst_rtsp_strresult (result);
GST_INFO
("client %p: error when handling message %p with id %d: %s",

View file

@ -185,6 +185,12 @@ void gst_rtsp_client_set_mount_points (GstRTSPClient *client,
GST_RTSP_SERVER_API
GstRTSPMountPoints * gst_rtsp_client_get_mount_points (GstRTSPClient *client);
GST_RTSP_SERVER_API
void gst_rtsp_client_set_content_length_limit (GstRTSPClient *client, guint limit);
GST_RTSP_SERVER_API
guint gst_rtsp_client_get_content_length_limit (GstRTSPClient *client);
GST_RTSP_SERVER_API
void gst_rtsp_client_set_auth (GstRTSPClient *client, GstRTSPAuth *auth);

View file

@ -132,6 +132,12 @@ void gst_rtsp_server_set_mount_points (GstRTSPServer *serve
GST_RTSP_SERVER_API
GstRTSPMountPoints * gst_rtsp_server_get_mount_points (GstRTSPServer *server);
GST_RTSP_SERVER_API
void gst_rtsp_server_set_content_length_limit (GstRTSPServer * server, guint limit);
GST_RTSP_SERVER_API
guint gst_rtsp_server_get_content_length_limit (GstRTSPServer * server);
GST_RTSP_SERVER_API
void gst_rtsp_server_set_auth (GstRTSPServer *server, GstRTSPAuth *auth);

View file

@ -84,6 +84,9 @@ struct _GstRTSPServerPrivate
/* mount points for this server */
GstRTSPMountPoints *mount_points;
/* request size limit */
guint content_length_limit;
/* authentication manager */
GstRTSPAuth *auth;
@ -116,6 +119,7 @@ enum
PROP_SESSION_POOL,
PROP_MOUNT_POINTS,
PROP_CONTENT_LENGTH_LIMIT,
PROP_LAST
};
@ -223,6 +227,19 @@ gst_rtsp_server_class_init (GstRTSPServerClass * klass)
GST_TYPE_RTSP_MOUNT_POINTS,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* RTSPServer::content-length-limit:
*
* Define an appropriate request size limit and reject requests exceeding the
* limit.
*
* Since: 1.18
*/
g_object_class_install_property (gobject_class, PROP_CONTENT_LENGTH_LIMIT,
g_param_spec_uint ("content-length-limit", "Limitation of Content-Length",
"Limitation of Content-Length",
0, G_MAXUINT, G_MAXUINT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gst_rtsp_server_signals[SIGNAL_CLIENT_CONNECTED] =
g_signal_new ("client-connected", G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPServerClass, client_connected),
@ -248,6 +265,7 @@ gst_rtsp_server_init (GstRTSPServer * server)
priv->backlog = DEFAULT_BACKLOG;
priv->session_pool = gst_rtsp_session_pool_new ();
priv->mount_points = gst_rtsp_mount_points_new ();
priv->content_length_limit = G_MAXUINT;
priv->thread_pool = gst_rtsp_thread_pool_new ();
}
@ -600,6 +618,57 @@ gst_rtsp_server_get_mount_points (GstRTSPServer * server)
return result;
}
/**
* gst_rtsp_server_set_content_length_limit
* @server: a #GstRTSPServer
* Configure @server to use the specified Content-Length limit.
*
* Define an appropriate request size limit and reject requests exceeding the
* limit.
*
* Since: 1.18
*/
void
gst_rtsp_server_set_content_length_limit (GstRTSPServer * server, guint limit)
{
GstRTSPServerPrivate *priv;
g_return_if_fail (GST_IS_RTSP_SERVER (server));
priv = server->priv;
GST_RTSP_SERVER_LOCK (server);
priv->content_length_limit = limit;
GST_RTSP_SERVER_UNLOCK (server);
}
/**
* gst_rtsp_server_get_content_length_limit:
* @server: a #GstRTSPServer
*
* Get the Content-Length limit of @server.
*
* Returns: the Content-Length limit.
*
* Since: 1.18
*/
guint
gst_rtsp_server_get_content_length_limit (GstRTSPServer * server)
{
GstRTSPServerPrivate *priv;
guint result;
g_return_val_if_fail (GST_IS_RTSP_SERVER (server), G_MAXUINT);
priv = server->priv;
GST_RTSP_SERVER_LOCK (server);
result = priv->content_length_limit;
GST_RTSP_SERVER_UNLOCK (server);
return result;
}
/**
* gst_rtsp_server_set_auth:
* @server: a #GstRTSPServer
@ -739,6 +808,10 @@ gst_rtsp_server_get_property (GObject * object, guint propid,
case PROP_MOUNT_POINTS:
g_value_take_object (value, gst_rtsp_server_get_mount_points (server));
break;
case PROP_CONTENT_LENGTH_LIMIT:
g_value_set_uint (value,
gst_rtsp_server_get_content_length_limit (server));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
}
@ -766,6 +839,10 @@ gst_rtsp_server_set_property (GObject * object, guint propid,
case PROP_MOUNT_POINTS:
gst_rtsp_server_set_mount_points (server, g_value_get_object (value));
break;
case PROP_CONTENT_LENGTH_LIMIT:
gst_rtsp_server_set_content_length_limit (server,
g_value_get_uint (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
}
@ -1073,6 +1150,9 @@ default_create_client (GstRTSPServer * server)
gst_rtsp_client_set_session_pool (client, priv->session_pool);
/* set the mount points that this client should use */
gst_rtsp_client_set_mount_points (client, priv->mount_points);
/* Set content-length limit */
gst_rtsp_client_set_content_length_limit (GST_RTSP_CLIENT (client),
priv->content_length_limit);
/* set authentication manager */
gst_rtsp_client_set_auth (client, priv->auth);
/* set threadpool */