From 4664fe40bca5706a5b6b18ddc2288b888825234d Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 2 Mar 2009 10:58:49 +0100 Subject: [PATCH] rtsp: add _get_url method and separate sockets Add gst_rtsp_connection_get_url() method. Reserve space for 2 sockets, one for reading and one for writing. Use socket pointers to select the read and write sockets. This should allow us to implement tunneling over HTTP soon. API: RTSP::gst_rtsp_connection_get_url() --- gst-libs/gst/rtsp/gstrtspconnection.c | 212 +++++++++++++++++++++------------- gst-libs/gst/rtsp/gstrtspconnection.h | 1 + 2 files changed, 131 insertions(+), 82 deletions(-) diff --git a/gst-libs/gst/rtsp/gstrtspconnection.c b/gst-libs/gst/rtsp/gstrtspconnection.c index d5b61ae..b181eaf 100644 --- a/gst-libs/gst/rtsp/gstrtspconnection.c +++ b/gst-libs/gst/rtsp/gstrtspconnection.c @@ -115,6 +115,22 @@ #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 + struct _GstRTSPConnection { /*< private > */ @@ -122,7 +138,12 @@ struct _GstRTSPConnection GstRTSPUrl *url; /* connection state */ - GstPollFD fd; + GstPollFD fd0; + GstPollFD fd1; + + GstPollFD *readfd; + GstPollFD *writefd; + GstPoll *fdset; gchar *ip; @@ -222,7 +243,8 @@ gst_rtsp_connection_create (GstRTSPUrl * url, GstRTSPConnection ** conn) goto no_fdset; newconn->url = url; - newconn->fd.fd = -1; + newconn->fd0.fd = -1; + newconn->fd1.fd = -1; newconn->timer = g_timer_new (); newconn->timeout = 60; @@ -309,8 +331,10 @@ gst_rtsp_connection_accept (gint sock, GstRTSPConnection ** conn) /* now create the connection object */ gst_rtsp_connection_create (url, &newconn); - newconn->fd.fd = fd; - gst_poll_add_fd (newconn->fdset, &newconn->fd); + ADD_POLLFD (newconn->fdset, newconn->fd0, fd); + + newconn->readfd = &newconn->fd0; + newconn->writefd = &newconn->fd0; *conn = newconn; @@ -361,7 +385,7 @@ 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->fd.fd < 0, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->fd0.fd < 0, GST_RTSP_EINVAL); url = conn->url; @@ -406,8 +430,10 @@ gst_rtsp_connection_connect (GstRTSPConnection * conn, GTimeVal * timeout) #endif /* G_OS_WIN32 */ /* add the socket to our fdset */ - conn->fd.fd = fd; - gst_poll_add_fd (conn->fdset, &conn->fd); + ADD_POLLFD (conn->fdset, conn->fd0, fd); + + conn->readfd = &conn->fd0; + conn->writefd = &conn->fd0; /* we are going to connect ASYNC now */ ret = connect (fd, (struct sockaddr *) &sa_in, sizeof (sa_in)); @@ -418,7 +444,7 @@ gst_rtsp_connection_connect (GstRTSPConnection * conn, GTimeVal * timeout) /* wait for connect to complete up to the specified timeout or until we got * interrupted. */ - gst_poll_fd_ctl_write (conn->fdset, &conn->fd, TRUE); + gst_poll_fd_ctl_write (conn->fdset, conn->writefd, TRUE); to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE; @@ -432,17 +458,18 @@ gst_rtsp_connection_connect (GstRTSPConnection * conn, GTimeVal * timeout) goto sys_error; /* we can still have an error connecting on windows */ - if (gst_poll_fd_has_error (conn->fdset, &conn->fd)) { + if (gst_poll_fd_has_error (conn->fdset, conn->writefd)) { socklen_t len = sizeof (errno); #ifndef G_OS_WIN32 - getsockopt (conn->fd.fd, SOL_SOCKET, SO_ERROR, &errno, &len); + getsockopt (fd, SOL_SOCKET, SO_ERROR, &errno, &len); #else - getsockopt (conn->fd.fd, SOL_SOCKET, SO_ERROR, (char *) &errno, &len); + getsockopt (fd, SOL_SOCKET, SO_ERROR, (char *) &errno, &len); #endif goto sys_error; } - gst_poll_fd_ignored (conn->fdset, &conn->fd); + gst_poll_fd_ignored (conn->fdset, conn->writefd); + gst_poll_fd_ignored (conn->fdset, conn->readfd); done: conn->ip = g_strdup (ip); @@ -452,13 +479,8 @@ done: sys_error: { GST_ERROR ("system error %d (%s)", errno, g_strerror (errno)); - if (conn->fd.fd >= 0) { - GST_DEBUG ("remove fd %d", conn->fd.fd); - gst_poll_remove_fd (conn->fdset, &conn->fd); - conn->fd.fd = -1; - } - if (fd >= 0) - CLOSE_SOCKET (fd); + REMOVE_POLLFD (conn->fdset, conn->fd0); + REMOVE_POLLFD (conn->fdset, conn->fd1); return GST_RTSP_ESYS; } not_resolved: @@ -474,13 +496,8 @@ not_ip: timeout: { GST_ERROR ("timeout"); - if (conn->fd.fd >= 0) { - GST_DEBUG ("remove fd %d", conn->fd.fd); - gst_poll_remove_fd (conn->fdset, &conn->fd); - conn->fd.fd = -1; - } - if (fd >= 0) - CLOSE_SOCKET (fd); + REMOVE_POLLFD (conn->fdset, conn->fd0); + REMOVE_POLLFD (conn->fdset, conn->fd1); return GST_RTSP_ETIMEOUT; } } @@ -750,13 +767,14 @@ gst_rtsp_connection_write (GstRTSPConnection * conn, const guint8 * data, 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->fd.fd >= 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->fd, TRUE); - gst_poll_fd_ctl_read (conn->fdset, &conn->fd, FALSE); + 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->fd); + gst_poll_fd_ignored (conn->fdset, conn->writefd); + gst_poll_fd_ignored (conn->fdset, conn->readfd); to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE; @@ -764,7 +782,7 @@ gst_rtsp_connection_write (GstRTSPConnection * conn, const guint8 * data, while (TRUE) { /* try to write */ - res = write_bytes (conn->fd.fd, data, &offset, size); + res = write_bytes (conn->writefd->fd, data, &offset, size); if (res == GST_RTSP_OK) break; if (res != GST_RTSP_EINTR) @@ -1087,7 +1105,7 @@ build_next (GstRTSPBuilder * builder, GstRTSPMessage * message, case STATE_START: builder->offset = 0; res = - read_bytes (conn->fd.fd, (guint8 *) builder->buffer, + read_bytes (conn->readfd->fd, (guint8 *) builder->buffer, &builder->offset, 1); if (res != GST_RTSP_OK) goto done; @@ -1105,7 +1123,7 @@ build_next (GstRTSPBuilder * builder, GstRTSPMessage * message, case STATE_DATA_HEADER: { res = - read_bytes (conn->fd.fd, (guint8 *) builder->buffer, + read_bytes (conn->readfd->fd, (guint8 *) builder->buffer, &builder->offset, 4); if (res != GST_RTSP_OK) goto done; @@ -1121,7 +1139,8 @@ build_next (GstRTSPBuilder * builder, GstRTSPMessage * message, } case STATE_DATA_BODY: { - res = read_bytes (conn->fd.fd, builder->body_data, &builder->offset, + res = + read_bytes (conn->readfd->fd, builder->body_data, &builder->offset, builder->body_len); if (res != GST_RTSP_OK) goto done; @@ -1138,7 +1157,7 @@ build_next (GstRTSPBuilder * builder, GstRTSPMessage * message, } case STATE_READ_LINES: { - res = read_line (conn->fd.fd, builder->buffer, &builder->offset, + res = read_line (conn->readfd->fd, builder->buffer, &builder->offset, sizeof (builder->buffer)); if (res != GST_RTSP_OK) goto done; @@ -1261,7 +1280,7 @@ gst_rtsp_connection_read (GstRTSPConnection * conn, guint8 * data, guint size, 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->fd.fd >= 0, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->readfd != NULL, GST_RTSP_EINVAL); if (size == 0) return GST_RTSP_OK; @@ -1272,11 +1291,11 @@ gst_rtsp_connection_read (GstRTSPConnection * conn, guint8 * data, guint size, 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->fd, FALSE); - gst_poll_fd_ctl_read (conn->fdset, &conn->fd, 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->fd.fd, data, &offset, size); + res = read_bytes (conn->readfd->fd, data, &offset, size); if (res == GST_RTSP_EEOF) goto eof; if (res == GST_RTSP_OK) @@ -1351,13 +1370,14 @@ gst_rtsp_connection_receive (GstRTSPConnection * conn, GstRTSPMessage * message, 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); /* 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->fd, FALSE); - gst_poll_fd_ctl_read (conn->fdset, &conn->fd, TRUE); + gst_poll_fd_ctl_write (conn->fdset, conn->writefd, FALSE); + gst_poll_fd_ctl_read (conn->fdset, conn->readfd, TRUE); while (TRUE) { res = build_next (&builder, message, conn); @@ -1431,27 +1451,17 @@ cleanup: GstRTSPResult gst_rtsp_connection_close (GstRTSPConnection * conn) { - gint res; - g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); g_free (conn->ip); conn->ip = NULL; - if (conn->fd.fd != -1) { - gst_poll_remove_fd (conn->fdset, &conn->fd); - res = CLOSE_SOCKET (conn->fd.fd); - conn->fd.fd = -1; - if (res != 0) - goto sys_error; - } + REMOVE_POLLFD (conn->fdset, conn->fd0); + REMOVE_POLLFD (conn->fdset, conn->fd1); + conn->writefd = NULL; + conn->readfd = NULL; return GST_RTSP_OK; - -sys_error: - { - return GST_RTSP_ESYS; - } } /** @@ -1513,15 +1523,17 @@ gst_rtsp_connection_poll (GstRTSPConnection * conn, GstRTSPEvent events, 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->fd.fd >= 0, 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); gst_poll_set_controllable (conn->fdset, TRUE); /* add fd to writer set when asked to */ - gst_poll_fd_ctl_write (conn->fdset, &conn->fd, events & GST_RTSP_EV_WRITE); + 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->fd, events & GST_RTSP_EV_READ); + gst_poll_fd_ctl_read (conn->fdset, conn->readfd, events & GST_RTSP_EV_READ); /* configure timeout if any */ to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE; @@ -1542,11 +1554,11 @@ gst_rtsp_connection_poll (GstRTSPConnection * conn, GstRTSPEvent events, *revents = 0; if (events & GST_RTSP_EV_READ) { - if (gst_poll_fd_can_read (conn->fdset, &conn->fd)) + if (gst_poll_fd_can_read (conn->fdset, conn->readfd)) *revents |= GST_RTSP_EV_READ; } if (events & GST_RTSP_EV_WRITE) { - if (gst_poll_fd_can_write (conn->fdset, &conn->fd)) + if (gst_poll_fd_can_write (conn->fdset, conn->writefd)) *revents |= GST_RTSP_EV_WRITE; } return GST_RTSP_OK; @@ -1764,19 +1776,8 @@ gst_rtsp_connection_clear_auth_params (GstRTSPConnection * conn) } } -/** - * gst_rtsp_connection_set_qos_dscp: - * @conn: a #GstRTSPConnection - * @qos_dscp: DSCP value - * - * Configure @conn to use the specified DSCP value. - * - * Returns: #GST_RTSP_OK on success. - * - * Since: 0.10.20 - */ -GstRTSPResult -gst_rtsp_connection_set_qos_dscp (GstRTSPConnection * conn, guint qos_dscp) +static GstRTSPResult +set_qos_dscp (gint fd, guint qos_dscp) { union gst_sockaddr { @@ -1788,17 +1789,16 @@ gst_rtsp_connection_set_qos_dscp (GstRTSPConnection * conn, guint qos_dscp) gint af; gint tos; - g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); - g_return_val_if_fail (conn->fd.fd >= 0, GST_RTSP_EINVAL); + if (fd == -1) + return GST_RTSP_OK; - if (getsockname (conn->fd.fd, &sa.sa, &slen) < 0) + if (getsockname (fd, &sa.sa, &slen) < 0) goto no_getsockname; af = sa.sa.sa_family; /* if this is an IPv4-mapped address then do IPv4 QoS */ if (af == AF_INET6) { - if (IN6_IS_ADDR_V4MAPPED (&sa.sa_in6.sin6_addr)) af = AF_INET; } @@ -1808,13 +1808,12 @@ gst_rtsp_connection_set_qos_dscp (GstRTSPConnection * conn, guint qos_dscp) switch (af) { case AF_INET: - if (SETSOCKOPT (conn->fd.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 (conn->fd.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 @@ -1838,6 +1837,53 @@ wrong_family: } /** + * gst_rtsp_connection_set_qos_dscp: + * @conn: a #GstRTSPConnection + * @qos_dscp: DSCP value + * + * Configure @conn to use the specified DSCP value. + * + * Returns: #GST_RTSP_OK on success. + * + * Since: 0.10.20 + */ +GstRTSPResult +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); + + res = set_qos_dscp (conn->fd0.fd, qos_dscp); + if (res == GST_RTSP_OK) + res = set_qos_dscp (conn->fd1.fd, qos_dscp); + + return res; +} + + +/** + * gst_rtsp_connection_get_url: + * @conn: a #GstRTSPConnection + * + * Retrieve the URL of the other end of @conn. + * + * Returns: The URL. This value remains valid until the + * connection is closed. + * + * Since: 0.10.23 + */ +GstRTSPUrl * +gst_rtsp_connection_get_url (const GstRTSPConnection * conn) +{ + g_return_val_if_fail (conn != NULL, NULL); + + return conn->url; +} + +/** * gst_rtsp_connection_get_ip: * @conn: a #GstRTSPConnection * @@ -2056,6 +2102,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); result = (GstRTSPWatch *) g_source_new (&gst_rtsp_source_funcs, sizeof (GstRTSPWatch)); @@ -2063,11 +2111,11 @@ gst_rtsp_watch_new (GstRTSPConnection * conn, result->conn = conn; result->builder.state = STATE_START; - result->readfd.fd = conn->fd.fd; + result->readfd.fd = conn->readfd->fd; result->readfd.events = READ_COND; result->readfd.revents = 0; - result->writefd.fd = conn->fd.fd; + result->writefd.fd = conn->writefd->fd; result->writefd.events = WRITE_COND; result->writefd.revents = 0; result->write_added = FALSE; diff --git a/gst-libs/gst/rtsp/gstrtspconnection.h b/gst-libs/gst/rtsp/gstrtspconnection.h index 56a6432..92e4df2 100644 --- a/gst-libs/gst/rtsp/gstrtspconnection.h +++ b/gst-libs/gst/rtsp/gstrtspconnection.h @@ -102,6 +102,7 @@ GstRTSPResult gst_rtsp_connection_set_qos_dscp (GstRTSPConnection *conn, guint qos_dscp); /* accessors */ +GstRTSPUrl * gst_rtsp_connection_get_url (const GstRTSPConnection *conn); const gchar * gst_rtsp_connection_get_ip (const GstRTSPConnection *conn); /* async IO */ -- 2.7.4