Add IPv6 support to evrtsp

This commit is contained in:
Julien BLACHE 2010-05-13 17:13:30 +02:00
parent 74c4dd1ea3
commit ed38ce7dd1
2 changed files with 30 additions and 9 deletions

View File

@ -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;

View File

@ -56,6 +56,7 @@
#ifndef WIN32
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#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);