Bug #4692 » SAT-IP-Print-external-NAT-ip-and-port-v2.diff
src/satip/rtsp.c | ||
---|---|---|
92 | 92 |
static void rtsp_close_session(session_t *rs); |
93 | 93 |
static void rtsp_free_session(session_t *rs); |
94 | 94 | |
95 |
static char any_ip[] = "127.0.0.1\0"; |
|
95 | 96 | |
96 | 97 |
/* |
97 | 98 |
* |
... | ... | |
319 | 320 |
/* |
320 | 321 |
* |
321 | 322 |
*/ |
323 |
static inline int |
|
324 |
rtsp_announced_port(struct sockaddr_storage *peer, struct sockaddr_storage *self) |
|
325 |
{ |
|
326 |
int used_port = 0; |
|
327 | ||
328 |
if (satip_server_conf.satip_nat_name_force || !check_is_local_address(peer,self)) { |
|
329 |
used_port = (rtsp_nat_port > 0)? rtsp_nat_port : rtsp_port; |
|
330 |
} else { |
|
331 |
used_port = rtsp_port; |
|
332 |
} |
|
333 | ||
334 |
return used_port; |
|
335 |
} |
|
336 | ||
337 |
/* |
|
338 |
* |
|
339 |
*/ |
|
340 |
static inline char * |
|
341 |
rtsp_announced_ip(struct sockaddr_storage *peer, struct sockaddr_storage *self) |
|
342 |
{ |
|
343 |
char *used_ip; |
|
344 | ||
345 |
if (satip_server_conf.satip_nat_name_force || !check_is_local_address(peer,self)) { |
|
346 |
used_ip = rtsp_nat_ip; |
|
347 |
} else { |
|
348 |
used_ip = rtsp_ip; |
|
349 |
} |
|
350 | ||
351 |
if (used_ip[0] == '*' || used_ip[0] == '\0' || used_ip == NULL) { |
|
352 |
used_ip = any_ip; |
|
353 |
} |
|
354 | ||
355 |
return used_ip; |
|
356 |
} |
|
357 | ||
358 |
/* |
|
359 |
* |
|
360 |
*/ |
|
322 | 361 |
static void |
323 | 362 |
rtsp_slave_add |
324 | 363 |
(session_t *rs, mpegts_service_t *master, mpegts_service_t *slave) |
... | ... | |
1322 | 1361 |
char *u = tvh_strdupa(hc->hc_url); |
1323 | 1362 |
session_t *rs; |
1324 | 1363 |
htsbuf_queue_t q; |
1325 |
char buf[96]; |
|
1364 |
char buf[96], *used_ip = NULL;
|
|
1326 | 1365 |
int r = HTTP_STATUS_BAD_REQUEST; |
1327 |
int stream, first = 1, valid; |
|
1366 |
int stream, first = 1, valid, used_port;
|
|
1328 | 1367 | |
1329 | 1368 |
htsbuf_queue_init(&q, 0); |
1330 | 1369 | |
... | ... | |
1381 | 1420 |
http_arg_init(&args); |
1382 | 1421 |
if (hc->hc_session) |
1383 | 1422 |
http_arg_set(&args, "Session", hc->hc_session); |
1384 |
if (stream > 0) |
|
1385 |
snprintf(buf, sizeof(buf), "rtsp://%s/stream=%i", rtsp_ip, stream); |
|
1423 |
used_port = rtsp_announced_port(hc->hc_peer,hc->hc_self); |
|
1424 |
used_ip = rtsp_announced_ip(hc->hc_peer,hc->hc_self); |
|
1425 |
if ((stream > 0) && (used_port != 554)) |
|
1426 |
snprintf(buf, sizeof(buf), "rtsp://%s:%d/stream=%i", used_ip, used_port, stream); |
|
1427 |
else if ((stream > 0) && (used_port == 554)) |
|
1428 |
snprintf(buf, sizeof(buf), "rtsp://%s/stream=%i", used_ip, stream); |
|
1429 |
else if (used_port != 554) |
|
1430 |
snprintf(buf, sizeof(buf), "rtsp://%s:%d", used_ip, used_port); |
|
1386 | 1431 |
else |
1387 |
snprintf(buf, sizeof(buf), "rtsp://%s", rtsp_ip);
|
|
1432 |
snprintf(buf, sizeof(buf), "rtsp://%s", used_ip);
|
|
1388 | 1433 |
http_arg_set(&args, "Content-Base", buf); |
1389 | 1434 |
http_send_begin(hc); |
1390 | 1435 |
http_send_header(hc, HTTP_STATUS_OK, "application/sdp", q.hq_size, |
... | ... | |
1408 | 1453 |
rtsp_process_play(http_connection_t *hc, int cmd) |
1409 | 1454 |
{ |
1410 | 1455 |
session_t *rs; |
1411 |
int errcode = HTTP_STATUS_BAD_REQUEST, valid = 0, i, stream; |
|
1412 |
char buf[256], *u = tvh_strdupa(hc->hc_url); |
|
1456 |
int errcode = HTTP_STATUS_BAD_REQUEST, valid = 0, i, stream, used_port;
|
|
1457 |
char buf[256], *u = tvh_strdupa(hc->hc_url), *used_ip = NULL;
|
|
1413 | 1458 |
http_arg_list_t args; |
1414 | 1459 | |
1415 | 1460 |
http_arg_init(&args); |
... | ... | |
1467 | 1512 |
snprintf(buf, sizeof(buf), "%d", rs->stream); |
1468 | 1513 |
http_arg_set(&args, "com.ses.streamID", buf); |
1469 | 1514 |
} else { |
1470 |
if (rtsp_port != 554) |
|
1471 |
snprintf(buf, sizeof(buf), "url=rtsp://%s:%d/stream=%d", rtsp_ip, rtsp_port, rs->stream); |
|
1515 |
used_port = rtsp_announced_port(hc->hc_peer,hc->hc_self); |
|
1516 |
used_ip = rtsp_announced_ip(hc->hc_peer,hc->hc_self); |
|
1517 |
if (used_port != 554) |
|
1518 |
snprintf(buf, sizeof(buf), "url=rtsp://%s:%d/stream=%d", used_ip, used_port, rs->stream); |
|
1472 | 1519 |
else |
1473 |
snprintf(buf, sizeof(buf), "url=rtsp://%s/stream=%d", rtsp_ip, rs->stream);
|
|
1520 |
snprintf(buf, sizeof(buf), "url=rtsp://%s/stream=%d", used_ip, rs->stream);
|
|
1474 | 1521 |
http_arg_set(&args, "RTP-Info", buf); |
1475 | 1522 |
} |
1476 | 1523 |
src/satip/server.c | ||
---|---|---|
777 | 777 |
.group = 2, |
778 | 778 |
}, |
779 | 779 |
{ |
780 |
.type = PT_BOOL, |
|
781 |
.id = "satip_nat_name_force", |
|
782 |
.name = N_("Force RTSP announcement of the external (NAT) ip:port"), |
|
783 |
.desc = N_("Advertise only NAT address and port in RTSP commands," |
|
784 |
"even for local connections."), |
|
785 |
.off = offsetof(struct satip_server_conf, satip_nat_name_force), |
|
786 |
.opts = PO_EXPERT, |
|
787 |
.group = 2, |
|
788 |
}, |
|
789 | ||
790 | ||
791 | ||
792 |
{ |
|
780 | 793 |
.type = PT_U32, |
781 | 794 |
.id = "satip_iptv_sig_level", |
782 | 795 |
.name = N_("IPTV signal level"), |
src/satip/server.h | ||
---|---|---|
65 | 65 |
int satip_atsc_c; |
66 | 66 |
char *satip_nat_ip; |
67 | 67 |
int satip_nat_rtsp; |
68 |
int satip_nat_name_force; |
|
68 | 69 |
}; |
69 | 70 | |
70 | 71 |
extern struct satip_server_conf satip_server_conf; |
src/tcp.c | ||
---|---|---|
34 | 34 |
#include <netinet/in.h> |
35 | 35 |
#include <netinet/tcp.h> |
36 | 36 |
#include <arpa/inet.h> |
37 |
#include <sys/types.h> |
|
38 |
#include <ifaddrs.h> |
|
37 | 39 | |
38 | 40 |
#include "tvheadend.h" |
39 | 41 |
#include "tcp.h" |
... | ... | |
73 | 75 |
/** |
74 | 76 |
* |
75 | 77 |
*/ |
78 |
inline int |
|
79 |
check_equal_v4(const struct in_addr * a, |
|
80 |
const struct in_addr * b) |
|
81 |
{ |
|
82 |
return (a->s_addr == b->s_addr); |
|
83 |
} |
|
84 | ||
85 |
/** |
|
86 |
* |
|
87 |
*/ |
|
88 |
inline int |
|
89 |
check_equal_v6(const struct in6_addr * a, |
|
90 |
const struct in6_addr * b) |
|
91 |
{ |
|
92 |
return (memcmp(a->s6_addr, b->s6_addr, 16) == 0) ? 1 : 0; |
|
93 |
} |
|
94 | ||
95 |
/** |
|
96 |
* |
|
97 |
*/ |
|
98 |
inline int |
|
99 |
check_in_network_v4(const struct in_addr * network, |
|
100 |
const struct in_addr * mask, |
|
101 |
const struct in_addr * address) |
|
102 |
{ |
|
103 |
return ((address->s_addr & mask->s_addr) == (network->s_addr & mask->s_addr)); |
|
104 |
} |
|
105 | ||
106 |
/** |
|
107 |
* |
|
108 |
*/ |
|
109 |
inline int |
|
110 |
check_in_network_v6(const struct in6_addr * network, |
|
111 |
const struct in6_addr * mask, |
|
112 |
const struct in6_addr * address) |
|
113 |
{ |
|
114 |
unsigned int i; |
|
115 |
for (i=0; i<sizeof(struct in6_addr)/sizeof (int); i++) |
|
116 |
if ( ((((int *) address)[i] & ((int *) mask)[i])) != |
|
117 |
(((int *) network)[i] & ((int *) mask)[i])) { |
|
118 |
return 0; |
|
119 |
} |
|
120 |
return 1; |
|
121 |
} |
|
122 | ||
123 |
/** |
|
124 |
* |
|
125 |
*/ |
|
126 |
inline int |
|
127 |
check_is_any_v4(const struct in_addr * address) |
|
128 |
{ |
|
129 |
return (address->s_addr == INADDR_ANY); |
|
130 |
} |
|
131 | ||
132 |
/** |
|
133 |
* |
|
134 |
*/ |
|
135 |
inline int |
|
136 |
check_is_any_v6(const struct in6_addr * address) |
|
137 |
{ |
|
138 |
return (check_equal_v6(address,&in6addr_any)); |
|
139 |
} |
|
140 | ||
141 |
/** |
|
142 |
* |
|
143 |
*/ |
|
144 |
int |
|
145 |
check_is_local_address(const struct sockaddr_storage *peer, const struct sockaddr_storage *local) |
|
146 |
{ |
|
147 |
struct ifaddrs *iflist, *ifdev = NULL; |
|
148 |
struct sockaddr_storage *ifaddr, *ifnetmask; |
|
149 |
int any_address = 0; |
|
150 | ||
151 |
if ( (local->ss_family == AF_INET && check_is_any_v4(&((struct sockaddr_in *)local)->sin_addr) ) || |
|
152 |
(local->ss_family == AF_INET6 && check_is_any_v6(&((struct sockaddr_in6 *)local)->sin6_addr) ) ) { |
|
153 |
any_address = 1; |
|
154 |
} |
|
155 |
tvhdebug(LS_SATIPS, "tcp_is_local_address(): ANY=%i",any_address); |
|
156 | ||
157 |
// Note: Not all platforms have getifaddrs() |
|
158 |
// See http://docs.freeswitch.org/switch__utils_8c_source.html |
|
159 |
if (!local || !peer || getifaddrs(&iflist) < 0) return 0; |
|
160 | ||
161 |
for (ifdev = iflist; ifdev; ifdev = ifdev->ifa_next) { |
|
162 |
ifaddr = (struct sockaddr_storage *)(ifdev->ifa_addr); |
|
163 |
ifnetmask = (struct sockaddr_storage *)(ifdev->ifa_netmask); |
|
164 | ||
165 |
if (ifaddr && ifnetmask && ifaddr->ss_family == local->ss_family && ifaddr->ss_family == peer->ss_family) { |
|
166 | ||
167 |
if (ifaddr->ss_family == AF_INET) { |
|
168 |
if ((any_address || check_equal_v4( &((struct sockaddr_in *)ifaddr)->sin_addr, &((struct sockaddr_in *)local)->sin_addr )) |
|
169 |
&& check_in_network_v4( &((struct sockaddr_in *)ifaddr)->sin_addr, |
|
170 |
&((struct sockaddr_in *)ifnetmask)->sin_addr, |
|
171 |
&((struct sockaddr_in *)peer)->sin_addr) ) { |
|
172 |
freeifaddrs(iflist); |
|
173 |
return 1; |
|
174 |
} |
|
175 |
} else if (ifaddr->ss_family == AF_INET6) { |
|
176 |
if ((any_address || check_equal_v6( &((struct sockaddr_in6 *)ifaddr)->sin6_addr, &((struct sockaddr_in6 *)local)->sin6_addr )) |
|
177 |
&& check_in_network_v6( &((struct sockaddr_in6 *)ifaddr)->sin6_addr, |
|
178 |
&((struct sockaddr_in6 *)ifnetmask)->sin6_addr, |
|
179 |
&((struct sockaddr_in6 *)peer)->sin6_addr) ) { |
|
180 |
freeifaddrs(iflist); |
|
181 |
return 1; |
|
182 |
} |
|
183 |
} |
|
184 |
} |
|
185 |
} |
|
186 |
freeifaddrs(iflist); |
|
187 |
return 0; |
|
188 |
} |
|
189 | ||
190 |
/** |
|
191 |
* |
|
192 |
*/ |
|
76 | 193 |
int |
77 | 194 |
tcp_connect(const char *hostname, int port, const char *bindaddr, |
78 | 195 |
char *errbuf, size_t errbufsize, int timeout) |
src/tcp.h | ||
---|---|---|
58 | 58 |
void tcp_server_init(void); |
59 | 59 |
void tcp_server_done(void); |
60 | 60 | |
61 |
int check_equal_v4(const struct in_addr * a, const struct in_addr * b); |
|
62 |
int check_equal_v6(const struct in6_addr * a, const struct in6_addr * b); |
|
63 |
int check_in_network_v4(const struct in_addr * network, |
|
64 |
const struct in_addr * mask, |
|
65 |
const struct in_addr * address); |
|
66 |
int check_in_network_v6(const struct in6_addr * network, |
|
67 |
const struct in6_addr * mask, |
|
68 |
const struct in6_addr * address); |
|
69 |
int check_is_any_v4(const struct in_addr * address); |
|
70 |
int check_is_any_v6(const struct in6_addr * address); |
|
71 |
int check_is_local_address(const struct sockaddr_storage *peer, const struct sockaddr_storage *local); |
|
72 | ||
61 | 73 |
int socket_set_dscp(int sockfd, uint32_t dscp, char *errbuf, size_t errbufsize); |
62 | 74 | |
63 | 75 |
int tcp_connect(const char *hostname, int port, const char *bindaddr, |