I might have finally figured out the packet flow for the most flexibility and utility.
- Packet arrives on interface
- Is queued by libpcap
- Thread grabs packet off of pcap queue
- IF the packet is NOT the packet we are expecting next (seg.sequence != rcv.nxt)
- Throw it into a list used by the thread.
- Go back up one level
- ELSE the packet is one we were expecting
- Add the packet to the State Machine's recv() queue, IF there is not already a packet with the same sequence number
- IF processing is enabled
- Process the packet (i.e. "Segment Arrives" stuff)
- Advance the 'processed packet' index, which points to the last packet in the recv() queue that has been processed.
- Iterate over all packets in the thread's personal queue. This is done because we might have already received the 'next' packet, but it was received out-of-order.
Okay, so now the packets are being added to a queue, and they are in the correct order. They are also conditionally processed/handled/whatever you want to call it.
Now, we are writing a test. We want to stop when  A certain packet is received or  A specific state change occurs. This means that two methods need to be hooked into: the state-change method, and the packet-handling method. With the state change, we will want to pass control to the user (i.e. disable auto-processing) AFTER the state transition. With the packet-recv stuff, we want to do it BEFORE the packet is processed. This means that there needs to be a step between '5.1' and '5.2' that checks to see if the packet is flagged, and appropriately disables processing when the packet is encountered.
The test-writer then can call the 'recv()' method and be guaranteed to get the next packet, in the proper order. Additionally, the test-writer can set "break points" that disable auto-processing. This is important, because auto-processing can lead to sending out additional packets (i.e. response to a SYN-ACK, response to a FIN packet, etc.) that may need to be omitted for a test to be successful.