Browse Source

support specifying interfaces to use in control protocols

pull/26/head
Richard Fuchs 11 years ago
parent
commit
45dee75156
7 changed files with 72 additions and 46 deletions
  1. +6
    -0
      daemon/aux.h
  2. +54
    -27
      daemon/call.c
  3. +1
    -6
      daemon/call.h
  4. +4
    -11
      daemon/call_interfaces.c
  5. +1
    -1
      daemon/sdp.c
  6. +1
    -1
      daemon/sdp.h
  7. +5
    -0
      utils/ng-client

+ 6
- 0
daemon/aux.h View File

@ -382,6 +382,12 @@ INLINE int is_addr_unspecified(const struct in6_addr *a) {
return 0; return 0;
} }
INLINE int family_from_address(const struct in6_addr *a) {
if (IN6_IS_ADDR_V4MAPPED(a))
return AF_INET;
return AF_INET6;
}
/* checks if at least one of the flags is set */ /* checks if at least one of the flags is set */
INLINE int bf_isset(const unsigned int *u, unsigned int f) { INLINE int bf_isset(const unsigned int *u, unsigned int f) {
if ((*u & f)) if ((*u & f))


+ 54
- 27
daemon/call.c View File

@ -307,8 +307,9 @@ static void stream_unkernelize(struct packet_stream *ps);
static void __monologue_destroy(struct call_monologue *monologue); static void __monologue_destroy(struct call_monologue *monologue);
static struct interface_address *get_interface_from_address(struct local_interface *lif, struct in6_addr *addr); static struct interface_address *get_interface_from_address(struct local_interface *lif, struct in6_addr *addr);
static struct interface_address *get_interface_address(struct local_interface *lif, int family); static struct interface_address *get_interface_address(struct local_interface *lif, int family);
static struct local_interface *get_local_interface(struct callmaster *m, str *name);
static struct local_interface *get_local_interface(struct callmaster *m, const str *name);
static const GQueue *get_interface_addresses(struct local_interface *lif, int family); static const GQueue *get_interface_addresses(struct local_interface *lif, int family);
static struct interface_address *get_any_interface_address(struct local_interface *lif);
@ -336,14 +337,11 @@ 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) { 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->family = family_from_address(&ep->ip46);
if (o->family == AF_INET)
o->u.ipv4 = in6_to_4(&ep->ip46); o->u.ipv4 = in6_to_4(&ep->ip46);
}
else {
o->family = AF_INET6;
else
memcpy(o->u.ipv6, &ep->ip46, sizeof(o->u.ipv6)); memcpy(o->u.ipv6, &ep->ip46, sizeof(o->u.ipv6));
}
o->port = ep->port; o->port = ep->port;
} }
@ -781,12 +779,12 @@ update_addr:
char ifa_buf[64]; char ifa_buf[64];
smart_ntop(ifa_buf, dst, sizeof(ifa_buf)); smart_ntop(ifa_buf, dst, sizeof(ifa_buf));
ifa = get_interface_from_address(media->interface, dst); ifa = get_interface_from_address(media->interface, dst);
if (!ifa)
if (!ifa) {
ilog(LOG_ERROR, "No matching local interface for destination address %s found", ifa_buf); ilog(LOG_ERROR, "No matching local interface for destination address %s found", ifa_buf);
else {
ilog(LOG_INFO, "Switching local interface to %s", ifa_buf);
media->local_address = ifa;
goto drop;
} }
ilog(LOG_INFO, "Switching local interface to %s", ifa_buf);
media->local_address = ifa;
update = 1; update = 1;
} }
@ -2046,6 +2044,34 @@ static void __tos_change(struct call *call, const struct sdp_ng_flags *flags) {
__set_all_tos(call); __set_all_tos(call);
} }
static void __init_interface(struct call_media *media, const str *ifname) {
if (!media->interface || !media->local_address)
goto get;
if (!ifname || !ifname->s)
return;
if (!str_cmp_str(&media->interface->name, ifname))
return;
get:
media->interface = get_local_interface(media->call->callmaster, ifname);
if (!media->interface) {
media->interface = get_local_interface(media->call->callmaster, NULL);
/* legacy support */
if (!str_cmp(ifname, "internal"))
media->desired_family = AF_INET;
else if (!str_cmp(ifname, "external"))
media->desired_family = AF_INET6;
else
ilog(LOG_WARNING, "Interface '"STR_FORMAT"' not found, using default", STR_FMT(ifname));
}
media->local_address = get_interface_address(media->interface, media->desired_family);
if (!media->local_address) {
ilog(LOG_WARNING, "No usable address in interface '"STR_FORMAT"' found, using default",
STR_FMT(ifname));
media->local_address = get_any_interface_address(media->interface);
media->desired_family = family_from_address(&media->local_address->addr);
}
}
/* called with call->master_lock held in W */ /* called with call->master_lock held in W */
int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams, int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams,
const struct sdp_ng_flags *flags) const struct sdp_ng_flags *flags)
@ -2057,10 +2083,8 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams,
struct call_monologue *monologue = other_ml->active_dialogue; struct call_monologue *monologue = other_ml->active_dialogue;
struct endpoint_map *em; struct endpoint_map *em;
struct call *call; struct call *call;
struct callmaster *cm;
call = monologue->call; call = monologue->call;
cm = call->callmaster;
call->last_signal = poller_now; call->last_signal = poller_now;
call->deleted = 0; call->deleted = 0;
@ -2145,25 +2169,17 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams,
__generate_crypto(flags, media, other_media); __generate_crypto(flags, media, other_media);
/* deduct address family from stream parameters received */ /* deduct address family from stream parameters received */
other_media->desired_family = AF_INET;
if (!IN6_IS_ADDR_V4MAPPED(&sp->rtp_endpoint.ip46))
other_media->desired_family = AF_INET6;
other_media->desired_family = family_from_address(&sp->rtp_endpoint.ip46);
/* for outgoing SDP, use "direction"/DF or default to what was offered */ /* for outgoing SDP, use "direction"/DF or default to what was offered */
if (!media->desired_family) if (!media->desired_family)
media->desired_family = other_media->desired_family; media->desired_family = other_media->desired_family;
if (sp->desired_family) if (sp->desired_family)
media->desired_family = sp->desired_family; media->desired_family = sp->desired_family;
else if (sp->direction[1] == DIR_EXTERNAL)
media->desired_family = AF_INET6;
/* local interface selection XXX */
media->interface = get_local_interface(cm, NULL);
media->local_address = get_interface_address(media->interface, media->desired_family);
other_media->interface = get_local_interface(cm, NULL);
other_media->local_address = get_interface_address(other_media->interface,
other_media->desired_family);
/* local interface selection */
__init_interface(media, &sp->direction[1]);
__init_interface(other_media, &sp->direction[0]);
/* we now know what's being advertised by the other side */ /* we now know what's being advertised by the other side */
@ -2840,10 +2856,10 @@ void callmaster_config_init(struct callmaster *m) {
} }
} }
static struct local_interface *get_local_interface(struct callmaster *m, str *name) {
static struct local_interface *get_local_interface(struct callmaster *m, const str *name) {
struct local_interface *lif; struct local_interface *lif;
if (!name)
if (!name || !name->s)
return m->interface_list.head->data; return m->interface_list.head->data;
lif = g_hash_table_lookup(m->interfaces, name); lif = g_hash_table_lookup(m->interfaces, name);
@ -2875,6 +2891,17 @@ static struct interface_address *get_interface_address(struct local_interface *l
return q->head->data; return q->head->data;
} }
/* safety fallback */
static struct interface_address *get_any_interface_address(struct local_interface *lif) {
struct interface_address *ifa;
GQueue q = G_QUEUE_INIT;
get_all_interface_addresses(&q, lif, AF_INET);
ifa = q.head->data;
g_queue_clear(&q);
return ifa;
}
void get_all_interface_addresses(GQueue *q, struct local_interface *lif, int family) { void get_all_interface_addresses(GQueue *q, struct local_interface *lif, int family) {
g_queue_append(q, get_interface_addresses(lif, family)); g_queue_append(q, get_interface_addresses(lif, family));
if (family == AF_INET) if (family == AF_INET)


+ 1
- 6
daemon/call.h View File

@ -20,11 +20,6 @@ enum stream_address_format {
SAF_NG, SAF_NG,
SAF_ICE, SAF_ICE,
}; };
enum stream_direction {
DIR_UNKNOWN = 0,
DIR_INTERNAL,
DIR_EXTERNAL,
};
enum call_opmode { enum call_opmode {
OP_OFFER = 0, OP_OFFER = 0,
OP_ANSWER = 1, OP_ANSWER = 1,
@ -201,7 +196,7 @@ struct stream_params {
const struct transport_protocol *protocol; const struct transport_protocol *protocol;
struct crypto_params crypto; struct crypto_params crypto;
unsigned int sdes_tag; unsigned int sdes_tag;
enum stream_direction direction[2];
str direction[2];
int desired_family; int desired_family;
struct dtls_fingerprint fingerprint; struct dtls_fingerprint fingerprint;
unsigned int sp_flags; unsigned int sp_flags;


+ 4
- 11
daemon/call_interfaces.c View File

@ -108,9 +108,9 @@ static int addr_parse_udp(struct stream_params *sp, char **out) {
for (cp =out[RE_UDP_UL_FLAGS]; *cp && i < 2; cp++) { for (cp =out[RE_UDP_UL_FLAGS]; *cp && i < 2; cp++) {
c = chrtoupper(*cp); c = chrtoupper(*cp);
if (c == 'E') if (c == 'E')
sp->direction[i++] = DIR_EXTERNAL;
str_init(&sp->direction[i++], "external");
else if (c == 'I') else if (c == 'I')
sp->direction[i++] = DIR_INTERNAL;
str_init(&sp->direction[i++], "internal");
} }
} }
@ -505,15 +505,8 @@ static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *inpu
diridx = 0; diridx = 0;
if ((list = bencode_dictionary_get_expect(input, "direction", BENCODE_LIST))) { if ((list = bencode_dictionary_get_expect(input, "direction", BENCODE_LIST))) {
for (it = list->child; it && diridx < 2; it = it->sibling) {
if (!bencode_strcmp(it, "internal"))
out->directions[diridx++] = DIR_INTERNAL;
else if (!bencode_strcmp(it, "external"))
out->directions[diridx++] = DIR_EXTERNAL;
else
ilog(LOG_WARN, "Unknown 'direction' flag encountered: '"BENCODE_FORMAT"'",
BENCODE_FMT(it));
}
for (it = list->child; it && diridx < 2; it = it->sibling)
bencode_get_str(it, &out->direction[diridx++]);
} }
list = bencode_dictionary_get_expect(input, "received from", BENCODE_LIST); list = bencode_dictionary_get_expect(input, "received from", BENCODE_LIST);


+ 1
- 1
daemon/sdp.c View File

@ -985,7 +985,7 @@ int sdp_streams(const GQueue *sessions, GQueue *streams, struct sdp_ng_flags *fl
sp->consecutive_ports = media->port_count; sp->consecutive_ports = media->port_count;
sp->protocol = transport_protocol(&media->transport); sp->protocol = transport_protocol(&media->transport);
sp->type = media->media_type; sp->type = media->media_type;
memcpy(sp->direction, flags->directions, sizeof(sp->direction));
memcpy(sp->direction, flags->direction, sizeof(sp->direction));
sp->desired_family = flags->address_family; sp->desired_family = flags->address_family;
bf_xset(&sp->sp_flags, SP_FLAG_ASYMMETRIC, flags->asymmetric); 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_STRICT_SOURCE, flags->strict_source);


+ 1
- 1
daemon/sdp.h View File

@ -16,7 +16,7 @@ struct sdp_ng_flags {
const struct transport_protocol *transport_protocol; const struct transport_protocol *transport_protocol;
struct in6_addr parsed_received_from; struct in6_addr parsed_received_from;
struct in6_addr parsed_media_address; struct in6_addr parsed_media_address;
enum stream_direction directions[2];
str direction[2];
int address_family; int address_family;
int tos; int tos;
int asymmetric:1, int asymmetric:1,


+ 5
- 0
utils/ng-client View File

@ -34,6 +34,7 @@ GetOptions(
'rtcp-mux-accept' => \$options{'rtcp-mux-accept'}, 'rtcp-mux-accept' => \$options{'rtcp-mux-accept'},
'rtcp-mux-reject' => \$options{'rtcp-mux-reject'}, 'rtcp-mux-reject' => \$options{'rtcp-mux-reject'},
'address-family=s' => \$options{'address family'}, 'address-family=s' => \$options{'address family'},
'direction=s' => \$options{'direction'},
'force' => \$options{'force'}, 'force' => \$options{'force'},
'v|verbose' => \$options{'verbose'}, 'v|verbose' => \$options{'verbose'},
'strict-source' => \$options{'strict source'}, 'strict-source' => \$options{'strict source'},
@ -57,6 +58,10 @@ for my $x (split(',', 'origin,session connection')) {
for my $x (split(',', 'offer,demux,accept,reject')) { for my $x (split(',', 'offer,demux,accept,reject')) {
defined($options{'rtcp-mux-' . $x}) and push(@{$packet{'rtcp-mux'}}, $x); defined($options{'rtcp-mux-' . $x}) and push(@{$packet{'rtcp-mux'}}, $x);
} }
if (defined($options{direction})) {
$options{direction} =~ /(.*),(.*)/ or die;
$packet{direction} = [$1,$2];
}
if (defined($options{sdp})) { if (defined($options{sdp})) {
$packet{sdp} = $options{sdp}; $packet{sdp} = $options{sdp};


Loading…
Cancel
Save