Browse Source

implement media-handover and strict-source logic

pull/6/head
Richard Fuchs 12 years ago
parent
commit
4ded03de91
4 changed files with 83 additions and 32 deletions
  1. +71
    -31
      daemon/call.c
  2. +7
    -0
      daemon/call.h
  3. +2
    -0
      daemon/sdp.c
  4. +3
    -1
      utils/ng-client

+ 71
- 31
daemon/call.c View File

@ -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;


+ 7
- 0
daemon/call.h View File

@ -77,6 +77,8 @@ struct call_monologue;
#define SHARED_FLAG_SETUP_ACTIVE 0x00000020
#define SHARED_FLAG_SETUP_PASSIVE 0x00000040
#define SHARED_FLAG_ICE 0x00000080
#define SHARED_FLAG_STRICT_SOURCE 0x00000100
#define SHARED_FLAG_MEDIA_HANDOVER 0x00000200
/* struct stream_params */
#define SP_FLAG_NO_RTCP 0x00010000
@ -88,6 +90,8 @@ struct call_monologue;
#define SP_FLAG_SETUP_ACTIVE SHARED_FLAG_SETUP_ACTIVE
#define SP_FLAG_SETUP_PASSIVE SHARED_FLAG_SETUP_PASSIVE
#define SP_FLAG_ICE SHARED_FLAG_ICE
#define SP_FLAG_STRICT_SOURCE SHARED_FLAG_STRICT_SOURCE
#define SP_FLAG_MEDIA_HANDOVER SHARED_FLAG_MEDIA_HANDOVER
/* struct packet_stream */
#define PS_FLAG_RTP 0x00010000
@ -101,6 +105,8 @@ struct call_monologue;
#define PS_FLAG_NO_KERNEL_SUPPORT 0x00800000
#define PS_FLAG_HAS_HANDLER 0x01000000
#define PS_FLAG_FINGERPRINT_VERIFIED 0x02000000
#define PS_FLAG_STRICT_SOURCE SHARED_FLAG_STRICT_SOURCE
#define PS_FLAG_MEDIA_HANDOVER SHARED_FLAG_MEDIA_HANDOVER
/* struct call_media */
#define MEDIA_FLAG_INITIALIZED 0x00010000
@ -320,6 +326,7 @@ struct callmaster {
u_int16_t lastport;
BIT_ARRAY_DECLARE(ports_used, 0x10000);
/* XXX rework these */
mutex_t statspslock;
struct stats statsps; /* per second stats, running timer */
mutex_t statslock;


+ 2
- 0
daemon/sdp.c View File

@ -987,6 +987,8 @@ int sdp_streams(const GQueue *sessions, GQueue *streams, struct sdp_ng_flags *fl
memcpy(sp->direction, flags->directions, sizeof(sp->direction));
sp->desired_family = flags->address_family;
bf_xset(&sp->sp_flags, SP_FLAG_ASYMMETRIC, flags->asymmetric);
bf_xset(&sp->sp_flags, SP_FLAG_STRICT_SOURCE, flags->strict_source);
bf_xset(&sp->sp_flags, SP_FLAG_MEDIA_HANDOVER, flags->media_handover);
/* a=crypto */
attr = attr_get_by_id(&media->attributes, ATTR_CRYPTO);


+ 3
- 1
utils/ng-client View File

@ -33,6 +33,8 @@ GetOptions(
'address-family=s' => \$options{'address family'},
'force' => \$options{'force'},
'v|verbose' => \$options{'verbose'},
'strict-source' => \$options{'strict source'},
'media-handover' => \$options{'media handover'},
) or die;
my $cmd = shift(@ARGV) or die;
@ -42,7 +44,7 @@ my %packet = (command => $cmd);
for my $x (split(',', 'from-tag,to-tag,call-id,transport protocol,media address,ICE,address family')) {
defined($options{$x}) and $packet{$x} = $options{$x};
}
for my $x (split(',', 'trust address,symmetric,asymmetric,force')) {
for my $x (split(',', 'trust address,symmetric,asymmetric,force,strict source,media handover')) {
defined($options{$x}) and push(@{$packet{flags}}, $x);
}
for my $x (split(',', 'origin,session connection')) {


Loading…
Cancel
Save