tcp: add helpers to determine default and used IP address for SAT>IP

This commit is contained in:
Jaroslav Kysela 2015-02-12 18:50:40 +01:00
parent 434fc5de6a
commit c19217e6e3
2 changed files with 99 additions and 0 deletions

View file

@ -381,6 +381,7 @@ static uint32_t tcp_server_launch_id;
typedef struct tcp_server {
int serverfd;
struct sockaddr_storage bound;
tcp_server_ops_t ops;
void *opaque;
} tcp_server_t;
@ -641,6 +642,7 @@ tcp_server_create
int fd, x;
tcp_server_t *ts;
struct addrinfo hints, *res, *ressave, *use = NULL;
struct sockaddr_storage bound;
char port_buf[6];
int one = 1;
int zero = 0;
@ -683,6 +685,10 @@ tcp_server_create
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(int));
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
assert(use->ai_addrlen <= sizeof(bound));
memset(&bound, 0, sizeof(bound));
memcpy(&bound, use->ai_addr, use->ai_addrlen);
x = bind(fd, use->ai_addr, use->ai_addrlen);
freeaddrinfo(ressave);
@ -698,6 +704,7 @@ tcp_server_create
ts = malloc(sizeof(tcp_server_t));
ts->serverfd = fd;
ts->bound = bound;
ts->ops = *ops;
ts->opaque = opaque;
return ts;
@ -744,6 +751,94 @@ tcp_server_delete(void *server)
free(ts);
}
/**
*
*/
int
tcp_default_ip_addr ( struct sockaddr_storage *deflt )
{
struct sockaddr_storage ss;
socklen_t ss_len;
int sock;
memset(&ss, 0, sizeof(ss));
ss.ss_family = tcp_preferred_address_family;
if (inet_pton(ss.ss_family,
ss.ss_family == AF_INET ?
/* Google name servers */
"8.8.8.8" : "2001:4860:4860::8888",
IP_IN_ADDR(ss)) <= 0)
return -1;
if (ss.ss_family == AF_INET)
IP_AS_V4(ss, port) = htons(53);
else
IP_AS_V6(ss, port) = htons(53);
sock = tvh_socket(ss.ss_family, SOCK_STREAM, 0);
if (sock < 0)
return -1;
if (connect(sock, (struct sockaddr *)&ss, IP_IN_ADDRLEN(ss)) < 0) {
close(sock);
return -1;
}
ss_len = sizeof(ss);
if (getsockname(sock, (struct sockaddr *)&ss, &ss_len) < 0) {
close(sock);
return -1;
}
if (ss.ss_family == AF_INET)
IP_AS_V4(ss, port) = 0;
else
IP_AS_V6(ss, port) = 0;
memset(deflt, 0, sizeof(*deflt));
memcpy(deflt, &ss, ss_len);
close(sock);
return 0;
}
/**
*
*/
int
tcp_server_bound ( void *server, struct sockaddr_storage *bound )
{
tcp_server_t *ts = server;
int i, len, port;
uint8_t *ptr;
if (server == NULL) {
memset(bound, 0, sizeof(*bound));
return 0;
}
len = IP_IN_ADDRLEN(*bound);
ptr = (uint8_t *)IP_IN_ADDR(*bound);
for (i = 0; i < len; i++)
if (ptr[0])
break;
if (i < len) {
*bound = ts->bound;
return 0;
}
port = IP_PORT(ts->bound);
/* no bind address was set, try to find one */
if (tcp_default_ip_addr(bound) < 0)
return -1;
if (bound->ss_family == AF_INET)
IP_AS_V4(*bound, port) = port;
else
IP_AS_V6(*bound, port) = port;
return 0;
}
/*
* Connections status
*/

View file

@ -66,6 +66,10 @@ void tcp_server_register(void *server);
void tcp_server_delete(void *server);
int tcp_default_ip_addr(struct sockaddr_storage *deflt);
int tcp_server_bound(void *server, struct sockaddr_storage *bound);
int tcp_read(int fd, void *buf, size_t len);
char *tcp_read_line(int fd, htsbuf_queue_t *spill);