SAT>IP: allow to specify the local bind IP address

This commit is contained in:
Jaroslav Kysela 2014-05-22 15:00:52 +02:00
parent 02642ce851
commit de306a0827
11 changed files with 68 additions and 32 deletions

View file

@ -1169,7 +1169,7 @@ cwc_thread(void *aux)
pthread_mutex_unlock(&cwc_mutex);
fd = tcp_connect(hostname, port, errbuf, sizeof(errbuf), 10);
fd = tcp_connect(hostname, port, NULL, errbuf, sizeof(errbuf), 10);
pthread_mutex_lock(&cwc_mutex);

View file

@ -222,6 +222,7 @@ struct http_client {
char *hc_scheme;
char *hc_host;
int hc_port;
char *hc_bindaddr;
tvhpoll_t *hc_efd;
int hc_pevents;
@ -289,8 +290,8 @@ void http_client_init ( void );
void http_client_done ( void );
http_client_t*
http_client_connect ( void *aux, http_ver_t ver,
const char *scheme, const char *host, int port );
http_client_connect ( void *aux, http_ver_t ver, const char *scheme,
const char *host, int port, const char *bindaddr );
void http_client_register ( http_client_t *hc );
void http_client_close ( http_client_t *hc );

View file

@ -1164,7 +1164,7 @@ http_client_reconnect
hc->hc_port = port;
if (port < 0)
return -EINVAL;
hc->hc_fd = tcp_connect(host, port, errbuf, sizeof(errbuf), -1);
hc->hc_fd = tcp_connect(host, port, hc->hc_bindaddr, errbuf, sizeof(errbuf), -1);
if (hc->hc_fd < 0) {
tvhlog(LOG_ERR, "httpc", "Unable to connect to %s:%i - %s", host, port, errbuf);
return -EINVAL;
@ -1217,7 +1217,8 @@ err1:
http_client_t *
http_client_connect
( void *aux, http_ver_t ver, const char *scheme, const char *host, int port )
( void *aux, http_ver_t ver, const char *scheme,
const char *host, int port, const char *bindaddr )
{
http_client_t *hc;
@ -1226,6 +1227,7 @@ http_client_connect
hc->hc_io_size = 1024;
hc->hc_rtsp_stream_id = -1;
hc->hc_verify_peer = -1;
hc->hc_bindaddr = bindaddr ? strdup(bindaddr) : NULL;
TAILQ_INIT(&hc->hc_args);
TAILQ_INIT(&hc->hc_wqueue);
@ -1280,6 +1282,7 @@ http_client_close ( http_client_t *hc )
free(hc->hc_data);
free(hc->hc_host);
free(hc->hc_scheme);
free(hc->hc_bindaddr);
free(hc);
}

View file

@ -166,7 +166,7 @@ imagecache_image_fetch ( imagecache_image_t *img )
pthread_mutex_unlock(&global_lock);
hc = http_client_connect(NULL, HTTP_VERSION_1_1, url.scheme,
url.host, url.port);
url.host, url.port, NULL);
if (hc == NULL)
goto error;

View file

@ -68,7 +68,7 @@ iptv_http_start
int r;
if (!(hc = http_client_connect(im, HTTP_VERSION_1_1, u->scheme,
u->host, u->port)))
u->host, u->port, NULL)))
return SM_CODE_TUNING_FAILED;
hc->hc_hdr_received = iptv_http_header;
hc->hc_data_received = iptv_http_data;

View file

@ -112,6 +112,13 @@ const idclass_t satip_device_class =
.opts = PO_ADVANCED,
.off = offsetof(satip_device_t, sd_pids0),
},
{
.type = PT_STR,
.id = "bindaddr",
.name = "Local bind IP address",
.opts = PO_ADVANCED,
.off = offsetof(satip_device_t, sd_bindaddr),
},
{
.type = PT_STR,
.id = "addr",
@ -227,7 +234,7 @@ const idclass_t satip_device_class =
{
.type = PT_STR,
.id = "myaddr",
.name = "Local IP Address",
.name = "Local Discovery IP Address",
.opts = PO_RDONLY | PO_NOSAVE,
.off = offsetof(satip_device_t, sd_info.myaddr),
},
@ -455,6 +462,7 @@ satip_device_destroy( satip_device_t *sd )
FREEM(presentation);
FREEM(tunercfg);
#undef FREEM
free(sd->sd_bindaddr);
tvh_hardware_delete((tvh_hardware_t*)sd);
free(sd);
@ -573,10 +581,7 @@ satip_discovery_http_closed(http_client_t *hc, int errn)
socklen_t addrlen = sizeof(ip);
errbuf[0] = '\0';
getsockname(hc->hc_fd, (struct sockaddr *)&ip, &addrlen);
if (ip.ss_family == AF_INET6)
inet_ntop(AF_INET6, &IP_AS_V6(ip, addr), errbuf, sizeof(errbuf));
else
inet_ntop(AF_INET, &IP_AS_V4(ip, addr), errbuf, sizeof(errbuf));
inet_ntop(ip.ss_family, IP_IN_ADDR(ip), errbuf, sizeof(errbuf));
free(d->myaddr);
d->myaddr = strdup(errbuf);
}
@ -703,7 +708,7 @@ satip_discovery_timerq_cb(void *aux)
}
d->http_client = http_client_connect(d, HTTP_VERSION_1_1, d->url.scheme,
d->url.host, d->url.port);
d->url.host, d->url.port, NULL);
if (d->http_client == NULL)
satip_discovery_destroy(d, 1);
else {
@ -803,7 +808,7 @@ satip_discovery_service_received
/* Forward information to next layer */
d = calloc(1, sizeof(satip_discovery_t));
if (inet_ntop(storage->ss_family, IP_IN_ADDR(conn->ip),
if (inet_ntop(conn->ip.ss_family, IP_IN_ADDR(conn->ip),
sockbuf, sizeof(sockbuf)) == NULL) {
satip_discovery_destroy(d, 0);
return;

View file

@ -42,6 +42,15 @@ satip_frontend_find_by_number( satip_device_t *sd, int num )
return NULL;
}
static char *
satip_frontend_bindaddr( satip_frontend_t *lfe )
{
char *bindaddr = lfe->sf_device->sd_bindaddr;
if (bindaddr == NULL || bindaddr[0] == '\0')
bindaddr = lfe->sf_device->sd_bindaddr;
return bindaddr;
}
/* **************************************************************************
* Class definition
* *************************************************************************/
@ -962,7 +971,8 @@ satip_frontend_input_thread ( void *aux )
pthread_mutex_unlock(&lfe->sf_device->sd_tune_mutex);
rtsp = http_client_connect(lfe, RTSP_VERSION_1_0, "rstp",
lfe->sf_device->sd_info.addr, 554);
lfe->sf_device->sd_info.addr, 554,
satip_frontend_bindaddr(lfe));
if (rtsp == NULL)
return NULL;
@ -1245,7 +1255,7 @@ satip_frontend_tune0
if (udp_bind_double(&lfe->sf_rtp, &lfe->sf_rtcp,
"satip", "rtp", "rtpc",
lfe->sf_device->sd_info.myaddr, lfe->sf_udp_rtp_port,
satip_frontend_bindaddr(lfe), lfe->sf_udp_rtp_port,
NULL, SATIP_BUF_SIZE, 16384) < 0)
return SM_CODE_TUNING_FAILED;

View file

@ -73,6 +73,7 @@ struct satip_device
/*
* RTSP
*/
char *sd_bindaddr;
int sd_fullmux_ok;
int sd_pids_max;
int sd_pids_len;

View file

@ -48,8 +48,8 @@ th_pipe_t tcp_server_pipe;
*
*/
int
tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize,
int timeout)
tcp_connect(const char *hostname, int port, const char *bindaddr,
char *errbuf, size_t errbufsize, int timeout)
{
int fd, r, res, err;
struct addrinfo *ai;
@ -78,7 +78,19 @@ tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize,
*/
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
if ((ai->ai_family != AF_INET) && (ai->ai_family != AF_INET6)) {
if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) {
if (bindaddr && bindaddr[0] != '\0') {
struct sockaddr_storage ip;
memset(&ip, 0, sizeof(ip));
ip.ss_family = ai->ai_family;
if (inet_pton(AF_INET, bindaddr, IP_IN_ADDR(ip)) <= 0 ||
bind(fd, (struct sockaddr *)&ip, IP_IN_ADDRLEN(ip)) < 0) {
snprintf(errbuf, errbufsize, "Cannot bind to IPv%s addr '%s'", bindaddr,
ai->ai_family == AF_INET6 ? "6" : "4");
return -1;
}
}
} else {
snprintf(errbuf, errbufsize, "Invalid protocol family");
freeaddrinfo(ai);
return -1;

View file

@ -22,6 +22,21 @@
#include "htsbuf.h"
#include "htsmsg.h"
#define IP_AS_V4(storage, f) ((struct sockaddr_in *)&(storage))->sin_##f
#define IP_AS_V6(storage, f) ((struct sockaddr_in6 *)&(storage))->sin6_##f
#define IP_IN_ADDR(storage) \
((storage).ss_family == AF_INET6 ? \
&((struct sockaddr_in6 *)&(storage))->sin6_addr : \
(void *)&((struct sockaddr_in *)&(storage))->sin_addr)
#define IP_IN_ADDRLEN(storage) \
((storage).ss_family == AF_INET6 ? \
sizeof(struct sockaddr_in6) : \
sizeof(struct sockaddr_in))
#define IP_PORT(storage) \
((storage).ss_family == AF_INET6 ? \
((struct sockaddr_in6 *)&(storage))->sin6_port : \
((struct sockaddr_in *)&(storage))->sin_port)
typedef struct tcp_server_ops
{
void (*start) (int fd, void **opaque,
@ -37,8 +52,8 @@ extern int tcp_preferred_address_family;
void tcp_server_init(int opt_ipv6);
void tcp_server_done(void);
int tcp_connect(const char *hostname, int port, char *errbuf,
size_t errbufsize, int timeout);
int tcp_connect(const char *hostname, int port, const char *bindaddr,
char *errbuf, size_t errbufsize, int timeout);
typedef void (tcp_server_callback_t)(int fd, void *opaque,
struct sockaddr_storage *peer,

View file

@ -25,17 +25,6 @@
#define UDP_FATAL_ERROR ((void *)-1)
#define IP_AS_V4(storage, f) ((struct sockaddr_in *)&(storage))->sin_##f
#define IP_AS_V6(storage, f) ((struct sockaddr_in6 *)&(storage))->sin6_##f
#define IP_IN_ADDR(storage) \
((storage).ss_family == AF_INET6 ? \
&((struct sockaddr_in6 *)&(storage))->sin6_addr : \
(void *)&((struct sockaddr_in *)&(storage))->sin_addr)
#define IP_PORT(storage) \
((storage).ss_family == AF_INET6 ? \
((struct sockaddr_in6 *)&(storage))->sin6_port : \
((struct sockaddr_in *)&(storage))->sin_port)
typedef struct udp_connection {
char *host;
int port;