/* we include this here to get the G_OS_* defines */
#include <glib.h>
+#include <gst/gst.h>
#ifdef G_OS_WIN32
#include <winsock2.h>
} 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
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;
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));
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));
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);
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);
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)
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));
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
}
/**
+ * 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
* @timeout: a timeout
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
* @GST_RTSP_FAM_INET: internet
typedef enum {
GST_RTSP_FAM_NONE,
GST_RTSP_FAM_INET,
- GST_RTSP_FAM_INET6,
+ GST_RTSP_FAM_INET6
} GstRTSPFamily;
/**
GST_RTSP_STATE_READY,
GST_RTSP_STATE_SEEKING,
GST_RTSP_STATE_PLAYING,
- GST_RTSP_STATE_RECORDING,
+ GST_RTSP_STATE_RECORDING
} GstRTSPState;
/**
*/
typedef enum {
GST_RTSP_VERSION_INVALID = 0x00,
- GST_RTSP_VERSION_1_0 = 0x10,
+ GST_RTSP_VERSION_1_0 = 0x10
} GstRTSPVersion;
/**
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;
/**
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);