From 01d9553d43335b7cde69a47afc6fa510ab3c530c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 17 Aug 2007 13:42:49 +0000 Subject: [PATCH] gst-libs/gst/rtsp/gstrtspconnection.*: Small cleanups. Original commit message from CVS: * gst-libs/gst/rtsp/gstrtspconnection.c: (gst_rtsp_connection_connect), (gst_rtsp_connection_write), (gst_rtsp_connection_read), (gst_rtsp_connection_poll): * gst-libs/gst/rtsp/gstrtspconnection.h: Small cleanups. On shutdown, don't read the control socket yet. Set timeout value correctly in all cases. Add function to check if the server accepts reads or writes. API: gst_rtsp_connection_poll() * gst-libs/gst/rtsp/gstrtspdefs.h: Fix compilation with -pedantic. Add enum for _poll. --- ChangeLog | 16 +++ gst-libs/gst/rtsp/gstrtspconnection.c | 163 +++++++++++++++++++------- gst-libs/gst/rtsp/gstrtspconnection.h | 4 + gst-libs/gst/rtsp/gstrtspdefs.h | 24 +++- 4 files changed, 158 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index b3ee37e3a9..fba1e7b940 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2007-08-17 Wim Taymans + + * gst-libs/gst/rtsp/gstrtspconnection.c: + (gst_rtsp_connection_connect), (gst_rtsp_connection_write), + (gst_rtsp_connection_read), (gst_rtsp_connection_poll): + * gst-libs/gst/rtsp/gstrtspconnection.h: + Small cleanups. + On shutdown, don't read the control socket yet. + Set timeout value correctly in all cases. + Add function to check if the server accepts reads or writes. + API: gst_rtsp_connection_poll() + + * gst-libs/gst/rtsp/gstrtspdefs.h: + Fix compilation with -pedantic. + Add enum for _poll. + 2007-08-16 Wim Taymans Patch by: Olivier Crete diff --git a/gst-libs/gst/rtsp/gstrtspconnection.c b/gst-libs/gst/rtsp/gstrtspconnection.c index 522e1a020f..b764767d94 100644 --- a/gst-libs/gst/rtsp/gstrtspconnection.c +++ b/gst-libs/gst/rtsp/gstrtspconnection.c @@ -70,6 +70,7 @@ /* we include this here to get the G_OS_* defines */ #include +#include #ifdef G_OS_WIN32 #include @@ -109,9 +110,11 @@ G_STMT_START { \ } G_STMT_END #ifdef G_OS_WIN32 +#define FIONREAD_TYPE gulong #define IOCTL_SOCKET ioctlsocket #define CLOSE_SOCKET(sock) closesocket(sock); #else +#define FIONREAD_TYPE gint #define IOCTL_SOCKET ioctl #define CLOSE_SOCKET(sock) close(sock); #endif @@ -290,7 +293,7 @@ gst_rtsp_connection_connect (GstRTSPConnection * conn, GTimeVal * timeout) FD_ZERO (&readfds); FD_SET (READ_SOCKET (conn), &readfds); - if (timeout->tv_sec != 0 || timeout->tv_usec != 0) { + if (timeout) { tv.tv_sec = timeout->tv_sec; tv.tv_usec = timeout->tv_usec; tvp = &tv; @@ -405,7 +408,6 @@ gst_rtsp_connection_write (GstRTSPConnection * conn, const guint8 * data, FD_ZERO (&writefds); FD_SET (conn->fd, &writefds); FD_ZERO (&readfds); - FD_SET (READ_SOCKET (conn), &readfds); max_fd = MAX (conn->fd, READ_SOCKET (conn)); @@ -422,6 +424,9 @@ gst_rtsp_connection_write (GstRTSPConnection * conn, const guint8 * data, while (towrite > 0) { gint written; + /* set bit inside the loop for when we loop to read the rest of the data */ + FD_SET (READ_SOCKET (conn), &readfds); + do { retval = select (max_fd + 1, &readfds, &writefds, NULL, tvp); } while ((retval == -1 && errno == EINTR)); @@ -432,20 +437,8 @@ gst_rtsp_connection_write (GstRTSPConnection * conn, const guint8 * data, if (retval == -1) goto select_error; - if (FD_ISSET (READ_SOCKET (conn), &readfds)) { - /* read all stop commands */ - while (TRUE) { - gchar command; - int res; - - READ_COMMAND (conn, command, res); - if (res <= 0) { - /* no more commands */ - break; - } - } + if (FD_ISSET (READ_SOCKET (conn), &readfds)) goto stopped; - } /* now we can write */ written = write (conn->fd, data, towrite); @@ -815,13 +808,8 @@ gst_rtsp_connection_read (GstRTSPConnection * conn, guint8 * data, guint size, fd_set readfds; guint toread; gint retval; - struct timeval tv_timeout, *ptv_timeout = NULL; - -#ifndef G_OS_WIN32 - gint avail; -#else - gulong avail; -#endif + struct timeval tv_timeout, *ptv_timeout; + FIONREAD_TYPE avail; g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); g_return_val_if_fail (data != NULL, GST_RTSP_EINVAL); @@ -831,6 +819,14 @@ gst_rtsp_connection_read (GstRTSPConnection * conn, guint8 * data, guint size, toread = size; + /* configure timeout if any */ + if (timeout != NULL) { + tv_timeout.tv_sec = timeout->tv_sec; + tv_timeout.tv_usec = timeout->tv_usec; + ptv_timeout = &tv_timeout; + } else + ptv_timeout = NULL; + /* if the call fails, just go in the select.. it should not fail. Else if * there is enough data to read, skip the select call al together.*/ if (IOCTL_SOCKET (conn->fd, FIONREAD, &avail) < 0) @@ -838,20 +834,16 @@ gst_rtsp_connection_read (GstRTSPConnection * conn, guint8 * data, guint size, else if (avail >= toread) goto do_read; - /* configure timeout if any */ - if (timeout != NULL) { - tv_timeout.tv_sec = timeout->tv_sec; - tv_timeout.tv_usec = timeout->tv_usec; - ptv_timeout = &tv_timeout; - } - FD_ZERO (&readfds); FD_SET (conn->fd, &readfds); - FD_SET (READ_SOCKET (conn), &readfds); while (toread > 0) { gint bytes; + /* set inside the loop so that when we did not read enough and we have to + * continue, we still have the cancel socket bit set */ + FD_SET (READ_SOCKET (conn), &readfds); + do { retval = select (FD_SETSIZE, &readfds, NULL, NULL, ptv_timeout); } while ((retval == -1 && errno == EINTR)); @@ -863,20 +855,8 @@ gst_rtsp_connection_read (GstRTSPConnection * conn, guint8 * data, guint size, if (retval == 0) goto select_timeout; - if (FD_ISSET (READ_SOCKET (conn), &readfds)) { - /* read all stop commands */ - while (TRUE) { - gchar command; - int res; - - READ_COMMAND (conn, command, res); - if (res <= 0) { - /* no more commands */ - break; - } - } + if (FD_ISSET (READ_SOCKET (conn), &readfds)) goto stopped; - } do_read: /* if we get here there is activity on the real fd since the select @@ -1168,6 +1148,103 @@ gst_rtsp_connection_free (GstRTSPConnection * conn) return res; } +/** + * gst_rtsp_connection_poll: + * @conn: a #GstRTSPConnection + * @events: a bitmask of #GstRTSPEvent flags to check + * @revents: location for result flags + * @timeout: a timeout + * + * Wait up to the specified @timeout for the connection to become available for + * at least one of the operations specified in @events. When the function returns + * with #GST_RTSP_OK, @revents will contain a bitmask of available operations on + * @conn. + * + * @timeout can be #NULL, in which case this function might block forever. + * + * This function can be canceled with gst_rtsp_connection_flush(). + * + * Returns: #GST_RTSP_OK on success. + * + * Since: 0.10.15 + */ +GstRTSPResult +gst_rtsp_connection_poll (GstRTSPConnection * conn, GstRTSPEvent events, + GstRTSPEvent * revents, GTimeVal * timeout) +{ + fd_set writefds, *pwritefds; + fd_set readfds; + int max_fd; + gint retval; + struct timeval tv, *tvp; + + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (events != 0, GST_RTSP_EINVAL); + g_return_val_if_fail (revents != NULL, GST_RTSP_EINVAL); + + if (events & GST_RTSP_EV_WRITE) { + /* add fd to writer set when asked to */ + FD_ZERO (&writefds); + FD_SET (conn->fd, &writefds); + pwritefds = &writefds; + } else + pwritefds = NULL; + + /* always add cancel socket to readfds */ + FD_ZERO (&readfds); + FD_SET (READ_SOCKET (conn), &readfds); + if (events & GST_RTSP_EV_READ) { + /* add fd to reader set when asked to */ + FD_SET (conn->fd, &readfds); + } + max_fd = MAX (conn->fd, READ_SOCKET (conn)); + + if (timeout) { + tv.tv_sec = timeout->tv_sec; + tv.tv_usec = timeout->tv_usec; + tvp = &tv; + } else + tvp = NULL; + + do { + retval = select (max_fd + 1, &readfds, pwritefds, NULL, tvp); + } while ((retval == -1 && errno == EINTR)); + + if (retval == 0) + goto select_timeout; + + if (retval == -1) + goto select_error; + + if (FD_ISSET (READ_SOCKET (conn), &readfds)) + goto stopped; + + *revents = 0; + if (events & GST_RTSP_EV_READ) { + if (FD_ISSET (conn->fd, &readfds)) + *revents |= GST_RTSP_EV_READ; + } + if (events & GST_RTSP_EV_WRITE) { + if (FD_ISSET (conn->fd, &writefds)) + *revents |= GST_RTSP_EV_WRITE; + } + return GST_RTSP_OK; + + /* ERRORS */ +select_timeout: + { + return GST_RTSP_ETIMEOUT; + } +select_error: + { + return GST_RTSP_ESYS; + } +stopped: + { + return GST_RTSP_EINTR; + } +} + /** * gst_rtsp_connection_next_timeout: * @conn: a #GstRTSPConnection diff --git a/gst-libs/gst/rtsp/gstrtspconnection.h b/gst-libs/gst/rtsp/gstrtspconnection.h index e6112ab0be..34793082ec 100644 --- a/gst-libs/gst/rtsp/gstrtspconnection.h +++ b/gst-libs/gst/rtsp/gstrtspconnection.h @@ -99,6 +99,10 @@ GstRTSPResult gst_rtsp_connection_send (GstRTSPConnection *conn, G GstRTSPResult gst_rtsp_connection_receive (GstRTSPConnection *conn, GstRTSPMessage *message, GTimeVal *timeout); +/* status management */ +GstRTSPResult gst_rtsp_connection_poll (GstRTSPConnection *conn, GstRTSPEvent events, + GstRTSPEvent *revents, GTimeVal *timeout); + /* reset the timeout */ GstRTSPResult gst_rtsp_connection_next_timeout (GstRTSPConnection *conn, GTimeVal *timeout); GstRTSPResult gst_rtsp_connection_reset_timeout (GstRTSPConnection *conn); diff --git a/gst-libs/gst/rtsp/gstrtspdefs.h b/gst-libs/gst/rtsp/gstrtspdefs.h index b6d9dfac31..cf2058bd7a 100644 --- a/gst-libs/gst/rtsp/gstrtspdefs.h +++ b/gst-libs/gst/rtsp/gstrtspdefs.h @@ -100,9 +100,21 @@ typedef enum { GST_RTSP_ENOTIP = -13, GST_RTSP_ETIMEOUT = -14, - GST_RTSP_ELAST = -15, + GST_RTSP_ELAST = -15 } GstRTSPResult; +/** + * GstRTSPEvent: + * @GST_RTSP_EV_READ: connection is readable + * @GST_RTSP_EV_WRITE: connection is writable + * + * The possible events for the connection. + */ +typedef enum { + GST_RTSP_EV_READ = (1 << 0), + GST_RTSP_EV_WRITE = (1 << 1) +} GstRTSPEvent; + /** * GstRTSPFamily: * @GST_RTSP_FAM_NONE: unknown network family @@ -114,7 +126,7 @@ typedef enum { typedef enum { GST_RTSP_FAM_NONE, GST_RTSP_FAM_INET, - GST_RTSP_FAM_INET6, + GST_RTSP_FAM_INET6 } GstRTSPFamily; /** @@ -134,7 +146,7 @@ typedef enum { GST_RTSP_STATE_READY, GST_RTSP_STATE_SEEKING, GST_RTSP_STATE_PLAYING, - GST_RTSP_STATE_RECORDING, + GST_RTSP_STATE_RECORDING } GstRTSPState; /** @@ -146,7 +158,7 @@ typedef enum { */ typedef enum { GST_RTSP_VERSION_INVALID = 0x00, - GST_RTSP_VERSION_1_0 = 0x10, + GST_RTSP_VERSION_1_0 = 0x10 } GstRTSPVersion; /** @@ -178,7 +190,7 @@ typedef enum { GST_RTSP_REDIRECT = (1 << 7), GST_RTSP_SETUP = (1 << 8), GST_RTSP_SET_PARAMETER = (1 << 9), - GST_RTSP_TEARDOWN = (1 << 10), + GST_RTSP_TEARDOWN = (1 << 10) } GstRTSPMethod; /** @@ -312,7 +324,7 @@ typedef enum { GST_RTSP_STS_SERVICE_UNAVAILABLE = 503, GST_RTSP_STS_GATEWAY_TIMEOUT = 504, GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED = 505, - GST_RTSP_STS_OPTION_NOT_SUPPORTED = 551, + GST_RTSP_STS_OPTION_NOT_SUPPORTED = 551 } GstRTSPStatusCode; gchar* gst_rtsp_strresult (GstRTSPResult result);