|
|
|
@ -404,7 +404,7 @@ void kernelize(struct packet_stream *stream) { |
|
|
|
mpt.src_addr.family = mpt.dst_addr.family; |
|
|
|
mpt.src_addr.port = sink->sfd->fd.localport; |
|
|
|
|
|
|
|
ifa = get_first_interface_address(cm, NULL, mpt.src_addr.family); /* XXX */ |
|
|
|
ifa = sink->media->local_address; |
|
|
|
if (mpt.src_addr.family == AF_INET) |
|
|
|
mpt.src_addr.u.ipv4 = in6_to_4(&ifa->addr); |
|
|
|
else |
|
|
|
@ -534,7 +534,7 @@ noop: |
|
|
|
goto done; |
|
|
|
} |
|
|
|
|
|
|
|
void callmaster_msg_mh_src(struct callmaster *cm, struct msghdr *mh) { |
|
|
|
void stream_msg_mh_src(struct packet_stream *ps, struct msghdr *mh) { |
|
|
|
struct cmsghdr *ch; |
|
|
|
struct in_pktinfo *pi; |
|
|
|
struct in6_pktinfo *pi6; |
|
|
|
@ -543,6 +543,7 @@ void callmaster_msg_mh_src(struct callmaster *cm, struct msghdr *mh) { |
|
|
|
|
|
|
|
|
|
|
|
sin6 = mh->msg_name; |
|
|
|
ifa = ps->media->local_address; |
|
|
|
|
|
|
|
ch = CMSG_FIRSTHDR(mh); |
|
|
|
ZERO(*ch); |
|
|
|
@ -552,7 +553,6 @@ void callmaster_msg_mh_src(struct callmaster *cm, struct msghdr *mh) { |
|
|
|
ch->cmsg_level = IPPROTO_IP; |
|
|
|
ch->cmsg_type = IP_PKTINFO; |
|
|
|
|
|
|
|
ifa = get_first_interface_address(cm, NULL, AF_INET); |
|
|
|
pi = (void *) CMSG_DATA(ch); |
|
|
|
ZERO(*pi); |
|
|
|
pi->ipi_spec_dst.s_addr = in6_to_4(&ifa->addr); |
|
|
|
@ -564,7 +564,6 @@ void callmaster_msg_mh_src(struct callmaster *cm, struct msghdr *mh) { |
|
|
|
ch->cmsg_level = IPPROTO_IPV6; |
|
|
|
ch->cmsg_type = IPV6_PKTINFO; |
|
|
|
|
|
|
|
ifa = get_first_interface_address(cm, NULL, AF_INET); |
|
|
|
pi6 = (void *) CMSG_DATA(ch); |
|
|
|
ZERO(*pi6); |
|
|
|
pi6->ipi6_addr = ifa->addr; |
|
|
|
@ -800,7 +799,7 @@ forward: |
|
|
|
|
|
|
|
mutex_unlock(&sink->out_lock); |
|
|
|
|
|
|
|
callmaster_msg_mh_src(cm, &mh); |
|
|
|
stream_msg_mh_src(sink, &mh); |
|
|
|
|
|
|
|
ZERO(iov); |
|
|
|
iov.iov_base = s->s; |
|
|
|
@ -2021,9 +2020,14 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams, |
|
|
|
unsigned int num_ports; |
|
|
|
struct call_monologue *monologue = other_ml->active_dialogue; |
|
|
|
struct endpoint_map *em; |
|
|
|
struct call *call; |
|
|
|
struct callmaster *cm; |
|
|
|
|
|
|
|
call = monologue->call; |
|
|
|
cm = call->callmaster; |
|
|
|
|
|
|
|
monologue->call->last_signal = poller_now; |
|
|
|
monologue->call->deleted = 0; |
|
|
|
call->last_signal = poller_now; |
|
|
|
call->deleted = 0; |
|
|
|
|
|
|
|
/* we must have a complete dialogue, even though the to-tag (monologue->tag) |
|
|
|
* may not be known yet */ |
|
|
|
@ -2033,7 +2037,7 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams, |
|
|
|
} |
|
|
|
__C_DBG("this="STR_FORMAT" other="STR_FORMAT, STR_FMT(&monologue->tag), STR_FMT(&other_ml->tag)); |
|
|
|
|
|
|
|
__tos_change(monologue->call, flags); |
|
|
|
__tos_change(call, flags); |
|
|
|
|
|
|
|
ml_media = other_ml_media = NULL; |
|
|
|
|
|
|
|
@ -2108,15 +2112,24 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams, |
|
|
|
other_media->desired_family = AF_INET; |
|
|
|
if (!IN6_IS_ADDR_V4MAPPED(&sp->rtp_endpoint.ip46)) |
|
|
|
other_media->desired_family = AF_INET6; |
|
|
|
/* for outgoing SDP, use "direction"/DF or default to IPv4 (?) */ |
|
|
|
/* for outgoing SDP, use "direction"/DF or default to what was offered */ |
|
|
|
if (!media->desired_family) |
|
|
|
media->desired_family = AF_INET; |
|
|
|
media->desired_family = other_media->desired_family; |
|
|
|
if (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); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* we now know what's being advertised by the other side */ |
|
|
|
MEDIA_SET(other_media, INITIALIZED); |
|
|
|
|
|
|
|
@ -2273,15 +2286,11 @@ void call_destroy(struct call *c) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef int (*csa_func)(char *o, struct packet_stream *ps, enum stream_address_format format, int *len); |
|
|
|
|
|
|
|
static int call_stream_address4(char *o, struct packet_stream *ps, enum stream_address_format format, int *len) { |
|
|
|
static int call_stream_address4(char *o, struct packet_stream *ps, enum stream_address_format format, |
|
|
|
int *len, struct interface_address *ifa) |
|
|
|
{ |
|
|
|
u_int32_t ip4; |
|
|
|
struct callmaster *m = ps->call->callmaster; |
|
|
|
int l = 0; |
|
|
|
struct interface_address *ifa; |
|
|
|
|
|
|
|
ifa = get_first_interface_address(m, NULL, AF_INET); |
|
|
|
|
|
|
|
if (format == SAF_NG) { |
|
|
|
strcpy(o + l, "IP4 "); |
|
|
|
@ -2301,12 +2310,10 @@ static int call_stream_address4(char *o, struct packet_stream *ps, enum stream_a |
|
|
|
return AF_INET; |
|
|
|
} |
|
|
|
|
|
|
|
static int call_stream_address6(char *o, struct packet_stream *ps, enum stream_address_format format, int *len) { |
|
|
|
struct callmaster *m = ps->call->callmaster; |
|
|
|
static int call_stream_address6(char *o, struct packet_stream *ps, enum stream_address_format format, |
|
|
|
int *len, struct interface_address *ifa) |
|
|
|
{ |
|
|
|
int l = 0; |
|
|
|
struct interface_address *ifa; |
|
|
|
|
|
|
|
ifa = get_first_interface_address(m, NULL, AF_INET6); |
|
|
|
|
|
|
|
if (format == SAF_NG) { |
|
|
|
strcpy(o + l, "IP6 "); |
|
|
|
@ -2326,57 +2333,29 @@ static int call_stream_address6(char *o, struct packet_stream *ps, enum stream_a |
|
|
|
return AF_INET6; |
|
|
|
} |
|
|
|
|
|
|
|
static csa_func __call_stream_address(struct packet_stream *ps, int variant) { |
|
|
|
struct callmaster *m; |
|
|
|
struct packet_stream *sink; |
|
|
|
struct call_media *sink_media; |
|
|
|
csa_func variants[2]; |
|
|
|
struct interface_address *ifa; |
|
|
|
|
|
|
|
assert(variant >= 0); |
|
|
|
assert(variant < G_N_ELEMENTS(variants)); |
|
|
|
int call_stream_address46(char *o, struct packet_stream *ps, enum stream_address_format format, |
|
|
|
int *len, struct interface_address *ifa) |
|
|
|
{ |
|
|
|
struct packet_stream *sink; |
|
|
|
|
|
|
|
m = ps->call->callmaster; |
|
|
|
sink = packet_stream_sink(ps); |
|
|
|
sink_media = sink->media; |
|
|
|
ifa = get_first_interface_address(m, NULL, AF_INET6); |
|
|
|
|
|
|
|
variants[0] = call_stream_address4; |
|
|
|
variants[1] = call_stream_address6; |
|
|
|
|
|
|
|
if (!ifa) { |
|
|
|
variants[1] = NULL; |
|
|
|
goto done; |
|
|
|
} |
|
|
|
if (sink_media->desired_family == AF_INET) |
|
|
|
goto done; |
|
|
|
if (sink_media->desired_family == 0 && IN6_IS_ADDR_V4MAPPED(&sink->endpoint.ip46)) |
|
|
|
goto done; |
|
|
|
if (sink_media->desired_family == 0 && is_addr_unspecified(&sink->advertised_endpoint.ip46)) |
|
|
|
goto done; |
|
|
|
|
|
|
|
variants[0] = call_stream_address6; |
|
|
|
variants[1] = call_stream_address4; |
|
|
|
goto done; |
|
|
|
|
|
|
|
done: |
|
|
|
return variants[variant]; |
|
|
|
if (ifa->family == AF_INET) |
|
|
|
return call_stream_address4(o, sink, format, len, ifa); |
|
|
|
return call_stream_address6(o, sink, format, len, ifa); |
|
|
|
} |
|
|
|
|
|
|
|
int call_stream_address(char *o, struct packet_stream *ps, enum stream_address_format format, int *len) { |
|
|
|
csa_func f; |
|
|
|
struct interface_address *ifa; |
|
|
|
struct call_media *media; |
|
|
|
|
|
|
|
ps = packet_stream_sink(ps); |
|
|
|
f = __call_stream_address(ps, 0); |
|
|
|
return f(o, ps, format, len); |
|
|
|
} |
|
|
|
media = ps->media; |
|
|
|
|
|
|
|
int call_stream_address_alt(char *o, struct packet_stream *ps, enum stream_address_format format, int *len) { |
|
|
|
csa_func f; |
|
|
|
ifa = media->local_address; |
|
|
|
if (!ifa) |
|
|
|
return -1; |
|
|
|
|
|
|
|
ps = packet_stream_sink(ps); |
|
|
|
f = __call_stream_address(ps, 1); |
|
|
|
return f ? f(o, ps, format, len) : -1; |
|
|
|
return call_stream_address46(o, ps, format, len, ifa); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -2820,6 +2799,8 @@ void callmaster_config_init(struct callmaster *m) { |
|
|
|
g_queue_push_tail(&lif->ipv4, ifa); |
|
|
|
else |
|
|
|
g_queue_push_tail(&lif->ipv6, ifa); |
|
|
|
|
|
|
|
sdp_ice_foundation(ifa); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -2833,27 +2814,35 @@ struct local_interface *get_local_interface(struct callmaster *m, str *name) { |
|
|
|
return lif; |
|
|
|
} |
|
|
|
|
|
|
|
struct interface_address *get_first_interface_address(struct callmaster *m, str *name, int family) { |
|
|
|
struct local_interface *lif; |
|
|
|
GQueue *q; |
|
|
|
|
|
|
|
lif = get_local_interface(m, name); |
|
|
|
const GQueue *get_interface_addresses(struct local_interface *lif, int family) { |
|
|
|
if (!lif) |
|
|
|
return NULL; |
|
|
|
|
|
|
|
switch (family) { |
|
|
|
case AF_INET: |
|
|
|
q = &lif->ipv4; |
|
|
|
return &lif->ipv4; |
|
|
|
break; |
|
|
|
case AF_INET6: |
|
|
|
q = &lif->ipv6; |
|
|
|
return &lif->ipv6; |
|
|
|
break; |
|
|
|
default: |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (!q->head) |
|
|
|
return NULL; |
|
|
|
struct interface_address *get_interface_address(struct local_interface *lif, int family) { |
|
|
|
const GQueue *q; |
|
|
|
|
|
|
|
q = get_interface_addresses(lif, family); |
|
|
|
if (!q || !q->head) |
|
|
|
return NULL; |
|
|
|
return q->head->data; |
|
|
|
} |
|
|
|
|
|
|
|
void get_all_interface_addresses(GQueue *q, struct local_interface *lif, int family) { |
|
|
|
g_queue_append(q, get_interface_addresses(lif, family)); |
|
|
|
if (family == AF_INET) |
|
|
|
g_queue_append(q, get_interface_addresses(lif, AF_INET6)); |
|
|
|
else |
|
|
|
g_queue_append(q, get_interface_addresses(lif, AF_INET)); |
|
|
|
} |