mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-25 16:19:07 +02:00
[squash] isInitial and answered can be inferred without state variables
This commit is contained in:
@@ -25,7 +25,6 @@ func (d *Driver) handleOffer(remoteWgKey string, o *OfferMsg) error {
|
|||||||
d.exchanges[remoteWgKey] = &exchangeCtl{
|
d.exchanges[remoteWgKey] = &exchangeCtl{
|
||||||
id: o.ExchangeID,
|
id: o.ExchangeID,
|
||||||
startedAt: time.Now(),
|
startedAt: time.Now(),
|
||||||
isInitial: !d.established[remoteWgKey],
|
|
||||||
}
|
}
|
||||||
d.mu.Unlock()
|
d.mu.Unlock()
|
||||||
|
|
||||||
@@ -51,15 +50,15 @@ func (d *Driver) handleOffer(remoteWgKey string, o *OfferMsg) error {
|
|||||||
// exchange then switches its retransmit payload to the confirm. Stale or duplicate
|
// exchange then switches its retransmit payload to the confirm. Stale or duplicate
|
||||||
// answers are ignored.
|
// answers are ignored.
|
||||||
func (d *Driver) handleAnswer(remoteWgKey string, a *AnswerMsg) error {
|
func (d *Driver) handleAnswer(remoteWgKey string, a *AnswerMsg) error {
|
||||||
// Claim the answer under the lock (set answered) so a concurrent/duplicate answer
|
// Ignore stale answers, answers to a responder-side exchange (cancel == nil), and
|
||||||
// bails before calling the Manager.
|
// duplicates once we are already in the confirm phase. A duplicate that still
|
||||||
|
// slips through is caught by the Manager, whose HandleAnswer bails under its lock.
|
||||||
d.mu.Lock()
|
d.mu.Lock()
|
||||||
ex := d.exchanges[remoteWgKey]
|
ex := d.exchanges[remoteWgKey]
|
||||||
if ex == nil || ex.id != a.ExchangeID || ex.cancel == nil || ex.answered {
|
if ex == nil || ex.id != a.ExchangeID || ex.cancel == nil || isConfirmPhase(ex.lastSent) {
|
||||||
d.mu.Unlock()
|
d.mu.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ex.answered = true
|
|
||||||
d.mu.Unlock()
|
d.mu.Unlock()
|
||||||
|
|
||||||
psk, confirm, err := d.mgr.HandleAnswer(remoteWgKey, a)
|
psk, confirm, err := d.mgr.HandleAnswer(remoteWgKey, a)
|
||||||
@@ -132,10 +131,10 @@ func (d *Driver) initiatorLoop(ctx context.Context, remoteWgKey string, id Excha
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ex.answered {
|
if !isConfirmPhase(ex.lastSent) {
|
||||||
if offerAttempts >= d.maxRetries {
|
if offerAttempts >= d.maxRetries {
|
||||||
delete(d.exchanges, remoteWgKey)
|
delete(d.exchanges, remoteWgKey)
|
||||||
fail := d.registerFailureLocked(remoteWgKey, ex.isInitial)
|
fail := d.registerFailureLocked(remoteWgKey)
|
||||||
d.mu.Unlock()
|
d.mu.Unlock()
|
||||||
d.raiseFailure(remoteWgKey, fail)
|
d.raiseFailure(remoteWgKey, fail)
|
||||||
return
|
return
|
||||||
@@ -161,11 +160,12 @@ func (d *Driver) initiatorLoop(ctx context.Context, remoteWgKey string, id Excha
|
|||||||
}
|
}
|
||||||
|
|
||||||
// registerFailureLocked applies policy B and reports whether OnRekeyFailed is due:
|
// registerFailureLocked applies policy B and reports whether OnRekeyFailed is due:
|
||||||
// the initial exchange fails immediately; a rekey tolerates up to maxRekeyFailures
|
// an initial exchange (peer never established) fails immediately; a rekey tolerates
|
||||||
// consecutive misses (we stay on the still-valid previous PSK) before failing.
|
// up to maxRekeyFailures consecutive misses (we stay on the still-valid previous
|
||||||
|
// PSK) before failing. Whether it is initial is read live from established.
|
||||||
// Assumes d.mu is held.
|
// Assumes d.mu is held.
|
||||||
func (d *Driver) registerFailureLocked(remoteWgKey string, isInitial bool) bool {
|
func (d *Driver) registerFailureLocked(remoteWgKey string) bool {
|
||||||
if isInitial {
|
if !d.established[remoteWgKey] {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
d.failures[remoteWgKey]++
|
d.failures[remoteWgKey]++
|
||||||
@@ -176,6 +176,12 @@ func (d *Driver) registerFailureLocked(remoteWgKey string, isInitial bool) bool
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isConfirmPhase reports whether the initiator's outstanding message is the confirm
|
||||||
|
// (as opposed to the offer), derived from the message's type byte.
|
||||||
|
func isConfirmPhase(lastSent []byte) bool {
|
||||||
|
return len(lastSent) > 0 && lastSent[0] == byte(MsgConfirm)
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Driver) raiseFailure(remoteWgKey string, fail bool) {
|
func (d *Driver) raiseFailure(remoteWgKey string, fail bool) {
|
||||||
if !fail {
|
if !fail {
|
||||||
d.logger.Warn("pqkem rekey attempt timed out, will retry next cycle", "peer", remoteWgKey)
|
d.logger.Warn("pqkem rekey attempt timed out, will retry next cycle", "peer", remoteWgKey)
|
||||||
|
|||||||
@@ -35,17 +35,17 @@ type Transport interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// exchangeCtl tracks one in-flight exchange for a peer. A single lastSent holds the
|
// exchangeCtl tracks one in-flight exchange for a peer. A single lastSent holds the
|
||||||
// message currently being (re)transmitted: for the initiator it is the offer and
|
// message currently being (re)transmitted: for the initiator the offer and then,
|
||||||
// then, once answered, the confirm; for the responder it is the answer, resent on a
|
// once answered, the confirm; for the responder the answer, resent on a duplicate
|
||||||
// duplicate offer. Only the initiator runs a retransmit loop (cancel != nil); the
|
// offer. Its type byte (lastSent[0]) also encodes the initiator's phase, so no
|
||||||
// responder is purely reactive.
|
// separate "answered" flag is kept. Only the initiator runs a retransmit loop
|
||||||
|
// (cancel != nil); the responder is purely reactive. Whether an exchange is the
|
||||||
|
// peer's first is read live from d.established, not snapshotted here.
|
||||||
type exchangeCtl struct {
|
type exchangeCtl struct {
|
||||||
id ExchangeID
|
id ExchangeID
|
||||||
startedAt time.Time
|
startedAt time.Time
|
||||||
isInitial bool
|
|
||||||
lastSent []byte
|
lastSent []byte
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
answered bool // initiator: the answer arrived; retransmit phase is now the confirm
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Driver ties the pure Manager to the outside world: per-peer rekey timer, inbound
|
// Driver ties the pure Manager to the outside world: per-peer rekey timer, inbound
|
||||||
@@ -186,7 +186,6 @@ func (d *Driver) initiateRekey(remoteWgKey string) error {
|
|||||||
d.exchanges[remoteWgKey] = &exchangeCtl{
|
d.exchanges[remoteWgKey] = &exchangeCtl{
|
||||||
id: offer.ExchangeID,
|
id: offer.ExchangeID,
|
||||||
startedAt: time.Now(),
|
startedAt: time.Now(),
|
||||||
isInitial: !d.established[remoteWgKey],
|
|
||||||
lastSent: raw,
|
lastSent: raw,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user