Skip to content

Commit

Permalink
add fig13 test
Browse files Browse the repository at this point in the history
  • Loading branch information
soypat committed Nov 14, 2023
1 parent 2450db4 commit b038732
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 2 deletions.
6 changes: 4 additions & 2 deletions control.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,11 @@ func (tcb *ControlBlock) rcvFinWait1(seg Segment) (pending Flags, err error) {
if !flags.HasAny(FlagACK) {
return 0, errors.New("rcvFinWait1: expected ACK")
} else if flags.HasAny(FlagFIN) {
tcb.debuglog += "got fin in finwait1\n"
tcb.state = StateClosing // Simultaneous close. See figure 13 of RFC 9293.
} else {
tcb.state = StateFinWait2
}
tcb.state = StateFinWait2

return FlagACK, nil
}

Expand Down
4 changes: 4 additions & 0 deletions control_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ func (tcb *ControlBlock) Send(seg Segment) error {
hasFIN := seg.Flags.HasAny(FlagFIN)
hasACK := seg.Flags.HasAny(FlagACK)
switch tcb.state {
case StateClosing:
if hasACK {
tcb.state = StateTimeWait
}
case StateEstablished:
if hasFIN {
tcb.state = StateFinWait1
Expand Down
4 changes: 4 additions & 0 deletions internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
// Here we define internal testing helpers that may be used in any *_test.go file
// but are not exported.

// Exchange represents a single exchange of segments.
type Exchange struct {
Outgoing *Segment
Incoming *Segment
Expand All @@ -25,6 +26,9 @@ func (tcb *ControlBlock) HelperExchange(t *testing.T, exchange []Exchange) {
t.Helper()
const pfx = "exchange"
for i, ex := range exchange {
if ex.Outgoing != nil && ex.Incoming != nil {
t.Fatalf(pfx+"[%d] cannot send and receive in the same exchange, please split into two exchanges.", i)
}
if ex.Outgoing != nil {
err := tcb.Send(*ex.Outgoing)
if err != nil {
Expand Down
44 changes: 44 additions & 0 deletions seqs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,50 @@ func TestExchange_rfc9293_figure12(t *testing.T) {
tcbB.HelperExchange(t, exchangeB)
}

/*
Figure 12: Simultaneous Close Sequence
TCP Peer A TCP Peer B
1. ESTABLISHED ESTABLISHED
2. (Close) (Close)
FIN-WAIT-1 --> <SEQ=100><ACK=300><CTL=FIN,ACK> ... FIN-WAIT-1
<-- <SEQ=300><ACK=100><CTL=FIN,ACK> <--
... <SEQ=100><ACK=300><CTL=FIN,ACK> -->
3. CLOSING --> <SEQ=101><ACK=301><CTL=ACK> ... CLOSING
<-- <SEQ=301><ACK=101><CTL=ACK> <--
... <SEQ=101><ACK=301><CTL=ACK> -->
4. TIME-WAIT TIME-WAIT
(2 MSL) (2 MSL)
CLOSED CLOSED
*/
func TestExchange_rfc9293_figure13(t *testing.T) {
const issA, issB, windowA, windowB = 100, 300, 1000, 1000
exchangeA := []seqs.Exchange{
0: { // A sends FIN|ACK to B to begin closing connection.
Outgoing: &seqs.Segment{SEQ: issA, ACK: issB, Flags: FINACK, WND: windowA},
WantState: seqs.StateFinWait1,
},
1: { // A receives FIN|ACK from B, who sent packet before receiving A's FINACK.
Incoming: &seqs.Segment{SEQ: issB, ACK: issA, Flags: FINACK, WND: windowB},
WantState: seqs.StateClosing,
WantPending: &seqs.Segment{SEQ: issA + 1, ACK: issB + 1, Flags: seqs.FlagACK, WND: windowA},
},
2: { // A sends ACK to B.
Outgoing: &seqs.Segment{SEQ: issA + 1, ACK: issB + 1, Flags: seqs.FlagACK, WND: windowA},
WantState: seqs.StateTimeWait,
},
}
var tcbA seqs.ControlBlock
tcbA.HelperInitState(seqs.StateEstablished, issA, issA, windowA)
tcbA.HelperInitRcv(issB, issB, windowB)
tcbA.HelperExchange(t, exchangeA)

// No need to test B since exchange is completely symmetric.
}

func TestExchange_helloworld_client(t *testing.T) {
// Client Transmission Control Block.
var tcb seqs.ControlBlock
Expand Down

0 comments on commit b038732

Please sign in to comment.