From: Ian Jackson Date: Sat, 28 Jun 2014 14:32:19 +0000 (+0100) Subject: site: transport peers: Delete or demote unsuitable peers addresses X-Git-Tag: base.polypath.v3~29 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=secnet.git;a=commitdiff_plain;h=ad4dcae4482c06b92f350f993390712e49a9d693 site: transport peers: Delete or demote unsuitable peers addresses If comm signals that the address is unuseable (ie we have no IPv4 or IPv6 interface or routing), delete the address. Or, if we are mobile, demote it to the end of the list (since we might gain appropriate routing in the future). Signed-off-by: Ian Jackson --- diff --git a/site.c b/site.c index f035e79..4990fe3 100644 --- a/site.c +++ b/site.c @@ -2193,7 +2193,7 @@ static void transport_peers_clear(struct site *st, transport_peers *peers) { static void transport_peers_copy(struct site *st, transport_peers *dst, const transport_peers *src) { dst->npeers=src->npeers; - memcpy(dst->peers, src->peers, sizeof(*dst->peers) * dst->npeers); + COPY_ARRAY(dst->peers, src->peers, dst->npeers); transport_peers_debug(st,dst,"copy", src->npeers, &src->peers->addr, sizeof(*src->peers)); } @@ -2209,15 +2209,63 @@ static void transport_resolve_complete_tardy(struct site *st, transport_record_peer(st,&st->peers,ca_use,"resolved tardily"); } +static void transport_peers__copy_by_mask(transport_peer *out, int *nout_io, + unsigned mask, + const transport_peers *inp) { + /* out and in->peers may be the same region, or nonoverlapping */ + const transport_peer *in=inp->peers; + int slot; + for (slot=0; slotnpeers; slot++) { + if (!(mask & (1U << slot))) + continue; + if (!(out==in && slot==*nout_io)) + COPY_OBJ(out[*nout_io], in[slot]); + (*nout_io)++; + } +} + void transport_xmit(struct site *st, transport_peers *peers, struct buffer_if *buf, bool_t candebug) { int slot; transport_peers_expire(st, peers); + unsigned failed=0; /* bitmask */ + assert(MAX_MOBILE_PEERS_MAX < sizeof(unsigned)*CHAR_BIT); + + int nfailed=0; for (slot=0; slotnpeers; slot++) { transport_peer *peer=&peers->peers[slot]; if (candebug) dump_packet(st, buf, &peer->addr, False); - peer->addr.comm->sendmsg(peer->addr.comm->st, buf, &peer->addr); + bool_t ok = + peer->addr.comm->sendmsg(peer->addr.comm->st, buf, &peer->addr); + if (!ok) { + failed |= 1U << slot; + nfailed++; + } + if (ok && !st->peer_mobile) + break; + } + /* Now we need to demote/delete failing addrs: if we are mobile we + * merely demote them; otherwise we delete them. */ + if (st->local_mobile) { + unsigned expected = ((1U << nfailed)-1) << (peers->npeers-nfailed); + /* `expected' has all the failures at the end already */ + if (failed != expected) { + int fslot=0; + transport_peer failedpeers[nfailed]; + transport_peers__copy_by_mask(failedpeers, &fslot, failed,peers); + assert(fslot == nfailed); + int wslot=0; + transport_peers__copy_by_mask(peers->peers,&wslot,~failed,peers); + assert(wslot+nfailed == peers->npeers); + COPY_ARRAY(peers->peers+wslot, failedpeers, nfailed); + } + } else { + if (failed && peers->npeers > 1) { + int wslot=0; + transport_peers__copy_by_mask(peers->peers,&wslot,~failed,peers); + peers->npeers=wslot; + } } }