mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-25 10:04:19 +00:00
rtsp: don't use sockets for blocking
Use the blocking and non-blocking API of the input/output streams instead of polling the sockets directly. This also allows us to simplify some code.
This commit is contained in:
parent
909e119a23
commit
4f660c388c
1 changed files with 144 additions and 261 deletions
|
@ -293,9 +293,6 @@ gst_rtsp_connection_create_from_socket (GSocket * socket, const gchar * ip,
|
||||||
g_return_val_if_fail (ip != NULL, GST_RTSP_EINVAL);
|
g_return_val_if_fail (ip != NULL, GST_RTSP_EINVAL);
|
||||||
g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
|
g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
|
||||||
|
|
||||||
/* set to non-blocking mode so that we can cancel the communication */
|
|
||||||
g_socket_set_blocking (socket, FALSE);
|
|
||||||
|
|
||||||
if (!collect_addresses (socket, &local_ip, NULL, FALSE, &err))
|
if (!collect_addresses (socket, &local_ip, NULL, FALSE, &err))
|
||||||
goto getnameinfo_failed;
|
goto getnameinfo_failed;
|
||||||
|
|
||||||
|
@ -479,7 +476,6 @@ setup_tunneling (GstRTSPConnection * conn, GTimeVal * timeout, gchar * uri)
|
||||||
goto connect_failed;
|
goto connect_failed;
|
||||||
|
|
||||||
socket = g_socket_connection_get_socket (connection);
|
socket = g_socket_connection_get_socket (connection);
|
||||||
g_socket_set_blocking (socket, FALSE);
|
|
||||||
|
|
||||||
/* get remote address */
|
/* get remote address */
|
||||||
g_free (conn->remote_ip);
|
g_free (conn->remote_ip);
|
||||||
|
@ -616,7 +612,6 @@ gst_rtsp_connection_connect (GstRTSPConnection * conn, GTimeVal * timeout)
|
||||||
|
|
||||||
/* get remote address */
|
/* get remote address */
|
||||||
socket = g_socket_connection_get_socket (connection);
|
socket = g_socket_connection_get_socket (connection);
|
||||||
g_socket_set_blocking (socket, FALSE);
|
|
||||||
|
|
||||||
if (!collect_addresses (socket, &remote_ip, NULL, TRUE, &error))
|
if (!collect_addresses (socket, &remote_ip, NULL, TRUE, &error))
|
||||||
goto remote_address_failed;
|
goto remote_address_failed;
|
||||||
|
@ -813,9 +808,11 @@ gen_date_string (gchar * date_string, guint len)
|
||||||
|
|
||||||
static GstRTSPResult
|
static GstRTSPResult
|
||||||
write_bytes (GOutputStream * stream, const guint8 * buffer, guint * idx,
|
write_bytes (GOutputStream * stream, const guint8 * buffer, guint * idx,
|
||||||
guint size, GCancellable * cancellable)
|
guint size, gboolean block, GCancellable * cancellable)
|
||||||
{
|
{
|
||||||
guint left;
|
guint left;
|
||||||
|
gssize r;
|
||||||
|
GError *err = NULL;
|
||||||
|
|
||||||
if (G_UNLIKELY (*idx > size))
|
if (G_UNLIKELY (*idx > size))
|
||||||
return GST_RTSP_ERROR;
|
return GST_RTSP_ERROR;
|
||||||
|
@ -823,31 +820,41 @@ write_bytes (GOutputStream * stream, const guint8 * buffer, guint * idx,
|
||||||
left = size - *idx;
|
left = size - *idx;
|
||||||
|
|
||||||
while (left) {
|
while (left) {
|
||||||
GError *err = NULL;
|
r = g_pollable_stream_write (stream, (gchar *) & buffer[*idx], left,
|
||||||
gssize r;
|
block, cancellable, &err);
|
||||||
|
if (G_UNLIKELY (r < 0))
|
||||||
|
goto error;
|
||||||
|
|
||||||
r = g_output_stream_write (stream, (gchar *) & buffer[*idx], left,
|
left -= r;
|
||||||
cancellable, &err);
|
*idx += r;
|
||||||
if (G_UNLIKELY (r == 0)) {
|
|
||||||
return GST_RTSP_EINTR;
|
|
||||||
} else if (G_UNLIKELY (r < 0)) {
|
|
||||||
if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
|
|
||||||
g_clear_error (&err);
|
|
||||||
return GST_RTSP_EINTR;
|
|
||||||
}
|
|
||||||
g_clear_error (&err);
|
|
||||||
return GST_RTSP_ESYS;
|
|
||||||
} else {
|
|
||||||
left -= r;
|
|
||||||
*idx += r;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return GST_RTSP_OK;
|
return GST_RTSP_OK;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
error:
|
||||||
|
{
|
||||||
|
if (G_UNLIKELY (r == 0))
|
||||||
|
return GST_RTSP_EEOF;
|
||||||
|
|
||||||
|
GST_DEBUG ("%s", err->message);
|
||||||
|
if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||||
|
g_clear_error (&err);
|
||||||
|
return GST_RTSP_EINTR;
|
||||||
|
} else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
|
||||||
|
g_clear_error (&err);
|
||||||
|
return GST_RTSP_EINTR;
|
||||||
|
} else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_TIMED_OUT)) {
|
||||||
|
g_clear_error (&err);
|
||||||
|
return GST_RTSP_ETIMEOUT;
|
||||||
|
}
|
||||||
|
g_clear_error (&err);
|
||||||
|
return GST_RTSP_ESYS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
fill_raw_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size,
|
fill_raw_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size,
|
||||||
GError ** err)
|
gboolean block, GError ** err)
|
||||||
{
|
{
|
||||||
gint out = 0;
|
gint out = 0;
|
||||||
|
|
||||||
|
@ -868,11 +875,17 @@ fill_raw_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size,
|
||||||
if (G_LIKELY (size > (guint) out)) {
|
if (G_LIKELY (size > (guint) out)) {
|
||||||
gssize r;
|
gssize r;
|
||||||
|
|
||||||
r = g_input_stream_read (conn->input_stream, (gchar *) & buffer[out],
|
r = g_pollable_stream_read (conn->input_stream,
|
||||||
size - out, conn->cancellable, err);
|
(gchar *) & buffer[out], size - out, block, conn->cancellable, err);
|
||||||
if (r <= 0) {
|
|
||||||
if (out == 0)
|
if (G_UNLIKELY (r < 0)) {
|
||||||
|
if (out == 0) {
|
||||||
|
/* propagate the error */
|
||||||
out = r;
|
out = r;
|
||||||
|
} else {
|
||||||
|
/* we have some data ignore error */
|
||||||
|
g_clear_error (err);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
out += r;
|
out += r;
|
||||||
}
|
}
|
||||||
|
@ -882,7 +895,7 @@ fill_raw_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size,
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
fill_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size,
|
fill_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size,
|
||||||
GError ** err)
|
gboolean block, GError ** err)
|
||||||
{
|
{
|
||||||
DecodeCtx *ctx = conn->ctxp;
|
DecodeCtx *ctx = conn->ctxp;
|
||||||
gint out = 0;
|
gint out = 0;
|
||||||
|
@ -904,7 +917,7 @@ fill_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* try to read more bytes */
|
/* try to read more bytes */
|
||||||
r = fill_raw_bytes (conn, in, sizeof (in), err);
|
r = fill_raw_bytes (conn, in, sizeof (in), block, err);
|
||||||
if (r <= 0) {
|
if (r <= 0) {
|
||||||
if (out == 0)
|
if (out == 0)
|
||||||
out = r;
|
out = r;
|
||||||
|
@ -917,16 +930,18 @@ fill_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size,
|
||||||
&ctx->save);
|
&ctx->save);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
out = fill_raw_bytes (conn, buffer, size, err);
|
out = fill_raw_bytes (conn, buffer, size, block, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstRTSPResult
|
static GstRTSPResult
|
||||||
read_bytes (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size)
|
read_bytes (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size,
|
||||||
|
gboolean block)
|
||||||
{
|
{
|
||||||
guint left;
|
guint left;
|
||||||
|
gint r;
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
|
|
||||||
if (G_UNLIKELY (*idx > size))
|
if (G_UNLIKELY (*idx > size))
|
||||||
|
@ -935,24 +950,35 @@ read_bytes (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size)
|
||||||
left = size - *idx;
|
left = size - *idx;
|
||||||
|
|
||||||
while (left) {
|
while (left) {
|
||||||
gint r;
|
r = fill_bytes (conn, &buffer[*idx], left, block, &err);
|
||||||
|
if (G_UNLIKELY (r <= 0))
|
||||||
|
goto error;
|
||||||
|
|
||||||
r = fill_bytes (conn, &buffer[*idx], left, &err);
|
left -= r;
|
||||||
if (G_UNLIKELY (r == 0)) {
|
*idx += r;
|
||||||
return GST_RTSP_EEOF;
|
|
||||||
} else if (G_UNLIKELY (r < 0)) {
|
|
||||||
if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
|
|
||||||
g_clear_error (&err);
|
|
||||||
return GST_RTSP_EINTR;
|
|
||||||
}
|
|
||||||
g_clear_error (&err);
|
|
||||||
return GST_RTSP_ESYS;
|
|
||||||
} else {
|
|
||||||
left -= r;
|
|
||||||
*idx += r;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return GST_RTSP_OK;
|
return GST_RTSP_OK;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
error:
|
||||||
|
{
|
||||||
|
if (G_UNLIKELY (r == 0))
|
||||||
|
return GST_RTSP_EEOF;
|
||||||
|
|
||||||
|
GST_DEBUG ("%s", err->message);
|
||||||
|
if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||||
|
g_clear_error (&err);
|
||||||
|
return GST_RTSP_EINTR;
|
||||||
|
} else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
|
||||||
|
g_clear_error (&err);
|
||||||
|
return GST_RTSP_EINTR;
|
||||||
|
} else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_TIMED_OUT)) {
|
||||||
|
g_clear_error (&err);
|
||||||
|
return GST_RTSP_ETIMEOUT;
|
||||||
|
}
|
||||||
|
g_clear_error (&err);
|
||||||
|
return GST_RTSP_ESYS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The code below tries to handle clients using \r, \n or \r\n to indicate the
|
/* The code below tries to handle clients using \r, \n or \r\n to indicate the
|
||||||
|
@ -962,13 +988,14 @@ read_bytes (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size)
|
||||||
* the method used in RTSP (and HTTP) to break long lines.
|
* the method used in RTSP (and HTTP) to break long lines.
|
||||||
*/
|
*/
|
||||||
static GstRTSPResult
|
static GstRTSPResult
|
||||||
read_line (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size)
|
read_line (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size,
|
||||||
|
gboolean block)
|
||||||
{
|
{
|
||||||
GError *err = NULL;
|
GstRTSPResult res;
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
guint8 c;
|
guint8 c;
|
||||||
gint r;
|
guint i;
|
||||||
|
|
||||||
if (conn->read_ahead == READ_AHEAD_EOH) {
|
if (conn->read_ahead == READ_AHEAD_EOH) {
|
||||||
/* the last call to read_line() already determined that we have reached
|
/* the last call to read_line() already determined that we have reached
|
||||||
|
@ -987,18 +1014,10 @@ read_line (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size)
|
||||||
conn->read_ahead = 0;
|
conn->read_ahead = 0;
|
||||||
} else {
|
} else {
|
||||||
/* read the next character */
|
/* read the next character */
|
||||||
r = fill_bytes (conn, &c, 1, &err);
|
i = 0;
|
||||||
if (G_UNLIKELY (r == 0)) {
|
res = read_bytes (conn, &c, &i, 1, block);
|
||||||
return GST_RTSP_EEOF;
|
if (G_UNLIKELY (res != GST_RTSP_OK))
|
||||||
} else if (G_UNLIKELY (r < 0)) {
|
return res;
|
||||||
if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
|
|
||||||
g_clear_error (&err);
|
|
||||||
return GST_RTSP_EINTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_clear_error (&err);
|
|
||||||
return GST_RTSP_ESYS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* special treatment of line endings */
|
/* special treatment of line endings */
|
||||||
|
@ -1007,21 +1026,10 @@ read_line (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size)
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
/* need to read ahead one more character to know what to do... */
|
/* need to read ahead one more character to know what to do... */
|
||||||
r = fill_bytes (conn, &read_ahead, 1, &err);
|
i = 0;
|
||||||
if (G_UNLIKELY (r == 0)) {
|
res = read_bytes (conn, &read_ahead, &i, 1, block);
|
||||||
return GST_RTSP_EEOF;
|
if (G_UNLIKELY (res != GST_RTSP_OK))
|
||||||
} else if (G_UNLIKELY (r < 0)) {
|
return res;
|
||||||
if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
|
|
||||||
/* remember the original character we read and try again next time */
|
|
||||||
if (conn->read_ahead == 0)
|
|
||||||
conn->read_ahead = c;
|
|
||||||
g_clear_error (&err);
|
|
||||||
return GST_RTSP_EINTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_clear_error (&err);
|
|
||||||
return GST_RTSP_ESYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (read_ahead == ' ' || read_ahead == '\t') {
|
if (read_ahead == ' ' || read_ahead == '\t') {
|
||||||
if (conn->read_ahead == READ_AHEAD_CRLFCR) {
|
if (conn->read_ahead == READ_AHEAD_CRLFCR) {
|
||||||
|
@ -1106,62 +1114,22 @@ gst_rtsp_connection_write (GstRTSPConnection * conn, const guint8 * data,
|
||||||
guint offset;
|
guint offset;
|
||||||
GstClockTime to;
|
GstClockTime to;
|
||||||
GstRTSPResult res;
|
GstRTSPResult res;
|
||||||
GError *err = NULL;
|
|
||||||
|
|
||||||
g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
|
g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
|
||||||
g_return_val_if_fail (data != NULL || size == 0, GST_RTSP_EINVAL);
|
g_return_val_if_fail (data != NULL || size == 0, GST_RTSP_EINVAL);
|
||||||
g_return_val_if_fail (conn->output_stream != NULL, GST_RTSP_EINVAL);
|
g_return_val_if_fail (conn->output_stream != NULL, GST_RTSP_EINVAL);
|
||||||
|
|
||||||
to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE;
|
|
||||||
|
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
|
||||||
while (TRUE) {
|
to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : 0;
|
||||||
/* try to write */
|
|
||||||
res =
|
|
||||||
write_bytes (conn->output_stream, data, &offset, size,
|
|
||||||
conn->cancellable);
|
|
||||||
if (G_LIKELY (res == GST_RTSP_OK))
|
|
||||||
break;
|
|
||||||
if (G_UNLIKELY (res != GST_RTSP_EINTR))
|
|
||||||
goto write_error;
|
|
||||||
/* not all is written, wait until we can write more */
|
|
||||||
g_socket_set_timeout (conn->write_socket,
|
|
||||||
(to + GST_SECOND - 1) / GST_SECOND);
|
|
||||||
if (!g_socket_condition_wait (conn->write_socket,
|
|
||||||
G_IO_OUT | G_IO_ERR | G_IO_HUP, conn->cancellable, &err)) {
|
|
||||||
g_socket_set_timeout (conn->write_socket, 0);
|
|
||||||
if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_BUSY)) {
|
|
||||||
g_clear_error (&err);
|
|
||||||
goto stopped;
|
|
||||||
} else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_TIMED_OUT)) {
|
|
||||||
g_clear_error (&err);
|
|
||||||
goto timeout;
|
|
||||||
}
|
|
||||||
g_clear_error (&err);
|
|
||||||
goto select_error;
|
|
||||||
}
|
|
||||||
g_socket_set_timeout (conn->write_socket, 0);
|
|
||||||
}
|
|
||||||
return GST_RTSP_OK;
|
|
||||||
|
|
||||||
/* ERRORS */
|
g_socket_set_timeout (conn->write_socket, (to + GST_SECOND - 1) / GST_SECOND);
|
||||||
timeout:
|
res =
|
||||||
{
|
write_bytes (conn->output_stream, data, &offset, size, TRUE,
|
||||||
return GST_RTSP_ETIMEOUT;
|
conn->cancellable);
|
||||||
}
|
g_socket_set_timeout (conn->write_socket, 0);
|
||||||
select_error:
|
|
||||||
{
|
return res;
|
||||||
return GST_RTSP_ESYS;
|
|
||||||
}
|
|
||||||
stopped:
|
|
||||||
{
|
|
||||||
return GST_RTSP_EINTR;
|
|
||||||
}
|
|
||||||
write_error:
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GString *
|
static GString *
|
||||||
|
@ -1618,7 +1586,7 @@ normalize_line (guint8 * buffer)
|
||||||
*/
|
*/
|
||||||
static GstRTSPResult
|
static GstRTSPResult
|
||||||
build_next (GstRTSPBuilder * builder, GstRTSPMessage * message,
|
build_next (GstRTSPBuilder * builder, GstRTSPMessage * message,
|
||||||
GstRTSPConnection * conn)
|
GstRTSPConnection * conn, gboolean block)
|
||||||
{
|
{
|
||||||
GstRTSPResult res;
|
GstRTSPResult res;
|
||||||
|
|
||||||
|
@ -1630,7 +1598,8 @@ build_next (GstRTSPBuilder * builder, GstRTSPMessage * message,
|
||||||
|
|
||||||
builder->offset = 0;
|
builder->offset = 0;
|
||||||
res =
|
res =
|
||||||
read_bytes (conn, (guint8 *) builder->buffer, &builder->offset, 1);
|
read_bytes (conn, (guint8 *) builder->buffer, &builder->offset, 1,
|
||||||
|
block);
|
||||||
if (res != GST_RTSP_OK)
|
if (res != GST_RTSP_OK)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
@ -1653,7 +1622,8 @@ build_next (GstRTSPBuilder * builder, GstRTSPMessage * message,
|
||||||
case STATE_DATA_HEADER:
|
case STATE_DATA_HEADER:
|
||||||
{
|
{
|
||||||
res =
|
res =
|
||||||
read_bytes (conn, (guint8 *) builder->buffer, &builder->offset, 4);
|
read_bytes (conn, (guint8 *) builder->buffer, &builder->offset, 4,
|
||||||
|
block);
|
||||||
if (res != GST_RTSP_OK)
|
if (res != GST_RTSP_OK)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
@ -1670,7 +1640,7 @@ build_next (GstRTSPBuilder * builder, GstRTSPMessage * message,
|
||||||
{
|
{
|
||||||
res =
|
res =
|
||||||
read_bytes (conn, builder->body_data, &builder->offset,
|
read_bytes (conn, builder->body_data, &builder->offset,
|
||||||
builder->body_len);
|
builder->body_len, block);
|
||||||
if (res != GST_RTSP_OK)
|
if (res != GST_RTSP_OK)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
@ -1687,7 +1657,7 @@ build_next (GstRTSPBuilder * builder, GstRTSPMessage * message,
|
||||||
case STATE_READ_LINES:
|
case STATE_READ_LINES:
|
||||||
{
|
{
|
||||||
res = read_line (conn, builder->buffer, &builder->offset,
|
res = read_line (conn, builder->buffer, &builder->offset,
|
||||||
sizeof (builder->buffer));
|
sizeof (builder->buffer), block);
|
||||||
if (res != GST_RTSP_OK)
|
if (res != GST_RTSP_OK)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
@ -1838,7 +1808,6 @@ gst_rtsp_connection_read (GstRTSPConnection * conn, guint8 * data, guint size,
|
||||||
guint offset;
|
guint offset;
|
||||||
GstClockTime to;
|
GstClockTime to;
|
||||||
GstRTSPResult res;
|
GstRTSPResult res;
|
||||||
GError *err = NULL;
|
|
||||||
|
|
||||||
g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
|
g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
|
||||||
g_return_val_if_fail (data != NULL, GST_RTSP_EINVAL);
|
g_return_val_if_fail (data != NULL, GST_RTSP_EINVAL);
|
||||||
|
@ -1850,58 +1819,13 @@ gst_rtsp_connection_read (GstRTSPConnection * conn, guint8 * data, guint size,
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
|
||||||
/* configure timeout if any */
|
/* configure timeout if any */
|
||||||
to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE;
|
to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : 0;
|
||||||
|
|
||||||
while (TRUE) {
|
g_socket_set_timeout (conn->read_socket, (to + GST_SECOND - 1) / GST_SECOND);
|
||||||
res = read_bytes (conn, data, &offset, size);
|
res = read_bytes (conn, data, &offset, size, TRUE);
|
||||||
if (G_UNLIKELY (res == GST_RTSP_EEOF))
|
g_socket_set_timeout (conn->read_socket, 0);
|
||||||
goto eof;
|
|
||||||
if (G_LIKELY (res == GST_RTSP_OK))
|
|
||||||
break;
|
|
||||||
if (G_UNLIKELY (res != GST_RTSP_EINTR))
|
|
||||||
goto read_error;
|
|
||||||
|
|
||||||
g_socket_set_timeout (conn->read_socket,
|
return res;
|
||||||
(to + GST_SECOND - 1) / GST_SECOND);
|
|
||||||
if (!g_socket_condition_wait (conn->read_socket,
|
|
||||||
G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP, conn->cancellable,
|
|
||||||
&err)) {
|
|
||||||
g_socket_set_timeout (conn->read_socket, 0);
|
|
||||||
if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_BUSY)) {
|
|
||||||
g_clear_error (&err);
|
|
||||||
goto stopped;
|
|
||||||
} else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_TIMED_OUT)) {
|
|
||||||
g_clear_error (&err);
|
|
||||||
goto select_timeout;
|
|
||||||
}
|
|
||||||
g_clear_error (&err);
|
|
||||||
goto select_error;
|
|
||||||
}
|
|
||||||
g_socket_set_timeout (conn->read_socket, 0);
|
|
||||||
}
|
|
||||||
return GST_RTSP_OK;
|
|
||||||
|
|
||||||
/* ERRORS */
|
|
||||||
select_error:
|
|
||||||
{
|
|
||||||
return GST_RTSP_ESYS;
|
|
||||||
}
|
|
||||||
select_timeout:
|
|
||||||
{
|
|
||||||
return GST_RTSP_ETIMEOUT;
|
|
||||||
}
|
|
||||||
stopped:
|
|
||||||
{
|
|
||||||
return GST_RTSP_EINTR;
|
|
||||||
}
|
|
||||||
eof:
|
|
||||||
{
|
|
||||||
return GST_RTSP_EEOF;
|
|
||||||
}
|
|
||||||
read_error:
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstRTSPMessage *
|
static GstRTSPMessage *
|
||||||
|
@ -1951,7 +1875,7 @@ no_message:
|
||||||
* Attempt to read into @message from the connected @conn, blocking up to
|
* Attempt to read into @message from the connected @conn, blocking up to
|
||||||
* the specified @timeout. @timeout can be #NULL, in which case this function
|
* the specified @timeout. @timeout can be #NULL, in which case this function
|
||||||
* might block forever.
|
* might block forever.
|
||||||
*
|
*
|
||||||
* This function can be cancelled with gst_rtsp_connection_flush().
|
* This function can be cancelled with gst_rtsp_connection_flush().
|
||||||
*
|
*
|
||||||
* Returns: #GST_RTSP_OK on success.
|
* Returns: #GST_RTSP_OK on success.
|
||||||
|
@ -1963,75 +1887,53 @@ gst_rtsp_connection_receive (GstRTSPConnection * conn, GstRTSPMessage * message,
|
||||||
GstRTSPResult res;
|
GstRTSPResult res;
|
||||||
GstRTSPBuilder builder;
|
GstRTSPBuilder builder;
|
||||||
GstClockTime to;
|
GstClockTime to;
|
||||||
GError *err = NULL;
|
|
||||||
|
|
||||||
g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
|
g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
|
||||||
g_return_val_if_fail (message != NULL, GST_RTSP_EINVAL);
|
g_return_val_if_fail (message != NULL, GST_RTSP_EINVAL);
|
||||||
g_return_val_if_fail (conn->read_socket != NULL, GST_RTSP_EINVAL);
|
g_return_val_if_fail (conn->read_socket != NULL, GST_RTSP_EINVAL);
|
||||||
|
|
||||||
/* configure timeout if any */
|
/* configure timeout if any */
|
||||||
to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE;
|
to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : 0;
|
||||||
|
|
||||||
|
g_socket_set_timeout (conn->read_socket, (to + GST_SECOND - 1) / GST_SECOND);
|
||||||
memset (&builder, 0, sizeof (GstRTSPBuilder));
|
memset (&builder, 0, sizeof (GstRTSPBuilder));
|
||||||
while (TRUE) {
|
res = build_next (&builder, message, conn, TRUE);
|
||||||
res = build_next (&builder, message, conn);
|
g_socket_set_timeout (conn->read_socket, 0);
|
||||||
if (G_UNLIKELY (res == GST_RTSP_EEOF))
|
|
||||||
goto eof;
|
|
||||||
else if (G_LIKELY (res == GST_RTSP_OK)) {
|
|
||||||
if (!conn->manual_http) {
|
|
||||||
if (message->type == GST_RTSP_MESSAGE_HTTP_REQUEST) {
|
|
||||||
if (conn->tstate == TUNNEL_STATE_NONE &&
|
|
||||||
message->type_data.request.method == GST_RTSP_GET) {
|
|
||||||
GstRTSPMessage *response;
|
|
||||||
|
|
||||||
conn->tstate = TUNNEL_STATE_GET;
|
if (G_UNLIKELY (res != GST_RTSP_OK))
|
||||||
|
goto read_error;
|
||||||
|
|
||||||
/* tunnel GET request, we can reply now */
|
if (!conn->manual_http) {
|
||||||
response = gen_tunnel_reply (conn, GST_RTSP_STS_OK, message);
|
if (message->type == GST_RTSP_MESSAGE_HTTP_REQUEST) {
|
||||||
res = gst_rtsp_connection_send (conn, response, timeout);
|
if (conn->tstate == TUNNEL_STATE_NONE &&
|
||||||
gst_rtsp_message_free (response);
|
message->type_data.request.method == GST_RTSP_GET) {
|
||||||
if (res == GST_RTSP_OK)
|
GstRTSPMessage *response;
|
||||||
res = GST_RTSP_ETGET;
|
|
||||||
goto cleanup;
|
|
||||||
} else if (conn->tstate == TUNNEL_STATE_NONE &&
|
|
||||||
message->type_data.request.method == GST_RTSP_POST) {
|
|
||||||
conn->tstate = TUNNEL_STATE_POST;
|
|
||||||
|
|
||||||
/* tunnel POST request, the caller now has to link the two
|
conn->tstate = TUNNEL_STATE_GET;
|
||||||
* connections. */
|
|
||||||
res = GST_RTSP_ETPOST;
|
/* tunnel GET request, we can reply now */
|
||||||
goto cleanup;
|
response = gen_tunnel_reply (conn, GST_RTSP_STS_OK, message);
|
||||||
} else {
|
res = gst_rtsp_connection_send (conn, response, timeout);
|
||||||
res = GST_RTSP_EPARSE;
|
gst_rtsp_message_free (response);
|
||||||
goto cleanup;
|
if (res == GST_RTSP_OK)
|
||||||
}
|
res = GST_RTSP_ETGET;
|
||||||
} else if (message->type == GST_RTSP_MESSAGE_HTTP_RESPONSE) {
|
goto cleanup;
|
||||||
res = GST_RTSP_EPARSE;
|
} else if (conn->tstate == TUNNEL_STATE_NONE &&
|
||||||
goto cleanup;
|
message->type_data.request.method == GST_RTSP_POST) {
|
||||||
}
|
conn->tstate = TUNNEL_STATE_POST;
|
||||||
|
|
||||||
|
/* tunnel POST request, the caller now has to link the two
|
||||||
|
* connections. */
|
||||||
|
res = GST_RTSP_ETPOST;
|
||||||
|
goto cleanup;
|
||||||
|
} else {
|
||||||
|
res = GST_RTSP_EPARSE;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
} else if (message->type == GST_RTSP_MESSAGE_HTTP_RESPONSE) {
|
||||||
break;
|
res = GST_RTSP_EPARSE;
|
||||||
} else if (G_UNLIKELY (res != GST_RTSP_EINTR))
|
goto cleanup;
|
||||||
goto read_error;
|
|
||||||
|
|
||||||
g_socket_set_timeout (conn->read_socket,
|
|
||||||
(to + GST_SECOND - 1) / GST_SECOND);
|
|
||||||
if (!g_socket_condition_wait (conn->read_socket,
|
|
||||||
G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP, conn->cancellable,
|
|
||||||
&err)) {
|
|
||||||
g_socket_set_timeout (conn->read_socket, 0);
|
|
||||||
if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
|
||||||
g_clear_error (&err);
|
|
||||||
goto stopped;
|
|
||||||
} else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_TIMED_OUT)) {
|
|
||||||
g_clear_error (&err);
|
|
||||||
goto select_timeout;
|
|
||||||
}
|
|
||||||
g_clear_error (&err);
|
|
||||||
goto select_error;
|
|
||||||
}
|
}
|
||||||
g_socket_set_timeout (conn->read_socket, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we have a message here */
|
/* we have a message here */
|
||||||
|
@ -2040,26 +1942,6 @@ gst_rtsp_connection_receive (GstRTSPConnection * conn, GstRTSPMessage * message,
|
||||||
return GST_RTSP_OK;
|
return GST_RTSP_OK;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
select_error:
|
|
||||||
{
|
|
||||||
res = GST_RTSP_ESYS;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
select_timeout:
|
|
||||||
{
|
|
||||||
res = GST_RTSP_ETIMEOUT;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
stopped:
|
|
||||||
{
|
|
||||||
res = GST_RTSP_EINTR;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
eof:
|
|
||||||
{
|
|
||||||
res = GST_RTSP_EEOF;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
read_error:
|
read_error:
|
||||||
cleanup:
|
cleanup:
|
||||||
{
|
{
|
||||||
|
@ -2907,7 +2789,7 @@ gst_rtsp_source_dispatch (GSource * source, GSourceFunc callback G_GNUC_UNUSED,
|
||||||
if (watch->readfd.revents & READ_ERR)
|
if (watch->readfd.revents & READ_ERR)
|
||||||
goto read_error;
|
goto read_error;
|
||||||
|
|
||||||
res = build_next (&watch->builder, &watch->message, watch->conn);
|
res = build_next (&watch->builder, &watch->message, watch->conn, FALSE);
|
||||||
if (res == GST_RTSP_EINTR)
|
if (res == GST_RTSP_EINTR)
|
||||||
break;
|
break;
|
||||||
else if (G_UNLIKELY (res == GST_RTSP_EEOF)) {
|
else if (G_UNLIKELY (res == GST_RTSP_EEOF)) {
|
||||||
|
@ -3022,7 +2904,8 @@ gst_rtsp_source_dispatch (GSource * source, GSourceFunc callback G_GNUC_UNUSED,
|
||||||
}
|
}
|
||||||
|
|
||||||
res = write_bytes (watch->conn->output_stream, watch->write_data,
|
res = write_bytes (watch->conn->output_stream, watch->write_data,
|
||||||
&watch->write_off, watch->write_size, watch->conn->cancellable);
|
&watch->write_off, watch->write_size, FALSE,
|
||||||
|
watch->conn->cancellable);
|
||||||
g_mutex_unlock (&watch->mutex);
|
g_mutex_unlock (&watch->mutex);
|
||||||
|
|
||||||
if (res == GST_RTSP_EINTR)
|
if (res == GST_RTSP_EINTR)
|
||||||
|
@ -3343,7 +3226,7 @@ gst_rtsp_watch_write_data (GstRTSPWatch * watch, const guint8 * data,
|
||||||
if (watch->messages->length == 0 && watch->write_data == NULL) {
|
if (watch->messages->length == 0 && watch->write_data == NULL) {
|
||||||
res =
|
res =
|
||||||
write_bytes (watch->conn->output_stream, data, &off, size,
|
write_bytes (watch->conn->output_stream, data, &off, size,
|
||||||
watch->conn->cancellable);
|
FALSE, watch->conn->cancellable);
|
||||||
if (res != GST_RTSP_EINTR) {
|
if (res != GST_RTSP_EINTR) {
|
||||||
if (id != NULL)
|
if (id != NULL)
|
||||||
*id = 0;
|
*id = 0;
|
||||||
|
|
Loading…
Reference in a new issue