ames: fix lane discovery during some lane changes

We used to not accept new indirect lanes if we already have a direct
lane.  This means that if Bob, with a publicly-accessible lane, changes
lanes (eg by restarting the process and getting a new port or changing
ip addresses), tries to talk to Alice, who is behind a NAT, then Bob
will try directly but fail (because Alice is behind a NAT), so he will
route the message through her galaxy.  This is good -- the message gets
to Alice.  However, Alice had a direct route to Bob's old lane, so she
will try to ack on that lane, which fails.  She will not time out this
lane because she doesn't know that Bob isn't getting the acks (acks
don't have their own acks).

The solution is that if Alice receives an indirect lane for Bob when she
already has a direct lane, she shouldn't ignore it.  If the lane is the
same as what she has, she shouldn't change anything (in particular, she
shouldn't mark it as indirect).  But if it's a new lane, she should
discard her old direct lane and use the new indirect lane.
This commit is contained in:
Philip Monk 2020-07-24 20:41:48 -07:00
parent c96705e755
commit 1d0409c4c4
No known key found for this signature in database
GPG Key ID: B66E1F02604E44EC

View File

@ -1121,17 +1121,32 @@
?> =(rcvr-life.shut-packet our-life.channel)
:: non-galaxy: update route with heard lane or forwarded lane
::
=? route.peer-state
?: =(%czar (clan:title her.channel))
%.n
=/ is-old-direct=? ?=([~ %& *] route.peer-state)
=/ is-new-direct=? ?=(~ origin.packet)
:: old direct takes precedence over new indirect
::
|(is-new-direct !is-old-direct)
=? route.peer-state !=(%czar (clan:title her.channel))
:: if new packet is direct, use that. otherwise, if the new new
:: and old lanes are indirect, use the new one. if the new lane
:: is indirect but the old lane is direct, then if the lanes are
:: identical, don't mark it indirect; if they're not identical,
:: use the new lane and mark it indirect.
::
?~ origin.packet
:: if you mark lane as indirect because you got an indirect
:: packet even though you already had a direct identical lane,
:: then delayed forwarded packets will come later and reset to
:: indirect, so you're unlikely to get a stable direct route
:: (unless the forwarder goes offline for a while).
::
:: conversely, if you don't accept indirect routes with different
:: lanes, then if your lane is stale and they're trying to talk
:: to you, your acks will go to the stale lane, and you'll never
:: time it out unless you reach out to them. this manifests as
:: needing to |hi or dotpost to get a response when the other
:: ship has changed lanes.
::
?: ?=(~ origin.packet)
`[direct=%.y lane]
?: ?=([~ %& *] route.peer-state)
?: =(lane.u.route.peer-state u.origin.packet)
route.peer-state
`[direct=%.n u.origin.packet]
`[direct=%.n u.origin.packet]
:: perform peer-specific handling of packet
::