mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-07-16 11:28:36 +00:00
rtsp: Use getaddrinfo() to support both IPv4 and IPv6.
This commit is contained in:
parent
e1a4c8871a
commit
95a606a0bb
|
@ -76,14 +76,17 @@
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
/* 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 <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#define EINPROGRESS WSAEINPROGRESS
|
#define EINPROGRESS WSAEINPROGRESS
|
||||||
#else
|
#else
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -95,6 +98,14 @@
|
||||||
#include "gstrtspbase64.h"
|
#include "gstrtspbase64.h"
|
||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
|
|
||||||
|
union gst_sockaddr
|
||||||
|
{
|
||||||
|
struct sockaddr sa;
|
||||||
|
struct sockaddr_in sa_in;
|
||||||
|
struct sockaddr_in6 sa_in6;
|
||||||
|
struct sockaddr_storage sa_stor;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
gint state;
|
gint state;
|
||||||
|
@ -195,22 +206,6 @@ struct _GstRTSPConnection
|
||||||
guint proxy_port;
|
guint proxy_port;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
|
||||||
static int
|
|
||||||
inet_aton (const char *c, struct in_addr *paddr)
|
|
||||||
{
|
|
||||||
/* note that inet_addr is deprecated on unix because
|
|
||||||
* inet_addr returns -1 (INADDR_NONE) for the valid 255.255.255.255
|
|
||||||
* address. */
|
|
||||||
paddr->s_addr = inet_addr (c);
|
|
||||||
|
|
||||||
if (paddr->s_addr == INADDR_NONE)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
STATE_START = 0,
|
STATE_START = 0,
|
||||||
|
@ -336,25 +331,30 @@ GstRTSPResult
|
||||||
gst_rtsp_connection_accept (gint sock, GstRTSPConnection ** conn)
|
gst_rtsp_connection_accept (gint sock, GstRTSPConnection ** conn)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
unsigned int address_len;
|
|
||||||
GstRTSPConnection *newconn = NULL;
|
GstRTSPConnection *newconn = NULL;
|
||||||
struct sockaddr_in address;
|
union gst_sockaddr sa;
|
||||||
|
socklen_t slen = sizeof (sa);
|
||||||
|
gchar ip[INET6_ADDRSTRLEN];
|
||||||
GstRTSPUrl *url;
|
GstRTSPUrl *url;
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
gulong flags = 1;
|
gulong flags = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
address_len = sizeof (address);
|
memset (&sa, 0, slen);
|
||||||
memset (&address, 0, address_len);
|
|
||||||
|
|
||||||
#ifndef G_OS_WIN32
|
#ifndef G_OS_WIN32
|
||||||
fd = accept (sock, (struct sockaddr *) &address, &address_len);
|
fd = accept (sock, &sa.sa, &slen);
|
||||||
#else
|
#else
|
||||||
fd = accept (sock, (struct sockaddr *) &address, (gint *) & address_len);
|
fd = accept (sock, &sa.sa, (gint *) & slen);
|
||||||
#endif /* G_OS_WIN32 */
|
#endif /* G_OS_WIN32 */
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
goto accept_failed;
|
goto accept_failed;
|
||||||
|
|
||||||
|
if (getnameinfo (&sa.sa, slen, ip, sizeof (ip), NULL, 0, NI_NUMERICHOST) != 0)
|
||||||
|
goto getnameinfo_failed;
|
||||||
|
if (sa.sa.sa_family != AF_INET && sa.sa.sa_family != AF_INET6)
|
||||||
|
goto wrong_family;
|
||||||
|
|
||||||
/* set to non-blocking mode so that we can cancel the communication */
|
/* set to non-blocking mode so that we can cancel the communication */
|
||||||
#ifndef G_OS_WIN32
|
#ifndef G_OS_WIN32
|
||||||
fcntl (fd, F_SETFL, O_NONBLOCK);
|
fcntl (fd, F_SETFL, O_NONBLOCK);
|
||||||
|
@ -364,8 +364,11 @@ gst_rtsp_connection_accept (gint sock, GstRTSPConnection ** conn)
|
||||||
|
|
||||||
/* create a url for the client address */
|
/* create a url for the client address */
|
||||||
url = g_new0 (GstRTSPUrl, 1);
|
url = g_new0 (GstRTSPUrl, 1);
|
||||||
url->host = g_strdup_printf ("%s", inet_ntoa (address.sin_addr));
|
url->host = g_strdup (ip);
|
||||||
url->port = address.sin_port;
|
if (sa.sa.sa_family == AF_INET)
|
||||||
|
url->port = sa.sa_in.sin_port;
|
||||||
|
else
|
||||||
|
url->port = sa.sa_in6.sin6_port;
|
||||||
|
|
||||||
/* now create the connection object */
|
/* now create the connection object */
|
||||||
gst_rtsp_connection_create (url, &newconn);
|
gst_rtsp_connection_create (url, &newconn);
|
||||||
|
@ -386,54 +389,59 @@ accept_failed:
|
||||||
{
|
{
|
||||||
return GST_RTSP_ESYS;
|
return GST_RTSP_ESYS;
|
||||||
}
|
}
|
||||||
|
getnameinfo_failed:
|
||||||
|
wrong_family:
|
||||||
|
{
|
||||||
|
close (fd);
|
||||||
|
return GST_RTSP_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar *
|
static gchar *
|
||||||
do_resolve (const gchar * host)
|
do_resolve (const gchar * host)
|
||||||
{
|
{
|
||||||
struct hostent *hostinfo;
|
static gchar ip[INET6_ADDRSTRLEN];
|
||||||
struct in_addr addr;
|
struct addrinfo *aires;
|
||||||
const gchar *ip;
|
struct addrinfo *ai;
|
||||||
#ifdef G_OS_WIN32
|
gint aierr;
|
||||||
struct in_addr *addrp;
|
|
||||||
#else
|
|
||||||
char **addrs;
|
|
||||||
gchar ipbuf[INET_ADDRSTRLEN];
|
|
||||||
#endif /* G_OS_WIN32 */
|
|
||||||
|
|
||||||
ip = NULL;
|
aierr = getaddrinfo (host, NULL, NULL, &aires);
|
||||||
|
if (aierr != 0)
|
||||||
|
goto no_addrinfo;
|
||||||
|
|
||||||
/* first check if it already is an IP address */
|
for (ai = aires; ai; ai = ai->ai_next) {
|
||||||
if (inet_aton (host, &addr)) {
|
if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) {
|
||||||
ip = host;
|
break;
|
||||||
} else {
|
}
|
||||||
hostinfo = gethostbyname (host);
|
|
||||||
if (!hostinfo)
|
|
||||||
goto not_resolved; /* h_errno set */
|
|
||||||
|
|
||||||
if (hostinfo->h_addrtype != AF_INET)
|
|
||||||
goto not_ip; /* host not an IP host */
|
|
||||||
#ifdef G_OS_WIN32
|
|
||||||
addrp = (struct in_addr *) hostinfo->h_addr_list[0];
|
|
||||||
/* this is not threadsafe */
|
|
||||||
ip = inet_ntoa (*addrp);
|
|
||||||
#else
|
|
||||||
addrs = hostinfo->h_addr_list;
|
|
||||||
ip = inet_ntop (AF_INET, (struct in_addr *) addrs[0], ipbuf,
|
|
||||||
sizeof (ipbuf));
|
|
||||||
#endif /* G_OS_WIN32 */
|
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
|
||||||
|
freeaddrinfo (aires);
|
||||||
|
|
||||||
return g_strdup (ip);
|
return g_strdup (ip);
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
not_resolved:
|
no_addrinfo:
|
||||||
{
|
{
|
||||||
GST_ERROR ("could not resolve %s", host);
|
GST_ERROR ("no addrinfo found for %s: %s", host, gai_strerror (aierr));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
not_ip:
|
no_family:
|
||||||
{
|
{
|
||||||
GST_ERROR ("not an IP address");
|
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);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -443,7 +451,11 @@ do_connect (const gchar * ip, guint16 port, GstPollFD * fdout,
|
||||||
GstPoll * fdset, GTimeVal * timeout)
|
GstPoll * fdset, GTimeVal * timeout)
|
||||||
{
|
{
|
||||||
gint fd;
|
gint fd;
|
||||||
struct sockaddr_in sa_in;
|
struct addrinfo hints;
|
||||||
|
struct addrinfo *aires;
|
||||||
|
struct addrinfo *ai;
|
||||||
|
gint aierr;
|
||||||
|
gchar service[NI_MAXSERV];
|
||||||
gint ret;
|
gint ret;
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
unsigned long flags = 1;
|
unsigned long flags = 1;
|
||||||
|
@ -451,12 +463,26 @@ do_connect (const gchar * ip, guint16 port, GstPollFD * fdout,
|
||||||
GstClockTime to;
|
GstClockTime to;
|
||||||
gint retval;
|
gint retval;
|
||||||
|
|
||||||
memset (&sa_in, 0, sizeof (sa_in));
|
memset (&hints, 0, sizeof hints);
|
||||||
sa_in.sin_family = AF_INET; /* network socket */
|
hints.ai_flags = AI_NUMERICHOST;
|
||||||
sa_in.sin_port = htons (port); /* on port */
|
hints.ai_family = AF_UNSPEC;
|
||||||
sa_in.sin_addr.s_addr = inet_addr (ip); /* on host ip */
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
g_snprintf (service, sizeof (service) - 1, "%hu", port);
|
||||||
|
service[sizeof (service) - 1] = '\0';
|
||||||
|
|
||||||
fd = socket (AF_INET, SOCK_STREAM, 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)
|
if (fd == -1)
|
||||||
goto no_socket;
|
goto no_socket;
|
||||||
|
|
||||||
|
@ -471,7 +497,7 @@ do_connect (const gchar * ip, guint16 port, GstPollFD * fdout,
|
||||||
ADD_POLLFD (fdset, fdout, fd);
|
ADD_POLLFD (fdset, fdout, fd);
|
||||||
|
|
||||||
/* we are going to connect ASYNC now */
|
/* we are going to connect ASYNC now */
|
||||||
ret = connect (fd, (struct sockaddr *) &sa_in, sizeof (sa_in));
|
ret = connect (fd, ai->ai_addr, ai->ai_addrlen);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (!ERRNO_IS_EINPROGRESS)
|
if (!ERRNO_IS_EINPROGRESS)
|
||||||
|
@ -504,26 +530,42 @@ do_connect (const gchar * ip, guint16 port, GstPollFD * fdout,
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_poll_fd_ignored (fdset, fdout);
|
gst_poll_fd_ignored (fdset, fdout);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
freeaddrinfo (aires);
|
||||||
|
|
||||||
return GST_RTSP_OK;
|
return GST_RTSP_OK;
|
||||||
|
|
||||||
/* ERRORS */
|
/* 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:
|
no_socket:
|
||||||
{
|
{
|
||||||
GST_ERROR ("no socket %d (%s)", errno, g_strerror (errno));
|
GST_ERROR ("no socket %d (%s)", errno, g_strerror (errno));
|
||||||
|
freeaddrinfo (aires);
|
||||||
return GST_RTSP_ESYS;
|
return GST_RTSP_ESYS;
|
||||||
}
|
}
|
||||||
sys_error:
|
sys_error:
|
||||||
{
|
{
|
||||||
GST_ERROR ("system error %d (%s)", errno, g_strerror (errno));
|
GST_ERROR ("system error %d (%s)", errno, g_strerror (errno));
|
||||||
REMOVE_POLLFD (fdset, fdout);
|
REMOVE_POLLFD (fdset, fdout);
|
||||||
|
freeaddrinfo (aires);
|
||||||
return GST_RTSP_ESYS;
|
return GST_RTSP_ESYS;
|
||||||
}
|
}
|
||||||
timeout:
|
timeout:
|
||||||
{
|
{
|
||||||
GST_ERROR ("timeout");
|
GST_ERROR ("timeout");
|
||||||
REMOVE_POLLFD (fdset, fdout);
|
REMOVE_POLLFD (fdset, fdout);
|
||||||
|
freeaddrinfo (aires);
|
||||||
return GST_RTSP_ETIMEOUT;
|
return GST_RTSP_ETIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2329,12 +2371,7 @@ gst_rtsp_connection_clear_auth_params (GstRTSPConnection * conn)
|
||||||
static GstRTSPResult
|
static GstRTSPResult
|
||||||
set_qos_dscp (gint fd, guint qos_dscp)
|
set_qos_dscp (gint fd, guint qos_dscp)
|
||||||
{
|
{
|
||||||
union gst_sockaddr
|
union gst_sockaddr sa;
|
||||||
{
|
|
||||||
struct sockaddr sa;
|
|
||||||
struct sockaddr_in6 sa_in6;
|
|
||||||
struct sockaddr_storage sa_stor;
|
|
||||||
} sa;
|
|
||||||
socklen_t slen = sizeof (sa);
|
socklen_t slen = sizeof (sa);
|
||||||
gint af;
|
gint af;
|
||||||
gint tos;
|
gint tos;
|
||||||
|
|
Loading…
Reference in a new issue