|
|
|
|
@ -262,6 +262,7 @@ static const struct mediaproxy_srtp __mps_null = {
|
|
|
|
|
|
|
|
|
|
static void call_destroy(struct call *);
|
|
|
|
|
static void unkernelize(struct packet_stream *);
|
|
|
|
|
static void __stream_unkernelize(struct packet_stream *ps);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -288,6 +289,18 @@ static void stream_fd_closed(int fd, void *p, uintptr_t u) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
INLINE void __mp_address_translate(struct mp_address *o, const struct endpoint *ep) {
|
|
|
|
|
if (IN6_IS_ADDR_V4MAPPED(&ep->ip46)) {
|
|
|
|
|
o->family = AF_INET;
|
|
|
|
|
o->u.ipv4 = ep->ip46.s6_addr32[3];
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
o->family = AF_INET6;
|
|
|
|
|
memcpy(o->u.ipv6, &ep->ip46, sizeof(o->u.ipv6));
|
|
|
|
|
}
|
|
|
|
|
o->port = ep->port;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* called with in_lock held */
|
|
|
|
|
void kernelize(struct packet_stream *stream) {
|
|
|
|
|
struct mediaproxy_target_info mpt;
|
|
|
|
|
@ -306,8 +319,7 @@ void kernelize(struct packet_stream *stream) {
|
|
|
|
|
if (!stream->sfd)
|
|
|
|
|
goto no_kernel;
|
|
|
|
|
|
|
|
|
|
ilog(LOG_DEBUG, "Kernelizing media stream with local port %u",
|
|
|
|
|
stream->sfd->fd.localport);
|
|
|
|
|
ilog(LOG_INFO, "Kernelizing media stream");
|
|
|
|
|
|
|
|
|
|
sink = packet_stream_sink(stream);
|
|
|
|
|
if (!sink) {
|
|
|
|
|
@ -326,28 +338,33 @@ void kernelize(struct packet_stream *stream) {
|
|
|
|
|
|
|
|
|
|
ZERO(mpt);
|
|
|
|
|
|
|
|
|
|
if (PS_ISSET(stream, STRICT_SOURCE) || PS_ISSET(stream, MEDIA_HANDOVER)) {
|
|
|
|
|
mutex_lock(&stream->out_lock);
|
|
|
|
|
__mp_address_translate(&mpt.expected_src, &stream->endpoint);
|
|
|
|
|
mutex_unlock(&stream->out_lock);
|
|
|
|
|
if (PS_ISSET(stream, STRICT_SOURCE))
|
|
|
|
|
mpt.src_mismatch = MSM_DROP;
|
|
|
|
|
else if (PS_ISSET(stream, MEDIA_HANDOVER))
|
|
|
|
|
mpt.src_mismatch = MSM_PROPAGATE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mutex_lock(&sink->out_lock);
|
|
|
|
|
|
|
|
|
|
mpt.target_port = stream->sfd->fd.localport;
|
|
|
|
|
mpt.tos = cm->conf.tos;
|
|
|
|
|
mpt.src_addr.port = sink->sfd->fd.localport;
|
|
|
|
|
mpt.dst_addr.port = sink->endpoint.port;
|
|
|
|
|
mpt.rtcp_mux = MEDIA_ISSET(stream->media, RTCP_MUX);
|
|
|
|
|
mpt.dtls = MEDIA_ISSET(stream->media, DTLS);
|
|
|
|
|
mpt.stun = PS_ISSET(stream, STUN);
|
|
|
|
|
|
|
|
|
|
if (IN6_IS_ADDR_V4MAPPED(&sink->endpoint.ip46)) {
|
|
|
|
|
mpt.src_addr.family = AF_INET;
|
|
|
|
|
__mp_address_translate(&mpt.dst_addr, &sink->endpoint);
|
|
|
|
|
|
|
|
|
|
mpt.src_addr.family = mpt.dst_addr.family;
|
|
|
|
|
mpt.src_addr.port = sink->sfd->fd.localport;
|
|
|
|
|
|
|
|
|
|
if (mpt.src_addr.family == AF_INET)
|
|
|
|
|
mpt.src_addr.u.ipv4 = cm->conf.ipv4;
|
|
|
|
|
mpt.dst_addr.family = AF_INET;
|
|
|
|
|
mpt.dst_addr.u.ipv4 = sink->endpoint.ip46.s6_addr32[3];
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
mpt.src_addr.family = AF_INET6;
|
|
|
|
|
else
|
|
|
|
|
memcpy(mpt.src_addr.u.ipv6, &cm->conf.ipv6, sizeof(mpt.src_addr.u.ipv6));
|
|
|
|
|
mpt.dst_addr.family = AF_INET6;
|
|
|
|
|
memcpy(mpt.dst_addr.u.ipv6, &sink->endpoint.ip46, sizeof(mpt.src_addr.u.ipv6));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stream->handler->in->kernel(&mpt.decrypt, stream);
|
|
|
|
|
stream->handler->out->kernel(&mpt.encrypt, sink);
|
|
|
|
|
@ -615,37 +632,55 @@ static int stream_packet(struct stream_fd *sfd, str *s, struct sockaddr_in6 *fsi
|
|
|
|
|
mutex_lock(&stream->in_lock);
|
|
|
|
|
|
|
|
|
|
use_cand:
|
|
|
|
|
/* we're OK to (potentially) use the source address of this packet as destination
|
|
|
|
|
* in the other direction. */
|
|
|
|
|
/* if the other side hasn't been signalled yet, just forward the packet */
|
|
|
|
|
if (!PS_ISSET(stream, FILLED))
|
|
|
|
|
goto forward;
|
|
|
|
|
|
|
|
|
|
/* do not pay attention to source addresses of incoming packets for asymmetric streams */
|
|
|
|
|
if (MEDIA_ISSET(media, ASYMMETRIC))
|
|
|
|
|
PS_SET(stream, CONFIRMED);
|
|
|
|
|
|
|
|
|
|
if (PS_ISSET(stream, CONFIRMED))
|
|
|
|
|
/* if we have already updated the endpoint in the past ... */
|
|
|
|
|
if (PS_ISSET(stream, CONFIRMED)) {
|
|
|
|
|
/* see if we need to compare the source address with the known endpoint */
|
|
|
|
|
if (PS_ISSET(stream, STRICT_SOURCE) || PS_ISSET(stream, MEDIA_HANDOVER)) {
|
|
|
|
|
endpoint.ip46 = fsin->sin6_addr;
|
|
|
|
|
endpoint.port = ntohs(fsin->sin6_port);
|
|
|
|
|
mutex_lock(&stream->out_lock);
|
|
|
|
|
|
|
|
|
|
int tmp = memcmp(&endpoint, &stream->endpoint, sizeof(endpoint));
|
|
|
|
|
if (tmp && PS_ISSET(stream, MEDIA_HANDOVER)) {
|
|
|
|
|
/* out_lock remains locked */
|
|
|
|
|
ilog(LOG_INFO, "Peer address changed to %s", addr);
|
|
|
|
|
__stream_unkernelize(stream);
|
|
|
|
|
goto update_addr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mutex_unlock(&stream->out_lock);
|
|
|
|
|
|
|
|
|
|
if (tmp && PS_ISSET(stream, STRICT_SOURCE)) {
|
|
|
|
|
stream->stats.errors++;
|
|
|
|
|
goto drop;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
goto kernel_check;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* wait at least 3 seconds after last signal before committing to a particular
|
|
|
|
|
* endpoint address */
|
|
|
|
|
if (!call->last_signal || poller_now <= call->last_signal + 3)
|
|
|
|
|
goto peerinfo;
|
|
|
|
|
goto update_peerinfo;
|
|
|
|
|
|
|
|
|
|
ilog(LOG_DEBUG, "Confirmed peer information for port %u - %s",
|
|
|
|
|
sfd->fd.localport, addr);
|
|
|
|
|
ilog(LOG_INFO, "Confirmed peer address as %s", addr);
|
|
|
|
|
|
|
|
|
|
PS_SET(stream, CONFIRMED);
|
|
|
|
|
update = 1;
|
|
|
|
|
|
|
|
|
|
peerinfo:
|
|
|
|
|
/*
|
|
|
|
|
if (!stun_ret && !stream->codec && s->len >= 2) {
|
|
|
|
|
cc = s->s[1];
|
|
|
|
|
cc &= 0x7f;
|
|
|
|
|
if (cc < G_N_ELEMENTS(rtp_codecs))
|
|
|
|
|
stream->codec = rtp_codecs[cc] ? : "unknown";
|
|
|
|
|
else
|
|
|
|
|
stream->codec = "unknown";
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
update_peerinfo:
|
|
|
|
|
mutex_lock(&stream->out_lock);
|
|
|
|
|
update_addr:
|
|
|
|
|
endpoint = stream->endpoint;
|
|
|
|
|
stream->endpoint.ip46 = fsin->sin6_addr;
|
|
|
|
|
stream->endpoint.port = ntohs(fsin->sin6_port);
|
|
|
|
|
@ -1513,8 +1548,11 @@ static int __init_streams(struct call_media *A, struct call_media *B, const stru
|
|
|
|
|
a->rtp_sink = b;
|
|
|
|
|
PS_SET(a, RTP);
|
|
|
|
|
|
|
|
|
|
if (sp)
|
|
|
|
|
if (sp) {
|
|
|
|
|
__fill_stream(a, &sp->rtp_endpoint, port_off);
|
|
|
|
|
bf_copy_same(&a->ps_flags, &sp->sp_flags,
|
|
|
|
|
SHARED_FLAG_STRICT_SOURCE | SHARED_FLAG_MEDIA_HANDOVER);
|
|
|
|
|
}
|
|
|
|
|
if (__init_stream(a))
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
@ -1561,6 +1599,8 @@ static int __init_streams(struct call_media *A, struct call_media *B, const stru
|
|
|
|
|
__fill_stream(a, &sp->rtp_endpoint, port_off + 1);
|
|
|
|
|
PS_SET(a, IMPLICIT_RTCP);
|
|
|
|
|
}
|
|
|
|
|
bf_copy_same(&a->ps_flags, &sp->sp_flags,
|
|
|
|
|
SHARED_FLAG_STRICT_SOURCE | SHARED_FLAG_MEDIA_HANDOVER);
|
|
|
|
|
}
|
|
|
|
|
if (__init_stream(a))
|
|
|
|
|
return -1;
|
|
|
|
|
|