Skip to content

Commit bde06f1

Browse files
committed
begin adding test for #19
1 parent 8b6dcdb commit bde06f1

File tree

3 files changed

+45
-3
lines changed

3 files changed

+45
-3
lines changed

control_user.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ func (tcb *ControlBlock) Close() (err error) {
8787
tcb.pending[0] = (tcb.pending[0] & FlagACK) | FlagFIN
8888
case StateFinWait2, StateTimeWait:
8989
err = errConnectionClosing
90+
default:
91+
err = errInvalidState
9092
}
9193
if err == nil {
9294
tcb.trace("tcb:close", slog.String("state", tcb.state.String()))
@@ -134,7 +136,8 @@ func (tcb *ControlBlock) Send(seg Segment) error {
134136
// Advance pending flags queue.
135137
tcb.pending[0] &^= seg.Flags
136138
if tcb.pending[0] == 0 {
137-
tcb.pending = [2]Flags{tcb.pending[1], 0}
139+
// Ensure we don't queue a FINACK if we have already sent a FIN.
140+
tcb.pending = [2]Flags{tcb.pending[1] &^ (seg.Flags & (FlagFIN)), 0}
138141
}
139142
tcb.pending[0] |= newPending
140143

@@ -183,6 +186,11 @@ func (tcb *ControlBlock) Recv(seg Segment) (err error) {
183186
if seg.Flags.HasAny(FlagACK) {
184187
tcb.close()
185188
}
189+
// case StateClosing:
190+
// if seg.Flags.HasAny(FlagACK) {
191+
// tcb.state = StateTimeWait
192+
// pending = FlagACK
193+
// }
186194
default:
187195
panic("unexpected state" + tcb.state.String())
188196
}

seqs_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,3 +667,37 @@ var exchangeHelloWorld = [][]byte{
667667
// server ACK
668668
11: []byte("\xd8\x5e\xd3\x43\x03\xeb\x28\xcd\xc1\x05\x4d\xbb\x08\x00\x45\x00\x00\x28\x00\x00\x40\x00\x40\x06\xb6\x5b\xc0\xa8\x01\x91\xc0\xa8\x01\x93\x04\xd2\x84\x96\xbe\x6e\x4c\x28\x5e\x72\x2b\x97\x50\x10\x10\x00\xfd\x56\x00\x00\x00\x00\x00\x00\x00\x00"),
669669
}
670+
671+
func TestUnexpectedStateClosing(t *testing.T) {
672+
// TCB is a server which returns an HTTP response and receives a FINACK.
673+
var tcb seqs.ControlBlock
674+
const httpLen = 1192
675+
const issA, issB, windowA, windowB = 1, 127, 2000, 2000
676+
tcb.HelperInitState(seqs.StateEstablished, issA, issA, windowA)
677+
tcb.HelperInitRcv(issB, issB, windowB)
678+
679+
ex := []seqs.Exchange{
680+
0: { // Server sends HTTP response.
681+
Outgoing: &seqs.Segment{SEQ: issA, ACK: issB, Flags: PSHACK, WND: windowA, DATALEN: httpLen},
682+
WantState: seqs.StateEstablished,
683+
},
684+
1: { // Client sends an ACK to server.
685+
Incoming: &seqs.Segment{SEQ: issB, ACK: issA + httpLen, Flags: seqs.FlagACK, WND: windowB},
686+
WantState: seqs.StateEstablished,
687+
},
688+
2: { // Client sends FIN|ACK to server.
689+
Incoming: &seqs.Segment{SEQ: issB, ACK: issA + httpLen, Flags: FINACK, WND: windowB},
690+
WantPending: &seqs.Segment{SEQ: issA + httpLen, ACK: issB + 1, Flags: seqs.FlagACK, WND: windowA},
691+
WantState: seqs.StateCloseWait,
692+
},
693+
3: { // Server sends out FINACK.
694+
Outgoing: &seqs.Segment{SEQ: issA + httpLen, ACK: issB + 1, Flags: FINACK, WND: windowA},
695+
WantState: seqs.StateLastAck,
696+
},
697+
4: { // Client sends back ACK.
698+
Incoming: &seqs.Segment{SEQ: issB + 1, ACK: issA + httpLen + 1, Flags: seqs.FlagACK, WND: windowB},
699+
WantState: seqs.StateClosed,
700+
},
701+
}
702+
tcb.HelperExchange(t, ex[:])
703+
}

seqsinternal_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,15 +193,15 @@ func (ex *Exchange) appendVisualization(buf []byte, A, B State) []byte {
193193
}
194194
var seg *Segment
195195
sentByA := ex.Outgoing != nil
196-
if ex.Outgoing != nil {
196+
if sentByA {
197197
seg = ex.Outgoing
198198
} else if ex.Incoming != nil {
199199
seg = ex.Incoming
200200
} else {
201201
return buf
202202
}
203203
dirSep := []byte(" <-- ")
204-
if !sentByA {
204+
if sentByA {
205205
dirSep = []byte(" --> ")
206206
}
207207
astr := A.String()

0 commit comments

Comments
 (0)