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.v1~29 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=secnet.git;a=commitdiff_plain;h=15efc8b65dfe32c10b2bbb93769973f1191ea815 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 1572a29..2012c4a 100644 --- a/site.c +++ b/site.c @@ -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)) + memcpy(&out[*nout_io], &in[slot], sizeof(out[0])); + (*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); + memcpy(peers->peers+wslot,failedpeers,sizeof(failedpeers)); + } + } else { + if (failed && peers->npeers > 1) { + int wslot=0; + transport_peers__copy_by_mask(peers->peers,&wslot,~failed,peers); + peers->npeers=wslot; + } } }