From ed38ce7dd106c02e54101c4e652d679212508497 Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Thu, 13 May 2010 17:13:30 +0200 Subject: [PATCH] Add IPv6 support to evrtsp --- src/evrtsp/rtsp-internal.h | 1 + src/evrtsp/rtsp.c | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/evrtsp/rtsp-internal.h b/src/evrtsp/rtsp-internal.h index 1ed61ed8..17ef8781 100644 --- a/src/evrtsp/rtsp-internal.h +++ b/src/evrtsp/rtsp-internal.h @@ -63,6 +63,7 @@ struct evrtsp_connection { u_short bind_port; /* local port for binding the src */ char *address; /* address to connect to */ + int family; u_short port; int flags; diff --git a/src/evrtsp/rtsp.c b/src/evrtsp/rtsp.c index ec99d4a6..52925d61 100644 --- a/src/evrtsp/rtsp.c +++ b/src/evrtsp/rtsp.c @@ -56,6 +56,7 @@ #ifndef WIN32 #include #include +#include #endif #ifdef WIN32 @@ -201,8 +202,8 @@ fake_freeaddrinfo(struct addrinfo *ai) extern int debug; static int socket_connect(int fd, const char *address, unsigned short port); -static int bind_socket_ai(struct addrinfo *, int reuse); -static int bind_socket(const char *, u_short, int reuse); +static int bind_socket_ai(int family, struct addrinfo *, int reuse); +static int bind_socket(int family, const char *, u_short, int reuse); static void name_from_addr(struct sockaddr *, socklen_t, char **, char **); static void evrtsp_connection_start_detectclose( struct evrtsp_connection *evcon); @@ -1236,7 +1237,18 @@ struct evrtsp_connection * evrtsp_connection_new(const char *address, unsigned short port) { struct evrtsp_connection *evcon = NULL; + unsigned char scratch[16]; + int family; + if (inet_pton(AF_INET6, address, scratch) == 1) + family = AF_INET6; + else if (inet_pton(AF_INET, address, scratch) == 1) + family = AF_INET; + else { + event_warn("%s: address is neither IPv6 nor IPv4", __func__); + return NULL; + } + event_debug(("Attempting connection to %s:%d\n", address, port)); if ((evcon = calloc(1, sizeof(struct evrtsp_connection))) == NULL) { @@ -1251,6 +1263,8 @@ evrtsp_connection_new(const char *address, unsigned short port) evcon->cseq = 1; + evcon->family = family; + if ((evcon->address = strdup(address)) == NULL) { event_warn("%s: strdup failed", __func__); goto error; @@ -1366,7 +1380,7 @@ evrtsp_connection_connect(struct evrtsp_connection *evcon) evrtsp_connection_reset(evcon); - evcon->fd = bind_socket( + evcon->fd = bind_socket(evcon->family, evcon->bind_address, evcon->bind_port, 0 /*reuse*/); if (evcon->fd == -1) { event_debug(("%s: failed to bind to \"%s\"", @@ -1637,13 +1651,16 @@ name_from_addr(struct sockaddr *sa, socklen_t salen, /* Create a non-blocking socket and bind it */ /* todo: rename this function */ static int -bind_socket_ai(struct addrinfo *ai, int reuse) +bind_socket_ai(int family, struct addrinfo *ai, int reuse) { int fd, on = 1, r; int serrno; + if (ai) + family = ai->ai_family; + /* Create listen socket */ - fd = socket(AF_INET, SOCK_STREAM, 0); + fd = socket(family, SOCK_STREAM, 0); if (fd == -1) { event_warn("socket"); return (-1); @@ -1659,6 +1676,9 @@ bind_socket_ai(struct addrinfo *ai, int reuse) } #endif + if (family == AF_INET6) + setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); + setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)); if (reuse) { setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, @@ -1691,7 +1711,7 @@ make_addrinfo(const char *address, u_short port) int ai_result; memset(&ai, 0, sizeof(ai)); - ai.ai_family = AF_INET; + ai.ai_family = AF_UNSPEC; ai.ai_socktype = SOCK_STREAM; ai.ai_flags = AI_PASSIVE; /* turn NULL host name into INADDR_ANY */ evutil_snprintf(strport, sizeof(strport), "%d", port); @@ -1719,21 +1739,21 @@ make_addrinfo(const char *address, u_short port) } static int -bind_socket(const char *address, u_short port, int reuse) +bind_socket(int family, const char *address, u_short port, int reuse) { int fd; struct addrinfo *aitop = NULL; /* just create an unbound socket */ if (address == NULL && port == 0) - return bind_socket_ai(NULL, 0); + return bind_socket_ai(family, NULL, 0); aitop = make_addrinfo(address, port); if (aitop == NULL) return (-1); - fd = bind_socket_ai(aitop, reuse); + fd = bind_socket_ai(family, aitop, reuse); #ifdef _EVENT_HAVE_GETADDRINFO freeaddrinfo(aitop);