make multi-homing thread safe

pull/26/head
Richard Fuchs 11 years ago
parent e830bf57eb
commit af9625de74

@ -403,7 +403,7 @@ void kernelize(struct packet_stream *stream) {
mpt.src_addr.family = mpt.dst_addr.family; mpt.src_addr.family = mpt.dst_addr.family;
mpt.src_addr.port = sink->sfd->fd.localport; mpt.src_addr.port = sink->sfd->fd.localport;
ifa = sink->media->local_address; ifa = g_atomic_pointer_get(&sink->media->local_address);
if (mpt.src_addr.family == AF_INET) if (mpt.src_addr.family == AF_INET)
mpt.src_addr.u.ipv4 = in6_to_4(&ifa->addr); mpt.src_addr.u.ipv4 = in6_to_4(&ifa->addr);
else else
@ -542,7 +542,7 @@ void stream_msg_mh_src(struct packet_stream *ps, struct msghdr *mh) {
sin6 = mh->msg_name; sin6 = mh->msg_name;
ifa = ps->media->local_address; ifa = g_atomic_pointer_get(&ps->media->local_address);
ch = CMSG_FIRSTHDR(mh); ch = CMSG_FIRSTHDR(mh);
ZERO(*ch); ZERO(*ch);
@ -590,6 +590,7 @@ static int stream_packet(struct stream_fd *sfd, str *s, struct sockaddr_in6 *fsi
char addr[64]; char addr[64];
struct endpoint endpoint; struct endpoint endpoint;
rewrite_func rwf_in, rwf_out; rewrite_func rwf_in, rwf_out;
struct interface_address *loc_addr;
call = sfd->call; call = sfd->call;
cm = call->callmaster; cm = call->callmaster;
@ -771,7 +772,8 @@ update_addr:
/* check the destination address of the received packet against what we think our /* check the destination address of the received packet against what we think our
* local interface to use is */ * local interface to use is */
if (dst && memcmp(dst, &media->local_address->addr, sizeof(*dst))) { loc_addr = g_atomic_pointer_get(&media->local_address);
if (dst && memcmp(dst, &loc_addr->addr, sizeof(*dst))) {
struct interface_address *ifa; struct interface_address *ifa;
char ifa_buf[64]; char ifa_buf[64];
smart_ntop(ifa_buf, dst, sizeof(ifa_buf)); smart_ntop(ifa_buf, dst, sizeof(ifa_buf));
@ -780,9 +782,10 @@ update_addr:
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);
goto drop; goto drop;
} }
ilog(LOG_INFO, "Switching local interface to %s", ifa_buf); if (g_atomic_pointer_compare_and_exchange(&media->local_address, loc_addr, ifa)) {
media->local_address = ifa; ilog(LOG_INFO, "Switching local interface to %s", ifa_buf);
update = 1; update = 1;
}
} }
@ -2042,7 +2045,11 @@ static void __tos_change(struct call *call, const struct sdp_ng_flags *flags) {
} }
static void __init_interface(struct call_media *media, const str *ifname) { static void __init_interface(struct call_media *media, const str *ifname) {
if (!media->interface || !media->local_address) /* we're holding master_lock in W mode here, so we can safely ignore the
* atomic ops */
struct interface_address *ifa = (void *) media->local_address;
if (!media->interface || !ifa)
goto get; goto get;
if (!ifname || !ifname->s) if (!ifname || !ifname->s)
return; return;
@ -2060,12 +2067,12 @@ get:
else else
ilog(LOG_WARNING, "Interface '"STR_FORMAT"' not found, using default", STR_FMT(ifname)); ilog(LOG_WARNING, "Interface '"STR_FORMAT"' not found, using default", STR_FMT(ifname));
} }
media->local_address = get_interface_address(media->interface, media->desired_family); media->local_address = ifa = get_interface_address(media->interface, media->desired_family);
if (!media->local_address) { if (!ifa) {
ilog(LOG_WARNING, "No usable address in interface '"STR_FORMAT"' found, using default", ilog(LOG_WARNING, "No usable address in interface '"STR_FORMAT"' found, using default",
STR_FMT(ifname)); STR_FMT(ifname));
media->local_address = get_any_interface_address(media->interface, media->desired_family); media->local_address = ifa = get_any_interface_address(media->interface, media->desired_family);
media->desired_family = family_from_address(&media->local_address->addr); media->desired_family = family_from_address(&ifa->addr);
} }
} }
@ -2400,7 +2407,7 @@ int call_stream_address(char *o, struct packet_stream *ps, enum stream_address_f
media = ps->media; media = ps->media;
ifa = media->local_address; ifa = g_atomic_pointer_get(&media->local_address);
if (!ifa) if (!ifa)
return -1; return -1;

@ -269,7 +269,11 @@ struct call_media {
const struct transport_protocol *protocol; const struct transport_protocol *protocol;
int desired_family; int desired_family;
struct local_interface *interface; struct local_interface *interface;
struct interface_address *local_address;
/* local_address is protected by call->master_lock in W mode, but may
* still be modified if the lock is held in R mode, therefore we use
* atomic ops to access it when holding an R lock. */
volatile struct interface_address *local_address;
str ice_ufrag; str ice_ufrag;
str ice_pwd; str ice_pwd;

Loading…
Cancel
Save