gst/rtsp/gstrtspsrc.c: Refactor timeout handling.

Original commit message from CVS:
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_send_keep_alive),
(gst_rtspsrc_loop_interleaved), (gst_rtspsrc_loop_udp),
(gst_rtspsrc_try_send), (gst_rtspsrc_send),
(gst_rtspsrc_setup_streams):
Refactor timeout handling.
Also send keep-alive when dealing with TCP transport.
* gst/rtsp/rtspconnection.c: (rtsp_connection_create),
(rtsp_connection_free), (rtsp_connection_next_timeout),
(rtsp_connection_reset_timeout):
* gst/rtsp/rtspconnection.h:
Use a timer to handle the session timeouts, add some methods to deal
with timeouts.
This commit is contained in:
Wim Taymans 2007-05-18 10:36:12 +00:00
parent ccd7a136a9
commit e4720e286c
4 changed files with 146 additions and 63 deletions

View file

@ -1,3 +1,19 @@
2007-05-18 Wim Taymans <wim@fluendo.com>
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_send_keep_alive),
(gst_rtspsrc_loop_interleaved), (gst_rtspsrc_loop_udp),
(gst_rtspsrc_try_send), (gst_rtspsrc_send),
(gst_rtspsrc_setup_streams):
Refactor timeout handling.
Also send keep-alive when dealing with TCP transport.
* gst/rtsp/rtspconnection.c: (rtsp_connection_create),
(rtsp_connection_free), (rtsp_connection_next_timeout),
(rtsp_connection_reset_timeout):
* gst/rtsp/rtspconnection.h:
Use a timer to handle the session timeouts, add some methods to deal
with timeouts.
2007-05-17 Wim Taymans <wim@fluendo.com>
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_send),

View file

@ -2079,6 +2079,47 @@ send_error:
}
}
/* send server keep-alive */
static RTSPResult
gst_rtspsrc_send_keep_alive (GstRTSPSrc * src)
{
RTSPMessage request = { 0 };
RTSPResult res;
RTSPMethod method;
GST_DEBUG_OBJECT (src, "creating server keep-alive");
/* find a method to use for keep-alive */
if (src->methods & RTSP_GET_PARAMETER)
method = RTSP_GET_PARAMETER;
else
method = RTSP_OPTIONS;
res = rtsp_message_init_request (&request, method, src->req_location);
if (res < 0)
goto send_error;
if ((res = rtsp_connection_send (src->connection, &request, NULL)) < 0)
goto send_error;
rtsp_connection_reset_timeout (src->connection);
rtsp_message_unset (&request);
return RTSP_OK;
/* ERRORS */
send_error:
{
gchar *str = rtsp_strresult (res);
rtsp_message_unset (&request);
GST_ELEMENT_WARNING (src, RESOURCE, WRITE, (NULL),
("Could not send keep-alive. (%s)", str));
g_free (str);
return res;
}
}
static void
gst_rtspsrc_loop_interleaved (GstRTSPSrc * src)
{
@ -2096,10 +2137,35 @@ gst_rtspsrc_loop_interleaved (GstRTSPSrc * src)
have_data = FALSE;
do {
GTimeVal tv_timeout;
/* get the next timeout interval */
rtsp_connection_next_timeout (src->connection, &tv_timeout);
/* see if the timeout period expired */
if ((tv_timeout.tv_usec | tv_timeout.tv_usec) == 0) {
GST_DEBUG_OBJECT (src, "timout, sending keep-alive");
/* send keep-alive, ignore the result, a warning will be posted. */
res = gst_rtspsrc_send_keep_alive (src);
}
GST_DEBUG_OBJECT (src, "doing receive");
if ((res = rtsp_connection_receive (src->connection, &message, NULL)) < 0)
goto receive_error;
res = rtsp_connection_receive (src->connection, &message, NULL);
switch (res) {
case RTSP_OK:
GST_DEBUG_OBJECT (src, "we received a server message");
break;
case RTSP_EINTR:
/* we got interrupted, see what we have to do */
GST_DEBUG_OBJECT (src, "we got interrupted, unset flushing");
/* unset flushing so we can do something else */
rtsp_connection_flush (src->connection, FALSE);
goto interrupt;
default:
goto receive_error;
}
switch (message.type) {
case RTSP_MESSAGE_REQUEST:
@ -2200,6 +2266,13 @@ unknown_stream:
rtsp_message_unset (&message);
return;
}
interrupt:
{
GST_DEBUG_OBJECT (src, "we got interrupted");
rtsp_message_unset (&message);
ret = GST_FLOW_WRONG_STATE;
goto need_pause;
}
receive_error:
{
gchar *str = rtsp_strresult (res);
@ -2260,49 +2333,6 @@ need_pause:
}
}
/* send server keep-alive */
static RTSPResult
gst_rtspsrc_send_keep_alive (GstRTSPSrc * src)
{
RTSPMessage request = { 0 };
RTSPMessage response = { 0 };
RTSPResult res;
RTSPStatusCode code;
RTSPMethod method;
GST_DEBUG_OBJECT (src, "creating server keep-alive");
/* find a method to use for keep-alive */
if (src->methods & RTSP_GET_PARAMETER)
method = RTSP_GET_PARAMETER;
else
method = RTSP_OPTIONS;
res = rtsp_message_init_request (&request, method, src->req_location);
if (res < 0)
goto send_error;
/* let us handle the error code because we don't care */
if ((res = gst_rtspsrc_send (src, &request, &response, &code)) < 0)
goto send_error;
rtsp_message_unset (&request);
return RTSP_OK;
/* ERRORS */
send_error:
{
gchar *str = rtsp_strresult (res);
rtsp_message_unset (&request);
GST_ELEMENT_WARNING (src, RESOURCE, WRITE, (NULL),
("Could not send keep-alive. (%s)", str));
g_free (str);
return res;
}
}
static void
gst_rtspsrc_loop_udp (GstRTSPSrc * src)
{
@ -2314,26 +2344,17 @@ gst_rtspsrc_loop_udp (GstRTSPSrc * src)
goto stopping;
while (src->loop_cmd == CMD_WAIT) {
GTimeVal tv_timeout;
gint timeout;
GST_OBJECT_UNLOCK (src);
while (TRUE) {
RTSPMessage message = { 0 };
GTimeVal tv_timeout;
/* calculate the session timeout. We should send the keep-alive request a
* little earlier to compensate for the round trip time to the server. We
* subtract 1 second here. */
timeout = src->connection->timeout;
if (timeout > 1)
timeout -= 1;
/* get the next timeout interval */
rtsp_connection_next_timeout (src->connection, &tv_timeout);
/* use the session timeout for receiving data */
tv_timeout.tv_sec = timeout;
tv_timeout.tv_usec = 0;
GST_DEBUG_OBJECT (src, "doing receive with timeout %d seconds", timeout);
GST_DEBUG_OBJECT (src, "doing receive with timeout %d seconds",
tv_timeout.tv_sec);
/* we should continue reading the TCP socket because the server might
* send us requests. When the session timeout expires, we need to send a
@ -2366,9 +2387,12 @@ gst_rtspsrc_loop_udp (GstRTSPSrc * src)
goto handle_request_failed;
break;
case RTSP_MESSAGE_RESPONSE:
/* we ignore response and data messages */
GST_DEBUG_OBJECT (src, "ignoring response message");
break;
case RTSP_MESSAGE_DATA:
/* we ignore response and data messages */
GST_DEBUG_OBJECT (src, "ignoring message");
GST_DEBUG_OBJECT (src, "ignoring data message");
break;
default:
GST_WARNING_OBJECT (src, "ignoring unknown message type %d",
@ -2673,6 +2697,8 @@ gst_rtspsrc_try_send (GstRTSPSrc * src, RTSPMessage * request,
if ((res = rtsp_connection_send (src->connection, request, NULL)) < 0)
goto send_error;
rtsp_connection_reset_timeout (src->connection);
next:
if ((res = rtsp_connection_receive (src->connection, response, NULL)) < 0)
goto receive_error;

View file

@ -142,6 +142,7 @@ rtsp_connection_create (RTSPUrl * url, RTSPConnection ** conn)
newconn->fd = -1;
newconn->cseq = 0;
newconn->session_id[0] = 0;
newconn->timer = g_timer_new ();
newconn->auth_method = RTSP_AUTH_NONE;
newconn->username = NULL;
@ -900,6 +901,7 @@ rtsp_connection_free (RTSPConnection * conn)
WSACleanup ();
#endif
g_timer_destroy (conn->timer);
g_free (conn->username);
g_free (conn->passwd);
@ -908,6 +910,40 @@ rtsp_connection_free (RTSPConnection * conn)
return RTSP_OK;
}
RTSPResult
rtsp_connection_next_timeout (RTSPConnection * conn, GTimeVal * timeout)
{
gdouble elapsed;
glong sec;
gulong usec;
g_return_val_if_fail (conn != NULL, RTSP_EINVAL);
g_return_val_if_fail (timeout != NULL, RTSP_EINVAL);
elapsed = g_timer_elapsed (conn->timer, &usec);
if (elapsed >= conn->timeout) {
sec = 0;
usec = 0;
} else {
sec = conn->timeout - elapsed;
}
timeout->tv_sec = sec;
timeout->tv_usec = usec;
return RTSP_OK;
}
RTSPResult
rtsp_connection_reset_timeout (RTSPConnection * conn)
{
g_return_val_if_fail (conn != NULL, RTSP_EINVAL);
g_timer_start (conn->timer);
return RTSP_OK;
}
RTSPResult
rtsp_connection_flush (RTSPConnection * conn, gboolean flush)
{

View file

@ -65,11 +65,12 @@ typedef struct _RTSPConnection
gint cseq; /* sequence number */
gchar session_id[512]; /* session id */
gint timeout; /* session timeout in seconds */
GTimer *timer; /* timeout timer */
/* Authentication */
RTSPAuthMethod auth_method;
gchar *username;
gchar *passwd;
RTSPAuthMethod auth_method;
gchar *username;
gchar *passwd;
} RTSPConnection;
/* opening/closing a connection */
@ -88,6 +89,10 @@ RTSPResult rtsp_connection_write (RTSPConnection * conn, const guint8 *
RTSPResult rtsp_connection_send (RTSPConnection *conn, RTSPMessage *message, GTimeVal *timeout);
RTSPResult rtsp_connection_receive (RTSPConnection *conn, RTSPMessage *message, GTimeVal *timeout);
/* reset the timeout */
RTSPResult rtsp_connection_next_timeout (RTSPConnection *conn, GTimeVal *timeout);
RTSPResult rtsp_connection_reset_timeout (RTSPConnection *conn);
/* flushing state */
RTSPResult rtsp_connection_flush (RTSPConnection *conn, gboolean flush);