diff options
Diffstat (limited to 'gst-libs')
-rw-r--r-- | gst-libs/gst/rtsp/Makefile.am | 5 | ||||
-rw-r--r-- | gst-libs/gst/rtsp/gstrtspconnection.c | 839 | ||||
-rw-r--r-- | gst-libs/gst/rtsp/gstrtspconnection.h | 9 | ||||
-rw-r--r-- | gst-libs/gst/rtsp/gstrtspdefs.c | 25 |
4 files changed, 346 insertions, 532 deletions
diff --git a/gst-libs/gst/rtsp/Makefile.am b/gst-libs/gst/rtsp/Makefile.am index f008eea7d..db466ff9e 100644 --- a/gst-libs/gst/rtsp/Makefile.am +++ b/gst-libs/gst/rtsp/Makefile.am @@ -32,8 +32,8 @@ noinst_HEADERS = gstrtsp.h #gstrtspextwms.c #rtspextreal.c -libgstrtsp_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) -libgstrtsp_@GST_MAJORMINOR@_la_LIBADD = $(GST_LIBS) $(WIN32_LIBS) $(HSTRERROR_LIBS) +libgstrtsp_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(GIO_CFLAGS) +libgstrtsp_@GST_MAJORMINOR@_la_LIBADD = $(GST_LIBS) $(GIO_LIBS) libgstrtsp_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) BUILT_SOURCES = $(built_headers) $(built_sources) @@ -76,6 +76,7 @@ GstRtsp-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstrtsp-@GST_MAJORMINO --libtool="$(top_builddir)/libtool" \ --pkg gstreamer-@GST_MAJORMINOR@ \ --pkg gstreamer-sdp-@GST_MAJORMINOR@ \ + --pkg gio-2.0 \ --pkg-export gstreamer-rtsp-@GST_MAJORMINOR@ \ --add-init-section="gst_init(NULL,NULL);" \ --output $@ \ diff --git a/gst-libs/gst/rtsp/gstrtspconnection.c b/gst-libs/gst/rtsp/gstrtspconnection.c index 455cbec6b..9855228be 100644 --- a/gst-libs/gst/rtsp/gstrtspconnection.c +++ b/gst-libs/gst/rtsp/gstrtspconnection.c @@ -61,39 +61,15 @@ #include <string.h> #include <time.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - /* we include this here to get the G_OS_* defines */ #include <glib.h> #include <gst/gst.h> -#ifdef G_OS_WIN32 -/* ws2_32.dll has getaddrinfo and freeaddrinfo on Windows XP and later. - * minwg32 headers check WINVER before allowing the use of these */ -#ifndef WINVER -#define WINVER 0x0501 -#endif -#include <winsock2.h> -#include <ws2tcpip.h> -#define EINPROGRESS WSAEINPROGRESS -#else -#include <sys/ioctl.h> -#include <netdb.h> -#include <sys/socket.h> -#include <fcntl.h> -#include <netinet/in.h> -#endif - -#ifdef HAVE_FIONREAD_IN_SYS_FILIO -#include <sys/filio.h> -#endif - #include "gstrtspconnection.h" #include "gst/glib-compat-private.h" +#ifdef IP_TOS union gst_sockaddr { struct sockaddr sa; @@ -101,6 +77,7 @@ union gst_sockaddr struct sockaddr_in6 sa_in6; struct sockaddr_storage sa_stor; }; +#endif typedef struct { @@ -117,42 +94,6 @@ typedef struct #define SEND_FLAGS 0 #endif -#ifdef G_OS_WIN32 -#define READ_SOCKET(fd, buf, len) recv (fd, (char *)buf, len, 0) -#define WRITE_SOCKET(fd, buf, len) send (fd, (const char *)buf, len, SEND_FLAGS) -#define SETSOCKOPT(sock, level, name, val, len) setsockopt (sock, level, name, (const char *)val, len) -#define CLOSE_SOCKET(sock) closesocket (sock) -#define ERRNO_IS_EAGAIN (WSAGetLastError () == WSAEWOULDBLOCK) -#define ERRNO_IS_EINTR (WSAGetLastError () == WSAEINTR) -/* According to Microsoft's connect() documentation this one returns - * WSAEWOULDBLOCK and not WSAEINPROGRESS. */ -#define ERRNO_IS_EINPROGRESS (WSAGetLastError () == WSAEWOULDBLOCK) -#else -#define READ_SOCKET(fd, buf, len) read (fd, buf, len) -#define WRITE_SOCKET(fd, buf, len) send (fd, buf, len, SEND_FLAGS) -#define SETSOCKOPT(sock, level, name, val, len) setsockopt (sock, level, name, val, len) -#define CLOSE_SOCKET(sock) close (sock) -#define ERRNO_IS_EAGAIN (errno == EAGAIN) -#define ERRNO_IS_EINTR (errno == EINTR) -#define ERRNO_IS_EINPROGRESS (errno == EINPROGRESS) -#endif - -#define ADD_POLLFD(fdset, pfd, fd) \ -G_STMT_START { \ - (pfd)->fd = fd; \ - gst_poll_add_fd (fdset, pfd); \ -} G_STMT_END - -#define REMOVE_POLLFD(fdset, pfd) \ -G_STMT_START { \ - if ((pfd)->fd != -1) { \ - GST_DEBUG ("remove fd %d", (pfd)->fd); \ - gst_poll_remove_fd (fdset, pfd); \ - CLOSE_SOCKET ((pfd)->fd); \ - (pfd)->fd = -1; \ - } \ -} G_STMT_END - typedef enum { TUNNEL_STATE_NONE, @@ -170,19 +111,16 @@ struct _GstRTSPConnection GstRTSPUrl *url; /* connection state */ - GstPollFD fd0; - GstPollFD fd1; - - GstPollFD *readfd; - GstPollFD *writefd; - + GSocket *read_socket; + GSocket *write_socket; gboolean manual_http; + GSocket *socket0, *socket1; + GCancellable *cancellable; gchar tunnelid[TUNNELID_LEN]; gboolean tunneled; GstRTSPTunnelState tstate; - GstPoll *fdset; gchar *ip; gint read_ahead; @@ -263,31 +201,14 @@ GstRTSPResult gst_rtsp_connection_create (const GstRTSPUrl * url, GstRTSPConnection ** conn) { GstRTSPConnection *newconn; -#ifdef G_OS_WIN32 - WSADATA w; - int error; -#endif g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); -#ifdef G_OS_WIN32 - error = WSAStartup (0x0202, &w); - - if (error) - goto startup_error; - - if (w.wVersion != 0x0202) - goto version_error; -#endif - newconn = g_new0 (GstRTSPConnection, 1); - if ((newconn->fdset = gst_poll_new (TRUE)) == NULL) - goto no_fdset; + newconn->cancellable = g_cancellable_new (); newconn->url = gst_rtsp_url_copy (url); - newconn->fd0.fd = -1; - newconn->fd1.fd = -1; newconn->timer = g_timer_new (); newconn->timeout = 60; newconn->cseq = 1; @@ -300,69 +221,38 @@ gst_rtsp_connection_create (const GstRTSPUrl * url, GstRTSPConnection ** conn) *conn = newconn; return GST_RTSP_OK; - - /* ERRORS */ -#ifdef G_OS_WIN32 -startup_error: - { - g_warning ("Error %d on WSAStartup", error); - return GST_RTSP_EWSASTART; - } -version_error: - { - g_warning ("Windows sockets are not version 0x202 (current 0x%x)", - w.wVersion); - WSACleanup (); - return GST_RTSP_EWSAVERSION; - } -#endif -no_fdset: - { - g_free (newconn); -#ifdef G_OS_WIN32 - WSACleanup (); -#endif - return GST_RTSP_ESYS; - } } /** - * gst_rtsp_connection_create_from_fd: - * @fd: a file descriptor + * gst_rtsp_connection_create_from_socket: + * @socket: a #GSocket * @ip: the IP address of the other end * @port: the port used by the other end * @initial_buffer: data already read from @fd * @conn: storage for a #GstRTSPConnection * * Create a new #GstRTSPConnection for handling communication on the existing - * file descriptor @fd. The @initial_buffer contains any data already read from - * @fd which should be used before starting to read new data. + * socket @socket. The @initial_buffer contains any data already read from + * @socket which should be used before starting to read new data. * * Returns: #GST_RTSP_OK when @conn contains a valid connection. * * Since: 0.10.25 */ GstRTSPResult -gst_rtsp_connection_create_from_fd (gint fd, const gchar * ip, guint16 port, - const gchar * initial_buffer, GstRTSPConnection ** conn) +gst_rtsp_connection_create_from_socket (GSocket * socket, const gchar * ip, + guint16 port, const gchar * initial_buffer, GstRTSPConnection ** conn) { GstRTSPConnection *newconn = NULL; GstRTSPUrl *url; -#ifdef G_OS_WIN32 - gulong flags = 1; -#endif GstRTSPResult res; - g_return_val_if_fail (fd >= 0, GST_RTSP_EINVAL); + g_return_val_if_fail (G_IS_SOCKET (socket), GST_RTSP_EINVAL); g_return_val_if_fail (ip != 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 */ -#ifndef G_OS_WIN32 - fcntl (fd, F_SETFL, O_NONBLOCK); -#else - ioctlsocket (fd, FIONBIO, &flags); -#endif /* G_OS_WIN32 */ + g_socket_set_blocking (socket, FALSE); /* create a url for the client address */ url = g_new0 (GstRTSPUrl, 1); @@ -373,11 +263,10 @@ gst_rtsp_connection_create_from_fd (gint fd, const gchar * ip, guint16 port, GST_RTSP_CHECK (gst_rtsp_connection_create (url, &newconn), newconn_failed); gst_rtsp_url_free (url); - ADD_POLLFD (newconn->fdset, &newconn->fd0, fd); - /* both read and write initially */ - newconn->readfd = &newconn->fd0; - newconn->writefd = &newconn->fd0; + newconn->socket0 = G_SOCKET (g_object_ref (socket)); + newconn->socket1 = G_SOCKET (g_object_ref (socket)); + newconn->write_socket = newconn->read_socket = newconn->socket0; newconn->ip = g_strdup (ip); @@ -397,10 +286,11 @@ newconn_failed: /** * gst_rtsp_connection_accept: - * @sock: a socket + * @socket: a socket * @conn: storage for a #GstRTSPConnection + * @cancellable: a #GCancellable to cancel the operation * - * Accept a new connection on @sock and create a new #GstRTSPConnection for + * Accept a new connection on @socket and create a new #GstRTSPConnection for * handling communication on new socket. * * Returns: #GST_RTSP_OK when @conn contains a valid connection. @@ -408,238 +298,182 @@ newconn_failed: * Since: 0.10.23 */ GstRTSPResult -gst_rtsp_connection_accept (gint sock, GstRTSPConnection ** conn) +gst_rtsp_connection_accept (GSocket * socket, GstRTSPConnection ** conn, + GCancellable * cancellable) { - int fd; - union gst_sockaddr sa; - socklen_t slen = sizeof (sa); - gchar ip[INET6_ADDRSTRLEN]; + GError *err = NULL; + gchar *ip; guint16 port; + GSocket *client_sock; + GSocketAddress *addr; + GstRTSPResult ret; - g_return_val_if_fail (sock >= 0, GST_RTSP_EINVAL); + g_return_val_if_fail (G_IS_SOCKET (socket), GST_RTSP_EINVAL); g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); - memset (&sa, 0, slen); - -#ifndef G_OS_WIN32 - fd = accept (sock, &sa.sa, &slen); -#else - fd = accept (sock, &sa.sa, (gint *) & slen); -#endif /* G_OS_WIN32 */ - if (fd == -1) + client_sock = g_socket_accept (socket, cancellable, &err); + if (!client_sock) goto accept_failed; - if (getnameinfo (&sa.sa, slen, ip, sizeof (ip), NULL, 0, NI_NUMERICHOST) != 0) + addr = g_socket_get_remote_address (client_sock, &err); + if (!addr) goto getnameinfo_failed; - if (sa.sa.sa_family == AF_INET) - port = sa.sa_in.sin_port; - else if (sa.sa.sa_family == AF_INET6) - port = sa.sa_in6.sin6_port; - else - goto wrong_family; + ip = g_inet_address_to_string (g_inet_socket_address_get_address + (G_INET_SOCKET_ADDRESS (addr))); + port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)); + + ret = + gst_rtsp_connection_create_from_socket (client_sock, ip, port, NULL, + conn); + g_free (ip); - return gst_rtsp_connection_create_from_fd (fd, ip, port, NULL, conn); + return ret; /* ERRORS */ accept_failed: { + GST_DEBUG ("Accepting client failed: %s", err->message); + g_clear_error (&err); return GST_RTSP_ESYS; } getnameinfo_failed: -wrong_family: { - CLOSE_SOCKET (fd); + if (!g_socket_close (client_sock, &err)) { + GST_DEBUG ("Closing socket failed: %s", err->message); + g_clear_error (&err); + } + g_object_unref (client_sock); return GST_RTSP_ERROR; } } static gchar * -do_resolve (const gchar * host) -{ - gchar ip[INET6_ADDRSTRLEN]; - struct addrinfo *aires, hints; - struct addrinfo *ai; - gint aierr; - - memset (&hints, 0, sizeof (struct addrinfo)); - hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ - hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ - hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ - hints.ai_protocol = 0; /* Any protocol */ - hints.ai_canonname = NULL; - hints.ai_addr = NULL; - hints.ai_next = NULL; - - aierr = getaddrinfo (host, NULL, &hints, &aires); - if (aierr != 0) - goto no_addrinfo; - - for (ai = aires; ai; ai = ai->ai_next) { - if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) { - break; +do_resolve (const gchar * host, GCancellable * cancellable) +{ + GResolver *resolver; + GInetAddress *addr; + GError *err = NULL; + gchar *ip; + + addr = g_inet_address_new_from_string (host); + if (!addr) { + GList *results, *l; + + resolver = g_resolver_get_default (); + + results = g_resolver_lookup_by_name (resolver, host, cancellable, &err); + if (!results) + goto name_resolve; + + for (l = results; l; l = l->next) { + GInetAddress *tmp = l->data; + + if (g_inet_address_get_family (tmp) == G_SOCKET_FAMILY_IPV4 || + g_inet_address_get_family (tmp) == G_SOCKET_FAMILY_IPV6) { + addr = G_INET_ADDRESS (g_object_ref (tmp)); + break; + } } + + g_resolver_free_addresses (results); + g_object_unref (resolver); } - if (ai == NULL) - goto no_family; - aierr = getnameinfo (ai->ai_addr, ai->ai_addrlen, ip, sizeof (ip), NULL, 0, - NI_NUMERICHOST | NI_NUMERICSERV); - if (aierr != 0) - goto no_address; + if (!addr) + return NULL; - freeaddrinfo (aires); + ip = g_inet_address_to_string (addr); + g_object_unref (addr); - return g_strdup (ip); + return ip; /* ERRORS */ -no_addrinfo: - { - GST_ERROR ("no addrinfo found for %s: %s", host, gai_strerror (aierr)); - return NULL; - } -no_family: +name_resolve: { - GST_ERROR ("no family found for %s", host); - freeaddrinfo (aires); - return NULL; - } -no_address: - { - GST_ERROR ("no address found for %s: %s", host, gai_strerror (aierr)); - freeaddrinfo (aires); + GST_ERROR ("failed to resolve %s: %s", host, err->message); + g_clear_error (&err); + g_object_unref (resolver); return NULL; } } static GstRTSPResult -do_connect (const gchar * ip, guint16 port, GstPollFD * fdout, - GstPoll * fdset, GTimeVal * timeout) +do_connect (const gchar * ip, guint16 port, GSocket ** socket_out, + GTimeVal * timeout, GCancellable * cancellable) { - gint fd; - struct addrinfo hints; - struct addrinfo *aires; - struct addrinfo *ai; - gint aierr; - gchar service[NI_MAXSERV]; - gint ret; -#ifdef G_OS_WIN32 - unsigned long flags = 1; -#endif /* G_OS_WIN32 */ + GSocket *socket; GstClockTime to; - gint retval; - - memset (&hints, 0, sizeof hints); - hints.ai_flags = AI_NUMERICHOST; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - g_snprintf (service, sizeof (service) - 1, "%hu", port); - service[sizeof (service) - 1] = '\0'; - - aierr = getaddrinfo (ip, service, &hints, &aires); - if (aierr != 0) - goto no_addrinfo; - - for (ai = aires; ai; ai = ai->ai_next) { - if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) { - break; - } - } - if (ai == NULL) - goto no_family; - - fd = socket (ai->ai_family, SOCK_STREAM, 0); - if (fd == -1) + GInetAddress *addr; + GSocketAddress *saddr; + GError *err = NULL; + + addr = g_inet_address_new_from_string (ip); + g_assert (addr); + saddr = g_inet_socket_address_new (addr, port); + g_object_unref (addr); + + socket = + g_socket_new (g_socket_address_get_family (saddr), G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_TCP, &err); + if (socket == NULL) goto no_socket; /* set to non-blocking mode so that we can cancel the connect */ -#ifndef G_OS_WIN32 - fcntl (fd, F_SETFL, O_NONBLOCK); -#else - ioctlsocket (fd, FIONBIO, &flags); -#endif /* G_OS_WIN32 */ - - /* add the socket to our fdset */ - ADD_POLLFD (fdset, fdout, fd); + g_socket_set_blocking (socket, FALSE); /* we are going to connect ASYNC now */ - ret = connect (fd, ai->ai_addr, ai->ai_addrlen); - if (ret == 0) + if (!g_socket_connect (socket, saddr, cancellable, &err)) { + if (!g_error_matches (err, G_IO_ERROR, G_IO_ERROR_PENDING)) + goto sys_error; + } else { goto done; - if (!ERRNO_IS_EINPROGRESS) - goto sys_error; + } /* wait for connect to complete up to the specified timeout or until we got * interrupted. */ - gst_poll_fd_ctl_write (fdset, fdout, TRUE); - to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE; - do { - retval = gst_poll_wait (fdset, to); - } while (retval == -1 && (errno == EINTR || errno == EAGAIN)); - - if (retval == 0) - goto timeout; - else if (retval == -1) - goto sys_error; - - /* we can still have an error connecting on windows */ - if (gst_poll_fd_has_error (fdset, fdout)) { - socklen_t len = sizeof (errno); -#ifndef G_OS_WIN32 - getsockopt (fd, SOL_SOCKET, SO_ERROR, &errno, &len); -#else - getsockopt (fd, SOL_SOCKET, SO_ERROR, (char *) &errno, &len); -#endif - goto sys_error; - } else { -#ifdef __APPLE__ - /* osx wakes up select with POLLOUT if the connection is refused... */ - socklen_t len = sizeof (errno); - getsockopt (fd, SOL_SOCKET, SO_ERROR, (char *) &errno, &len); - if (errno != 0) + g_socket_set_timeout (socket, (to + GST_SECOND - 1) / GST_SECOND); + if (!g_socket_condition_wait (socket, G_IO_OUT, cancellable, &err)) { + g_socket_set_timeout (socket, 0); + if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_TIMED_OUT)) + goto timeout; + else goto sys_error; -#endif } + g_socket_set_timeout (socket, 0); - gst_poll_fd_ignored (fdset, fdout); + if (g_socket_check_connect_result (socket, &err)) + goto sys_error; done: - freeaddrinfo (aires); + g_object_unref (saddr); return GST_RTSP_OK; /* ERRORS */ -no_addrinfo: - { - GST_ERROR ("no addrinfo found for %s: %s", ip, gai_strerror (aierr)); - return GST_RTSP_ERROR; - } -no_family: - { - GST_ERROR ("no family found for %s", ip); - freeaddrinfo (aires); - return GST_RTSP_ERROR; - } no_socket: { - GST_ERROR ("no socket %d (%s)", errno, g_strerror (errno)); - freeaddrinfo (aires); + GST_ERROR ("no socket: %s", err->message); + g_clear_error (&err); + g_object_unref (saddr); return GST_RTSP_ESYS; } sys_error: { - GST_ERROR ("system error %d (%s)", errno, g_strerror (errno)); - REMOVE_POLLFD (fdset, fdout); - freeaddrinfo (aires); + GST_ERROR ("system error: %s", err->message); + g_clear_error (&err); + g_object_unref (saddr); + g_object_unref (socket); return GST_RTSP_ESYS; } timeout: { GST_ERROR ("timeout"); - REMOVE_POLLFD (fdset, fdout); - freeaddrinfo (aires); + g_clear_error (&err); + g_object_unref (saddr); + g_object_unref (socket); return GST_RTSP_ETIMEOUT; } } @@ -700,7 +534,7 @@ setup_tunneling (GstRTSPConnection * conn, GTimeVal * timeout) gst_rtsp_message_add_header (msg, GST_RTSP_HDR_PRAGMA, "no-cache"); /* we start by writing to this fd */ - conn->writefd = &conn->fd0; + conn->write_socket = conn->socket0; /* we need to temporarily set conn->tunneled to FALSE to prevent the HTTP * request from being base64 encoded */ @@ -733,7 +567,7 @@ setup_tunneling (GstRTSPConnection * conn, GTimeVal * timeout) hostparam = g_strdup_printf ("%s:%d", url->host, url_port); } else { /* and resolve the new ip address */ - if (!(ip = do_resolve (value))) + if (!(ip = do_resolve (value, conn->cancellable))) goto not_resolved; g_free (conn->ip); conn->ip = ip; @@ -741,12 +575,12 @@ setup_tunneling (GstRTSPConnection * conn, GTimeVal * timeout) } /* connect to the host/port */ - res = do_connect (ip, port, &conn->fd1, conn->fdset, timeout); + res = do_connect (ip, port, &conn->socket1, timeout, conn->cancellable); if (res != GST_RTSP_OK) goto connect_failed; /* this is now our writing socket */ - conn->writefd = &conn->fd1; + conn->write_socket = conn->socket1; /* create the POST request for the write connection */ GST_RTSP_CHECK (gst_rtsp_message_new_request (&msg, GST_RTSP_POST, uri), @@ -842,12 +676,12 @@ gst_rtsp_connection_connect (GstRTSPConnection * conn, GTimeVal * timeout) g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); g_return_val_if_fail (conn->url != NULL, GST_RTSP_EINVAL); - g_return_val_if_fail (conn->fd0.fd < 0, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->socket0 == NULL, GST_RTSP_EINVAL); url = conn->url; if (conn->proxy_host && conn->tunneled) { - if (!(ip = do_resolve (conn->proxy_host))) { + if (!(ip = do_resolve (conn->proxy_host, conn->cancellable))) { GST_ERROR ("could not resolve %s", conn->proxy_host); goto not_resolved; } @@ -855,7 +689,7 @@ gst_rtsp_connection_connect (GstRTSPConnection * conn, GTimeVal * timeout) g_free (conn->proxy_host); conn->proxy_host = ip; } else { - if (!(ip = do_resolve (url->host))) { + if (!(ip = do_resolve (url->host, conn->cancellable))) { GST_ERROR ("could not resolve %s", url->host); goto not_resolved; } @@ -867,19 +701,19 @@ gst_rtsp_connection_connect (GstRTSPConnection * conn, GTimeVal * timeout) } /* connect to the host/port */ - res = do_connect (ip, port, &conn->fd0, conn->fdset, timeout); + res = do_connect (ip, port, &conn->socket0, timeout, conn->cancellable); if (res != GST_RTSP_OK) goto connect_failed; /* this is our read URL */ - conn->readfd = &conn->fd0; + conn->read_socket = conn->socket0; if (conn->tunneled) { res = setup_tunneling (conn, timeout); if (res != GST_RTSP_OK) goto tunneling_failed; } else { - conn->writefd = &conn->fd0; + conn->write_socket = conn->socket0; } return GST_RTSP_OK; @@ -1050,7 +884,8 @@ gen_date_string (gchar * date_string, guint len) } static GstRTSPResult -write_bytes (gint fd, const guint8 * buffer, guint * idx, guint size) +write_bytes (GSocket * socket, const guint8 * buffer, guint * idx, guint size, + GCancellable * cancellable) { guint left; @@ -1060,16 +895,20 @@ write_bytes (gint fd, const guint8 * buffer, guint * idx, guint size) left = size - *idx; while (left) { - gint r; + GError *err = NULL; + gssize r; - r = WRITE_SOCKET (fd, &buffer[*idx], left); + r = g_socket_send (socket, (gchar *) & buffer[*idx], left, cancellable, + &err); if (G_UNLIKELY (r == 0)) { return GST_RTSP_EINTR; } else if (G_UNLIKELY (r < 0)) { - if (ERRNO_IS_EAGAIN) + if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + g_clear_error (&err); return GST_RTSP_EINTR; - if (!ERRNO_IS_EINTR) - return GST_RTSP_ESYS; + } + g_clear_error (&err); + return GST_RTSP_ESYS; } else { left -= r; *idx += r; @@ -1079,7 +918,8 @@ write_bytes (gint fd, const guint8 * buffer, guint * idx, guint size) } static gint -fill_raw_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size) +fill_raw_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size, + GError ** err) { gint out = 0; @@ -1098,9 +938,10 @@ fill_raw_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size) } if (G_LIKELY (size > (guint) out)) { - gint r; + gssize r; - r = READ_SOCKET (conn->readfd->fd, &buffer[out], size - out); + r = g_socket_receive (conn->read_socket, (gchar *) & buffer[out], + size - out, conn->cancellable, err); if (r <= 0) { if (out == 0) out = r; @@ -1112,7 +953,8 @@ fill_raw_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size) } static gint -fill_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size) +fill_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size, + GError ** err) { DecodeCtx *ctx = conn->ctxp; gint out = 0; @@ -1134,7 +976,7 @@ fill_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size) break; /* try to read more bytes */ - r = fill_raw_bytes (conn, in, sizeof (in)); + r = fill_raw_bytes (conn, in, sizeof (in), err); if (r <= 0) { if (out == 0) out = r; @@ -1147,7 +989,7 @@ fill_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size) &ctx->save); } } else { - out = fill_raw_bytes (conn, buffer, size); + out = fill_raw_bytes (conn, buffer, size, err); } return out; @@ -1157,6 +999,7 @@ static GstRTSPResult read_bytes (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size) { guint left; + GError *err = NULL; if (G_UNLIKELY (*idx > size)) return GST_RTSP_ERROR; @@ -1166,14 +1009,16 @@ read_bytes (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size) while (left) { gint r; - r = fill_bytes (conn, &buffer[*idx], left); + r = fill_bytes (conn, &buffer[*idx], left, &err); if (G_UNLIKELY (r == 0)) { return GST_RTSP_EEOF; } else if (G_UNLIKELY (r < 0)) { - if (ERRNO_IS_EAGAIN) + if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + g_clear_error (&err); return GST_RTSP_EINTR; - if (!ERRNO_IS_EINTR) - return GST_RTSP_ESYS; + } + g_clear_error (&err); + return GST_RTSP_ESYS; } else { left -= r; *idx += r; @@ -1191,6 +1036,8 @@ read_bytes (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size) static GstRTSPResult read_line (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size) { + GError *err = NULL; + while (TRUE) { guint8 c; gint r; @@ -1212,15 +1059,17 @@ read_line (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size) conn->read_ahead = 0; } else { /* read the next character */ - r = fill_bytes (conn, &c, 1); + r = fill_bytes (conn, &c, 1, &err); if (G_UNLIKELY (r == 0)) { return GST_RTSP_EEOF; } else if (G_UNLIKELY (r < 0)) { - if (ERRNO_IS_EAGAIN) + if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + g_clear_error (&err); return GST_RTSP_EINTR; - if (!ERRNO_IS_EINTR) - return GST_RTSP_ESYS; - continue; + } + + g_clear_error (&err); + return GST_RTSP_ESYS; } } @@ -1230,19 +1079,21 @@ read_line (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size) retry: /* need to read ahead one more character to know what to do... */ - r = fill_bytes (conn, &read_ahead, 1); + r = fill_bytes (conn, &read_ahead, 1, &err); if (G_UNLIKELY (r == 0)) { return GST_RTSP_EEOF; } else if (G_UNLIKELY (r < 0)) { - if (ERRNO_IS_EAGAIN) { + 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; return GST_RTSP_EINTR; + g_clear_error (&err); + return GST_RTSP_EINTR; } - if (!ERRNO_IS_EINTR) - return GST_RTSP_ESYS; - goto retry; + + g_clear_error (&err); + return GST_RTSP_ESYS; } if (read_ahead == ' ' || read_ahead == '\t') { @@ -1326,20 +1177,13 @@ gst_rtsp_connection_write (GstRTSPConnection * conn, const guint8 * data, guint size, GTimeVal * timeout) { guint offset; - gint retval; GstClockTime to; GstRTSPResult res; + GError *err = NULL; 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 (conn->writefd != NULL, GST_RTSP_EINVAL); - - gst_poll_set_controllable (conn->fdset, TRUE); - gst_poll_fd_ctl_write (conn->fdset, conn->writefd, TRUE); - gst_poll_fd_ctl_read (conn->fdset, conn->readfd, FALSE); - /* clear all previous poll results */ - gst_poll_fd_ignored (conn->fdset, conn->writefd); - gst_poll_fd_ignored (conn->fdset, conn->readfd); + g_return_val_if_fail (conn->write_socket != NULL, GST_RTSP_EINVAL); to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE; @@ -1347,30 +1191,31 @@ gst_rtsp_connection_write (GstRTSPConnection * conn, const guint8 * data, while (TRUE) { /* try to write */ - res = write_bytes (conn->writefd->fd, data, &offset, size); + res = + write_bytes (conn->write_socket, 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 */ - do { - retval = gst_poll_wait (conn->fdset, to); - } while (retval == -1 && (errno == EINTR || errno == EAGAIN)); - - if (G_UNLIKELY (retval == 0)) - goto timeout; - - if (G_UNLIKELY (retval == -1)) { - if (errno == EBUSY) + 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 - goto select_error; + } 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; } - - /* could also be an error with read socket */ - if (gst_poll_fd_has_error (conn->fdset, conn->readfd)) - goto socket_error; + g_socket_set_timeout (conn->write_socket, 0); } return GST_RTSP_OK; @@ -1387,10 +1232,6 @@ stopped: { return GST_RTSP_EINTR; } -socket_error: - { - return GST_RTSP_ENET; - } write_error: { return res; @@ -2067,13 +1908,13 @@ gst_rtsp_connection_read (GstRTSPConnection * conn, guint8 * data, guint size, GTimeVal * timeout) { guint offset; - gint retval; GstClockTime to; GstRTSPResult res; + GError *err = NULL; 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 (conn->readfd != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->read_socket != NULL, GST_RTSP_EINVAL); if (G_UNLIKELY (size == 0)) return GST_RTSP_OK; @@ -2083,10 +1924,6 @@ gst_rtsp_connection_read (GstRTSPConnection * conn, guint8 * data, guint size, /* configure timeout if any */ to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE; - gst_poll_set_controllable (conn->fdset, TRUE); - gst_poll_fd_ctl_write (conn->fdset, conn->writefd, FALSE); - gst_poll_fd_ctl_read (conn->fdset, conn->readfd, TRUE); - while (TRUE) { res = read_bytes (conn, data, &offset, size); if (G_UNLIKELY (res == GST_RTSP_EEOF)) @@ -2096,26 +1933,23 @@ gst_rtsp_connection_read (GstRTSPConnection * conn, guint8 * data, guint size, if (G_UNLIKELY (res != GST_RTSP_EINTR)) goto read_error; - do { - retval = gst_poll_wait (conn->fdset, to); - } while (retval == -1 && (errno == EINTR || errno == EAGAIN)); - - /* check for timeout */ - if (G_UNLIKELY (retval == 0)) - goto select_timeout; - - if (G_UNLIKELY (retval == -1)) { - if (errno == EBUSY) + 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_BUSY)) { + g_clear_error (&err); goto stopped; - else - goto select_error; + } 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; } - - /* could also be an error with write socket */ - if (gst_poll_fd_has_error (conn->fdset, conn->writefd)) - goto socket_error; - - gst_poll_set_controllable (conn->fdset, FALSE); + g_socket_set_timeout (conn->read_socket, 0); } return GST_RTSP_OK; @@ -2136,10 +1970,6 @@ eof: { return GST_RTSP_EEOF; } -socket_error: - { - res = GST_RTSP_ENET; - } read_error: { return res; @@ -2202,20 +2032,16 @@ gst_rtsp_connection_receive (GstRTSPConnection * conn, GstRTSPMessage * message, { GstRTSPResult res; GstRTSPBuilder builder; - gint retval; GstClockTime to; + GError *err = NULL; 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 (conn->readfd != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->read_socket != NULL, GST_RTSP_EINVAL); /* configure timeout if any */ to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE; - gst_poll_set_controllable (conn->fdset, TRUE); - gst_poll_fd_ctl_write (conn->fdset, conn->writefd, FALSE); - gst_poll_fd_ctl_read (conn->fdset, conn->readfd, TRUE); - memset (&builder, 0, sizeof (GstRTSPBuilder)); while (TRUE) { res = build_next (&builder, message, conn); @@ -2259,28 +2085,23 @@ gst_rtsp_connection_receive (GstRTSPConnection * conn, GstRTSPMessage * message, } else if (G_UNLIKELY (res != GST_RTSP_EINTR)) goto read_error; - do { - retval = gst_poll_wait (conn->fdset, to); - } while (retval == -1 && (errno == EINTR || errno == EAGAIN)); - - /* check for timeout */ - if (G_UNLIKELY (retval == 0)) - goto select_timeout; - - if (G_UNLIKELY (retval == -1)) { - if (errno == EBUSY) + 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_BUSY)) { + g_clear_error (&err); goto stopped; - else - goto select_error; + } 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; } - - /* could also be an error with write socket */ - if (gst_poll_fd_has_error (conn->fdset, conn->writefd)) - goto socket_error; - - /* once we start reading the wait cannot be controlled */ - if (builder.state != STATE_START) - gst_poll_set_controllable (conn->fdset, FALSE); + g_socket_set_timeout (conn->read_socket, 0); } /* we have a message here */ @@ -2309,11 +2130,6 @@ eof: res = GST_RTSP_EEOF; goto cleanup; } -socket_error: - { - res = GST_RTSP_ENET; - goto cleanup; - } read_error: cleanup: { @@ -2346,10 +2162,8 @@ gst_rtsp_connection_close (GstRTSPConnection * conn) conn->initial_buffer = NULL; conn->initial_buffer_offset = 0; - REMOVE_POLLFD (conn->fdset, &conn->fd0); - REMOVE_POLLFD (conn->fdset, &conn->fd1); - conn->writefd = NULL; - conn->readfd = NULL; + conn->write_socket = NULL; + conn->read_socket = NULL; conn->tunneled = FALSE; conn->tstate = TUNNEL_STATE_NONE; conn->ctxp = NULL; @@ -2381,14 +2195,18 @@ gst_rtsp_connection_free (GstRTSPConnection * conn) g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); res = gst_rtsp_connection_close (conn); - gst_poll_free (conn->fdset); + if (conn->socket0) + g_object_unref (conn->socket0); + if (conn->socket1) + g_object_unref (conn->socket1); + + if (conn->cancellable) + g_object_unref (conn->cancellable); + g_timer_destroy (conn->timer); gst_rtsp_url_free (conn->url); g_free (conn->proxy_host); g_free (conn); -#ifdef G_OS_WIN32 - WSACleanup (); -#endif return res; } @@ -2418,64 +2236,66 @@ gst_rtsp_connection_poll (GstRTSPConnection * conn, GstRTSPEvent events, GstRTSPEvent * revents, GTimeVal * timeout) { GstClockTime to; - gint retval; + GMainContext *ctx; + GSource *rs, *ws, *ts; + GIOCondition condition; 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); - g_return_val_if_fail (conn->readfd != NULL, GST_RTSP_EINVAL); - g_return_val_if_fail (conn->writefd != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->read_socket != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->write_socket != NULL, GST_RTSP_EINVAL); - gst_poll_set_controllable (conn->fdset, TRUE); - - /* add fd to writer set when asked to */ - gst_poll_fd_ctl_write (conn->fdset, conn->writefd, - events & GST_RTSP_EV_WRITE); - - /* add fd to reader set when asked to */ - gst_poll_fd_ctl_read (conn->fdset, conn->readfd, events & GST_RTSP_EV_READ); + ctx = g_main_context_new (); /* configure timeout if any */ to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE; - do { - retval = gst_poll_wait (conn->fdset, to); - } while (retval == -1 && (errno == EINTR || errno == EAGAIN)); + if (timeout) { + ts = g_timeout_source_new (to / GST_MSECOND); + g_source_set_dummy_callback (ts); + g_source_attach (ts, ctx); + g_source_unref (ts); + } - if (G_UNLIKELY (retval == 0)) - goto select_timeout; + rs = g_socket_create_source (conn->read_socket, + G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP, conn->cancellable); + g_source_set_dummy_callback (rs); + g_source_attach (rs, ctx); + g_source_unref (rs); - if (G_UNLIKELY (retval == -1)) { - if (errno == EBUSY) - goto stopped; - else - goto select_error; - } + ws = g_socket_create_source (conn->write_socket, + G_IO_OUT | G_IO_ERR | G_IO_HUP, conn->cancellable); + g_source_set_dummy_callback (ws); + g_source_attach (ws, ctx); + g_source_unref (ws); + + /* Returns after handling all pending events */ + g_main_context_iteration (ctx, TRUE); + + g_main_context_unref (ctx); + + condition = + g_socket_condition_check (conn->read_socket, + G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP); + condition |= + g_socket_condition_check (conn->write_socket, + G_IO_OUT | G_IO_ERR | G_IO_HUP); *revents = 0; if (events & GST_RTSP_EV_READ) { - if (gst_poll_fd_can_read (conn->fdset, conn->readfd)) + if ((condition & G_IO_IN) || (condition & G_IO_PRI)) *revents |= GST_RTSP_EV_READ; } if (events & GST_RTSP_EV_WRITE) { - if (gst_poll_fd_can_write (conn->fdset, conn->writefd)) + if ((condition & G_IO_OUT)) *revents |= GST_RTSP_EV_WRITE; } - return GST_RTSP_OK; - /* ERRORS */ -select_timeout: - { + if (*revents == 0) return GST_RTSP_ETIMEOUT; - } -select_error: - { - return GST_RTSP_ESYS; - } -stopped: - { - return GST_RTSP_EINTR; - } + + return GST_RTSP_OK; } /** @@ -2563,7 +2383,10 @@ gst_rtsp_connection_flush (GstRTSPConnection * conn, gboolean flush) { g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); - gst_poll_set_flushing (conn->fdset, flush); + if (flush) + g_cancellable_cancel (conn->cancellable); + else + g_cancellable_reset (conn->cancellable); return GST_RTSP_OK; } @@ -2720,16 +2543,21 @@ gst_rtsp_connection_clear_auth_params (GstRTSPConnection * conn) } static GstRTSPResult -set_qos_dscp (gint fd, guint qos_dscp) +set_qos_dscp (GSocket * socket, guint qos_dscp) { +#ifndef IP_TOS + return GST_RTSP_OK; +#else + gint fd; union gst_sockaddr sa; socklen_t slen = sizeof (sa); gint af; gint tos; - if (fd == -1) + if (!socket) return GST_RTSP_OK; + fd = g_socket_get_fd (socket); if (getsockname (fd, &sa.sa, &slen) < 0) goto no_getsockname; @@ -2746,12 +2574,12 @@ set_qos_dscp (gint fd, guint qos_dscp) switch (af) { case AF_INET: - if (SETSOCKOPT (fd, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)) < 0) + if (setsockopt (fd, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)) < 0) goto no_setsockopt; break; case AF_INET6: #ifdef IPV6_TCLASS - if (SETSOCKOPT (fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof (tos)) < 0) + if (setsockopt (fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof (tos)) < 0) goto no_setsockopt; break; #endif @@ -2767,11 +2595,11 @@ no_setsockopt: { return GST_RTSP_ESYS; } - wrong_family: { return GST_RTSP_ERROR; } +#endif } /** @@ -2791,12 +2619,12 @@ gst_rtsp_connection_set_qos_dscp (GstRTSPConnection * conn, guint qos_dscp) GstRTSPResult res; g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); - g_return_val_if_fail (conn->readfd != NULL, GST_RTSP_EINVAL); - g_return_val_if_fail (conn->writefd != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->read_socket != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->write_socket != NULL, GST_RTSP_EINVAL); - res = set_qos_dscp (conn->fd0.fd, qos_dscp); + res = set_qos_dscp (conn->socket0, qos_dscp); if (res == GST_RTSP_OK) - res = set_qos_dscp (conn->fd1.fd, qos_dscp); + res = set_qos_dscp (conn->socket1, qos_dscp); return res; } @@ -2864,38 +2692,38 @@ gst_rtsp_connection_set_ip (GstRTSPConnection * conn, const gchar * ip) * * Get the file descriptor for reading. * - * Returns: the file descriptor used for reading or -1 on error. The file + * Returns: the file descriptor used for reading or %NULL on error. The file * descriptor remains valid until the connection is closed. * * Since: 0.10.23 */ -gint -gst_rtsp_connection_get_readfd (const GstRTSPConnection * conn) +GSocket * +gst_rtsp_connection_get_read_socket (const GstRTSPConnection * conn) { - g_return_val_if_fail (conn != NULL, -1); - g_return_val_if_fail (conn->readfd != NULL, -1); + g_return_val_if_fail (conn != NULL, NULL); + g_return_val_if_fail (conn->read_socket != NULL, NULL); - return conn->readfd->fd; + return conn->read_socket; } /** - * gst_rtsp_connection_get_writefd: + * gst_rtsp_connection_get_write_socket: * @conn: a #GstRTSPConnection * * Get the file descriptor for writing. * - * Returns: the file descriptor used for writing or -1 on error. The file + * Returns: the file descriptor used for writing or NULL on error. The file * descriptor remains valid until the connection is closed. * * Since: 0.10.23 */ -gint -gst_rtsp_connection_get_writefd (const GstRTSPConnection * conn) +GSocket * +gst_rtsp_connection_get_write_socket (const GstRTSPConnection * conn) { - g_return_val_if_fail (conn != NULL, -1); - g_return_val_if_fail (conn->writefd != NULL, -1); + g_return_val_if_fail (conn != NULL, NULL); + g_return_val_if_fail (conn->write_socket != NULL, NULL); - return conn->writefd->fd; + return conn->write_socket; } /** @@ -2931,8 +2759,8 @@ void gst_rtsp_connection_set_tunneled (GstRTSPConnection * conn, gboolean tunneled) { g_return_if_fail (conn != NULL); - g_return_if_fail (conn->readfd == NULL); - g_return_if_fail (conn->writefd == NULL); + g_return_if_fail (conn->read_socket == NULL); + g_return_if_fail (conn->write_socket == NULL); conn->tunneled = tunneled; } @@ -3007,18 +2835,21 @@ gst_rtsp_connection_do_tunnel (GstRTSPConnection * conn, g_return_val_if_fail (!memcmp (conn2->tunnelid, conn->tunnelid, TUNNELID_LEN), GST_RTSP_EINVAL); - /* both connections have fd0 as the read/write socket. start by taking the + /* both connections have socket0 as the read/write socket. start by taking the * socket from conn2 and set it as the socket in conn */ - conn->fd1 = conn2->fd0; + conn->socket1 = conn2->socket0; /* clean up some of the state of conn2 */ - gst_poll_remove_fd (conn2->fdset, &conn2->fd0); - conn2->fd0.fd = -1; - conn2->readfd = conn2->writefd = NULL; + g_cancellable_cancel (conn2->cancellable); + conn2->socket0 = 0; + g_object_unref (conn2->socket1); + conn2->socket1 = NULL; + conn2->write_socket = conn2->read_socket = NULL; + g_cancellable_reset (conn2->cancellable); - /* We make fd0 the write socket and fd1 the read socket. */ - conn->writefd = &conn->fd0; - conn->readfd = &conn->fd1; + /* We make socket0 the write socket and socket1 the read socket. */ + conn->write_socket = conn->socket0; + conn->read_socket = conn->socket1; conn->tstate = TUNNEL_STATE_COMPLETE; } @@ -3221,8 +3052,8 @@ gst_rtsp_source_dispatch (GSource * source, GSourceFunc callback G_GNUC_UNUSED, g_slice_free (GstRTSPRec, rec); } - res = write_bytes (watch->writefd.fd, watch->write_data, - &watch->write_off, watch->write_size); + res = write_bytes (watch->conn->write_socket, watch->write_data, + &watch->write_off, watch->write_size, watch->conn->cancellable); g_mutex_unlock (watch->mutex); if (res == GST_RTSP_EINTR) @@ -3362,8 +3193,8 @@ gst_rtsp_watch_new (GstRTSPConnection * conn, g_return_val_if_fail (conn != NULL, NULL); g_return_val_if_fail (funcs != NULL, NULL); - g_return_val_if_fail (conn->readfd != NULL, NULL); - g_return_val_if_fail (conn->writefd != NULL, NULL); + g_return_val_if_fail (conn->read_socket != NULL, NULL); + g_return_val_if_fail (conn->write_socket != NULL, NULL); result = (GstRTSPWatch *) g_source_new (&gst_rtsp_source_funcs, sizeof (GstRTSPWatch)); @@ -3403,11 +3234,11 @@ gst_rtsp_watch_reset (GstRTSPWatch * watch) if (watch->writefd.fd != -1) g_source_remove_poll ((GSource *) watch, &watch->writefd); - watch->readfd.fd = watch->conn->readfd->fd; + watch->readfd.fd = g_socket_get_fd (watch->conn->read_socket); watch->readfd.events = READ_COND; watch->readfd.revents = 0; - watch->writefd.fd = watch->conn->writefd->fd; + watch->writefd.fd = g_socket_get_fd (watch->conn->write_socket); watch->writefd.events = WRITE_ERR; watch->writefd.revents = 0; @@ -3490,7 +3321,9 @@ gst_rtsp_watch_write_data (GstRTSPWatch * watch, const guint8 * data, /* try to send the message synchronously first */ if (watch->messages->length == 0) { - res = write_bytes (watch->writefd.fd, data, &off, size); + res = + write_bytes (watch->conn->write_socket, data, &off, size, + watch->conn->cancellable); if (res != GST_RTSP_EINTR) { if (id != NULL) *id = 0; diff --git a/gst-libs/gst/rtsp/gstrtspconnection.h b/gst-libs/gst/rtsp/gstrtspconnection.h index 3279e4cf4..57acdbefa 100644 --- a/gst-libs/gst/rtsp/gstrtspconnection.h +++ b/gst-libs/gst/rtsp/gstrtspconnection.h @@ -49,6 +49,7 @@ #include <gst/rtsp/gstrtspdefs.h> #include <gst/rtsp/gstrtspurl.h> #include <gst/rtsp/gstrtspmessage.h> +#include <gio/gio.h> G_BEGIN_DECLS @@ -61,12 +62,12 @@ typedef struct _GstRTSPConnection GstRTSPConnection; /* opening/closing a connection */ GstRTSPResult gst_rtsp_connection_create (const GstRTSPUrl *url, GstRTSPConnection **conn); -GstRTSPResult gst_rtsp_connection_create_from_fd (gint fd, +GstRTSPResult gst_rtsp_connection_create_from_socket (GSocket * socket, const gchar * ip, guint16 port, const gchar * initial_buffer, GstRTSPConnection ** conn); -GstRTSPResult gst_rtsp_connection_accept (gint sock, GstRTSPConnection **conn); +GstRTSPResult gst_rtsp_connection_accept (GSocket *socket, GstRTSPConnection **conn, GCancellable *cancellable); GstRTSPResult gst_rtsp_connection_connect (GstRTSPConnection *conn, GTimeVal *timeout); GstRTSPResult gst_rtsp_connection_close (GstRTSPConnection *conn); GstRTSPResult gst_rtsp_connection_free (GstRTSPConnection *conn); @@ -117,8 +118,8 @@ GstRTSPUrl * gst_rtsp_connection_get_url (const GstRTSPConnection * const gchar * gst_rtsp_connection_get_ip (const GstRTSPConnection *conn); void gst_rtsp_connection_set_ip (GstRTSPConnection *conn, const gchar *ip); -gint gst_rtsp_connection_get_readfd (const GstRTSPConnection *conn); -gint gst_rtsp_connection_get_writefd (const GstRTSPConnection *conn); +GSocket * gst_rtsp_connection_get_read_socket (const GstRTSPConnection *conn); +GSocket * gst_rtsp_connection_get_write_socket (const GstRTSPConnection *conn); void gst_rtsp_connection_set_http_mode (GstRTSPConnection *conn, gboolean enable); diff --git a/gst-libs/gst/rtsp/gstrtspdefs.c b/gst-libs/gst/rtsp/gstrtspdefs.c index ee74b9830..e39059cfc 100644 --- a/gst-libs/gst/rtsp/gstrtspdefs.c +++ b/gst-libs/gst/rtsp/gstrtspdefs.c @@ -54,12 +54,6 @@ #include "gstrtspdefs.h" -#ifdef G_OS_WIN32 -#include <winsock2.h> -#else -#include <netdb.h> -#endif - struct rtsp_header { const gchar *name; @@ -261,25 +255,10 @@ gst_rtsp_strresult (GstRTSPResult result) switch (result) { case GST_RTSP_OK: return g_strdup ("OK"); -#ifdef G_OS_WIN32 - case GST_RTSP_ESYS: - case GST_RTSP_ENET: - { - gchar *res, *msg; - msg = g_win32_error_message (WSAGetLastError ()); - if (result == GST_RTSP_ESYS) - res = g_strdup_printf ("System error: %s", msg); - else - res = g_strdup_printf ("Network error: %s", msg); - g_free (msg); - return res; - } -#else case GST_RTSP_ESYS: - return g_strdup_printf ("System error: %s", g_strerror (errno)); + return g_strdup ("System error"); case GST_RTSP_ENET: - return g_strdup_printf ("Network error: %s", hstrerror (h_errno)); -#endif + return g_strdup ("Network error"); case GST_RTSP_ERROR: return g_strdup ("Generic error"); case GST_RTSP_EINVAL: |