## TCP Teardown Analysis (Client 192.168.1.17 ↔ Radio 192.168.1.14)

### Summary
The TCP teardown sequence is functioning correctly at the protocol level. The connection failure is caused by the client aborting a valid half-closed connection after receiving additional data from the radio.

---

### Observed Packet Flow

1. **Client initiates close**
   - `9442`: Client → Radio `[FIN, ACK] Seq=3427 Ack=50034`
   - Client correctly signals end of its transmit stream

2. **Client retransmits FIN (normal behavior)**
   - `9456`: `[TCP Retransmission] [FIN, ACK] Seq=3427`
   - Indicates FIN ACK was not yet received (normal TCP behavior)

3. **Radio acknowledges FIN**
   - `9457`: Radio → Client `[ACK] Ack=3428`
   - Correctly acknowledges FIN (`3427 + 1`)

4. **Radio sends additional data (valid TCP behavior)**
   - `9615`: Radio → Client `[PSH, ACK] Seq=50034 Ack=3428 Len=95`
   - This is expected: radio is in **CLOSE-WAIT** and may continue sending remaining data

5. **Client aborts connection**
   - `9616`: Client → Radio `[RST] Seq=3428`
   - Client immediately resets connection instead of accepting data

---

### Key Findings

- The FIN/ACK exchange is **correct and complete**
- The radio behaves correctly by:
  - ACKing the FIN
  - Continuing to send remaining data (valid TCP CLOSE-WAIT behavior)
- The client **incorrectly resets the connection** upon receiving this data

---

### Root Cause

The issue is **client-side socket/application behavior**, not a TCP protocol issue.

The client appears to:
- Treat the connection as fully closed immediately after sending FIN
- Reject valid incoming data
- Abort the connection via RST

---

### Likely Causes in Client Code

- Socket is fully closed (`close()`) instead of half-closed (`shutdown(SHUT_WR)`)
- Use of abortive close (e.g., `SO_LINGER = 0`)
- Application assumes no data will arrive after sending FIN
- Incorrect state handling of TCP half-close (FIN-WAIT-2)

---

### Expected Behavior

After sending FIN and receiving ACK:
- Client enters **FIN-WAIT-2**
- Client must continue to **receive data** until the peer sends its FIN
- Only then should the connection fully close

---

### Recommended Fix Direction

- Ensure client uses **half-close semantics** (`shutdown(SHUT_WR)` instead of immediate `close()`)
- Do not treat incoming data after FIN as invalid
- Avoid triggering RST on valid post-FIN data
- Verify socket options (especially `SO_LINGER`) are not forcing abortive close

---

### Conclusion

This is not a TCP teardown bug.
It is a **client-side socket lifecycle/state management issue**, specifically improper handling of the half-closed connection state.
