Skip to content

Commit ae4a3f4

Browse files
committed
Handle duplicated Flight 4
1 parent 22a0632 commit ae4a3f4

2 files changed

Lines changed: 54 additions & 1 deletion

File tree

internal/handshake/fsm13.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
dtlsflight "github.com/pion/dtls/v3/internal/flight"
1313
dtlsflight13 "github.com/pion/dtls/v3/internal/flight/flight13"
1414
dtlsstate "github.com/pion/dtls/v3/internal/state"
15+
"github.com/pion/dtls/v3/pkg/protocol"
1516
"github.com/pion/dtls/v3/pkg/protocol/alert"
1617
"github.com/pion/dtls/v3/pkg/protocol/handshake"
1718
)
@@ -347,7 +348,7 @@ func (s *fsm13) finish(ctx context.Context, conn Conn) (State, error) {
347348
return StateFinished, nil
348349
}
349350

350-
func (s *fsm13) handleReceivedFlight(
351+
func (s *fsm13) handleReceivedFlight( //nolint:cyclop
351352
ctx context.Context,
352353
conn Conn,
353354
received RecvHandshakeState,
@@ -362,6 +363,9 @@ func (s *fsm13) handleReceivedFlight(
362363
if !received.HasHandshake && len(received.ACKs) != 0 {
363364
return s.transitionAfterACK(ackResult, false), nil
364365
}
366+
if received.HasHandshake && received.IsRetransmit && s.currentFlight.IsLastSendFlight() {
367+
return s.handlePreviousFlightRetransmit(ctx, conn, received.RecordsToACK, ackResult)
368+
}
365369

366370
nextFlight, err := s.parseReceivedFlight(ctx, conn, s.currentFlight)
367371
if err != nil {
@@ -386,6 +390,23 @@ func (s *fsm13) handleReceivedFlight(
386390
return transition, nil
387391
}
388392

393+
func (s *fsm13) handlePreviousFlightRetransmit(
394+
ctx context.Context,
395+
conn Conn,
396+
recordsToACK []protocol.RecordNumber,
397+
ackResult ACKResult,
398+
) (receivedFlightTransition, error) {
399+
// A duplicate peer flight means it didn't receive our response.
400+
// ACK the duplicate and retransmit the pending final flight.
401+
// check WAIT exit 3:
402+
// https://datatracker.ietf.org/doc/html/rfc9147#section-5.8.1
403+
if err := sendACK(ctx, conn, s.state.LocalEpoch(), recordsToACK); err != nil {
404+
return receivedFlightTransition{}, err
405+
}
406+
407+
return s.transitionAfterACK(ackResult, true), nil
408+
}
409+
389410
func (s *fsm13) prepareFlightACKTracking(flights []*dtlsflight.Packet, retransmit bool) {
390411
s.flightACK.reset()
391412
if retransmit {

internal/handshake/fsm_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,38 @@ func TestHandshakeFSM13ClientFlight5GeneratesFinished(t *testing.T) {
894894
assert.Equal(t, dtlsflight13.EpochHandshake, conn.localEpoch)
895895
}
896896

897+
func TestHandshakeFSM13ClientFlight5HandlesPreviousFlightRetransmit(t *testing.T) {
898+
fixture := newNoHRRFlight13Fixture(t)
899+
fsm := clientFSMThroughServerFlight13(t, fixture)
900+
conn := &flightTestConn{}
901+
nextState, err := fsm.prepare(context.Background(), conn)
902+
require.NoError(t, err)
903+
require.Equal(t, StateSending, nextState)
904+
require.Equal(t, dtlsflight13.Flight5, fsm.currentFlight)
905+
906+
fixture.clientState.SetLocalEpoch(dtlsflight13.EpochHandshake)
907+
record := protocol.RecordNumber{Epoch: uint64(dtlsflight13.EpochHandshake), SequenceNumber: 11}
908+
retransmit := RecvHandshakeState{
909+
Done: make(chan struct{}),
910+
HasHandshake: true,
911+
IsRetransmit: true,
912+
RecordsToACK: []protocol.RecordNumber{record},
913+
}
914+
transition, err := fsm.handleReceivedFlight(context.Background(), conn, retransmit)
915+
require.NoError(t, err)
916+
assert.Equal(t, StateSending, transition.state)
917+
assert.Equal(t, dtlsflight13.Flight5, fsm.currentFlight)
918+
require.Len(t, conn.writtenPackets, 1)
919+
ackPacket := conn.writtenPackets[0]
920+
assert.True(t, ackPacket.ShouldEncrypt)
921+
assert.Equal(t, dtlsflight13.EpochHandshake, ackPacket.Record.Header.Epoch)
922+
ack, ok := ackPacket.Record.Content.(*protocol.ACK)
923+
require.True(t, ok)
924+
assert.Equal(t, []protocol.RecordNumber{record}, ack.Records)
925+
fsm.received.release()
926+
assertFlight13RecvDoneClosed(t, retransmit)
927+
}
928+
897929
func TestHandshakeFSM13SendErrorReleasesReader(t *testing.T) {
898930
tests := []struct {
899931
name string

0 commit comments

Comments
 (0)