mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-21 10:55:51 +02:00
Merge commit '6b58e11a8331690ec32e9869db89ae10c54614e9'
* commit '6b58e11a8331690ec32e9869db89ae10c54614e9': rtpproto: Add an option for writing return packets to the address of the last received packets Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
commit
2425be894a
@ -45,6 +45,9 @@ typedef struct RTPContext {
|
||||
URLContext *rtp_hd, *rtcp_hd;
|
||||
int rtp_fd, rtcp_fd, nb_ssm_include_addrs, nb_ssm_exclude_addrs;
|
||||
struct sockaddr_storage **ssm_include_addrs, **ssm_exclude_addrs;
|
||||
int write_to_source;
|
||||
struct sockaddr_storage last_rtp_source, last_rtcp_source;
|
||||
socklen_t last_rtp_source_len, last_rtcp_source_len;
|
||||
} RTPContext;
|
||||
|
||||
/**
|
||||
@ -125,6 +128,27 @@ static int compare_addr(const struct sockaddr_storage *a,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_port(const struct sockaddr_storage *ss)
|
||||
{
|
||||
if (ss->ss_family == AF_INET)
|
||||
return ntohs(((const struct sockaddr_in *)ss)->sin_port);
|
||||
#ifdef AF_INET6
|
||||
if (ss->ss_family == AF_INET6)
|
||||
return ntohs(((const struct sockaddr_in6 *)ss)->sin6_port);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_port(struct sockaddr_storage *ss, int port)
|
||||
{
|
||||
if (ss->ss_family == AF_INET)
|
||||
((struct sockaddr_in *)ss)->sin_port = htons(port);
|
||||
#ifdef AF_INET6
|
||||
else if (ss->ss_family == AF_INET6)
|
||||
((struct sockaddr_in6 *)ss)->sin6_port = htons(port);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int rtp_check_source_lists(RTPContext *s, struct sockaddr_storage *source_addr_ptr)
|
||||
{
|
||||
int i;
|
||||
@ -237,6 +261,7 @@ static void rtp_parse_addr_list(URLContext *h, char *buf,
|
||||
* 'connect=0/1' : do a connect() on the UDP socket
|
||||
* 'sources=ip[,ip]' : list allowed source IP addresses
|
||||
* 'block=ip[,ip]' : list disallowed source IP addresses
|
||||
* 'write_to_source=0/1' : send packets to the source address of the latest received packet
|
||||
* deprecated option:
|
||||
* 'localport=n' : set the local port to n
|
||||
*
|
||||
@ -290,6 +315,9 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
|
||||
if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
|
||||
connect = strtol(buf, NULL, 10);
|
||||
}
|
||||
if (av_find_info_tag(buf, sizeof(buf), "write_to_source", p)) {
|
||||
s->write_to_source = strtol(buf, NULL, 10);
|
||||
}
|
||||
if (av_find_info_tag(buf, sizeof(buf), "sources", p)) {
|
||||
av_strlcpy(include_sources, buf, sizeof(include_sources));
|
||||
rtp_parse_addr_list(h, buf, &s->ssm_include_addrs, &s->nb_ssm_include_addrs);
|
||||
@ -334,11 +362,11 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
|
||||
static int rtp_read(URLContext *h, uint8_t *buf, int size)
|
||||
{
|
||||
RTPContext *s = h->priv_data;
|
||||
struct sockaddr_storage from;
|
||||
socklen_t from_len;
|
||||
int len, n, i;
|
||||
struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0}, {s->rtcp_fd, POLLIN, 0}};
|
||||
int poll_delay = h->flags & AVIO_FLAG_NONBLOCK ? 0 : 100;
|
||||
struct sockaddr_storage *addrs[2] = { &s->last_rtp_source, &s->last_rtcp_source };
|
||||
socklen_t *addr_lens[2] = { &s->last_rtp_source_len, &s->last_rtcp_source_len };
|
||||
|
||||
for(;;) {
|
||||
if (ff_check_interrupt(&h->interrupt_callback))
|
||||
@ -349,16 +377,16 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size)
|
||||
for (i = 1; i >= 0; i--) {
|
||||
if (!(p[i].revents & POLLIN))
|
||||
continue;
|
||||
from_len = sizeof(from);
|
||||
*addr_lens[i] = sizeof(*addrs[i]);
|
||||
len = recvfrom(p[i].fd, buf, size, 0,
|
||||
(struct sockaddr *)&from, &from_len);
|
||||
(struct sockaddr *)addrs[i], addr_lens[i]);
|
||||
if (len < 0) {
|
||||
if (ff_neterrno() == AVERROR(EAGAIN) ||
|
||||
ff_neterrno() == AVERROR(EINTR))
|
||||
continue;
|
||||
return AVERROR(EIO);
|
||||
}
|
||||
if (rtp_check_source_lists(s, &from))
|
||||
if (rtp_check_source_lists(s, addrs[i]))
|
||||
continue;
|
||||
return len;
|
||||
}
|
||||
@ -382,6 +410,57 @@ static int rtp_write(URLContext *h, const uint8_t *buf, int size)
|
||||
if (size < 2)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
if (s->write_to_source) {
|
||||
int fd;
|
||||
struct sockaddr_storage *source, temp_source;
|
||||
socklen_t *source_len, temp_len;
|
||||
if (!s->last_rtp_source.ss_family && !s->last_rtcp_source.ss_family) {
|
||||
av_log(h, AV_LOG_ERROR,
|
||||
"Unable to send packet to source, no packets received yet\n");
|
||||
// Intentionally not returning an error here
|
||||
return size;
|
||||
}
|
||||
|
||||
if (RTP_PT_IS_RTCP(buf[1])) {
|
||||
fd = s->rtcp_fd;
|
||||
source = &s->last_rtcp_source;
|
||||
source_len = &s->last_rtcp_source_len;
|
||||
} else {
|
||||
fd = s->rtp_fd;
|
||||
source = &s->last_rtp_source;
|
||||
source_len = &s->last_rtp_source_len;
|
||||
}
|
||||
if (!source->ss_family) {
|
||||
source = &temp_source;
|
||||
source_len = &temp_len;
|
||||
if (RTP_PT_IS_RTCP(buf[1])) {
|
||||
temp_source = s->last_rtp_source;
|
||||
temp_len = s->last_rtp_source_len;
|
||||
set_port(source, get_port(source) + 1);
|
||||
av_log(h, AV_LOG_INFO,
|
||||
"Not received any RTCP packets yet, inferring peer port "
|
||||
"from the RTP port\n");
|
||||
} else {
|
||||
temp_source = s->last_rtcp_source;
|
||||
temp_len = s->last_rtcp_source_len;
|
||||
set_port(source, get_port(source) - 1);
|
||||
av_log(h, AV_LOG_INFO,
|
||||
"Not received any RTP packets yet, inferring peer port "
|
||||
"from the RTCP port\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
|
||||
ret = ff_network_wait_fd(fd, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
ret = sendto(fd, buf, size, 0, (struct sockaddr *) source,
|
||||
*source_len);
|
||||
|
||||
return ret < 0 ? ff_neterrno() : ret;
|
||||
}
|
||||
|
||||
if (RTP_PT_IS_RTCP(buf[1])) {
|
||||
/* RTCP payload type */
|
||||
hd = s->rtcp_hd;
|
||||
|
Loading…
Reference in New Issue
Block a user