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);
char *hc_scheme;
char *hc_host;
int hc_port;
+ char *hc_bindaddr;
tvhpoll_t *hc_efd;
int hc_pevents;
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 );
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;
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;
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);
free(hc->hc_data);
free(hc->hc_host);
free(hc->hc_scheme);
+ free(hc->hc_bindaddr);
free(hc);
}
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;
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;
.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",
{
.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),
},
FREEM(presentation);
FREEM(tunercfg);
#undef FREEM
+ free(sd->sd_bindaddr);
tvh_hardware_delete((tvh_hardware_t*)sd);
free(sd);
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);
}
}
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 {
/* 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;
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
* *************************************************************************/
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;
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;
/*
* RTSP
*/
+ char *sd_bindaddr;
int sd_fullmux_ok;
int sd_pids_max;
int sd_pids_len;
*
*/
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;
*/
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;
#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,
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,
#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;