static void contract_and_expand(const char *data, size_t s_window, uint32_t base, size_t s_pcodes) { struct diag_vcdiff_script *script; struct diag_rollinghash32 *rh; size_t size, s; uint8_t *result; char *result0; size = strlen(data); rh = (struct diag_rollinghash32 *)diag_rollinghash32_new_rabin_karp((const uint8_t *)data, size, s_window, base); ASSERT_NOT_NULL(rh); script = diag_vcdiff_contract(rh); ASSERT_NOT_NULL(script); dump_pcodes(script); ASSERT_EQ_UINT(s_pcodes, script->s_pcodes); result = diag_vcdiff_expand(script, &s); ASSERT_EQ_UINT(size, s); result0 = diag_malloc(s + 1); (void)memcpy(result0, result, s); result0[s] = '\0'; ASSERT_EQ_STRING(data, result0); diag_free(result0); diag_free(result); diag_vcdiff_script_destroy(script); diag_rollinghash32_destroy(rh); }
// ------------------------------------------------------------------------------------------------ static void TestCaseEnd() { ASSERT_TRUE(ListIsEmpty(&s_outPackets)); ASSERT_TRUE(ListIsEmpty(&g_tcpActiveConns)); ASSERT_EQ_INT(g_netBufAllocCount, 0); ASSERT_EQ_UINT(outError, 0); }
// ------------------------------------------------------------------------------------------------ static void ValidateChecksum(Packet *pkt) { u8 *phdrData = (u8 *)&pkt->phdr; u8 *phdrEnd = phdrData + sizeof(ChecksumHeader); uint sum = 0; sum = NetChecksumAcc(phdrData, phdrEnd, sum); sum = NetChecksumAcc(pkt->data, pkt->end, sum); u16 checksum = NetChecksumFinal(sum); ASSERT_EQ_UINT(checksum, 0); }
static void OnError(TcpConn *conn, uint error) { ASSERT_EQ_UINT(outError, 0); outError = error; }
// ------------------------------------------------------------------------------------------------ int main(int argc, const char **argv) { // Common variables NetBuf *inPkt; TcpHeader *inHdr; Packet *outPkt; TcpHeader *outHdr; TcpConn *conn; TestSetup(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_CLOSED, "RST", "segment dropped"); inPkt = NetAllocBuf(); inHdr = (TcpHeader *)inPkt->start; inHdr->srcPort = 100; inHdr->dstPort = 101; inHdr->seq = 1; inHdr->ack = 2; inHdr->off = 5 << 4; inHdr->flags = TCP_RST; inHdr->windowSize = TCP_WINDOW_SIZE; inHdr->checksum = 0; inHdr->urgent = 0; TcpInput(inPkt); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_CLOSED, "ACK", "RST sent"); inPkt = NetAllocBuf(); inHdr = (TcpHeader *)inPkt->start; inHdr->srcPort = 100; inHdr->dstPort = 101; inHdr->seq = 1; inHdr->ack = 2; inHdr->off = 5 << 4; inHdr->flags = TCP_ACK; inHdr->windowSize = TCP_WINDOW_SIZE; inHdr->checksum = 0; inHdr->urgent = 0; TcpInput(inPkt); outPkt = PopPacket(); outHdr = (TcpHeader *)outPkt->data; TcpSwap(outHdr); ASSERT_EQ_UINT(outHdr->srcPort, 101); ASSERT_EQ_UINT(outHdr->dstPort, 100); ASSERT_EQ_UINT(outHdr->seq, 2); ASSERT_EQ_UINT(outHdr->ack, 0); ASSERT_EQ_HEX8(outHdr->flags, TCP_RST); free(outPkt); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_CLOSED, "no ACK", "RST/ACK sent"); inPkt = NetAllocBuf(); inHdr = (TcpHeader *)inPkt->start; inHdr->srcPort = 100; inHdr->dstPort = 101; inHdr->seq = 1; inHdr->ack = 2; inHdr->off = 5 << 4; inHdr->flags = 0; inHdr->windowSize = TCP_WINDOW_SIZE; inHdr->checksum = 0; inHdr->urgent = 0; TcpInput(inPkt); outPkt = PopPacket(); outHdr = (TcpHeader *)outPkt->data; TcpSwap(outHdr); ASSERT_EQ_UINT(outHdr->srcPort, 101); ASSERT_EQ_UINT(outHdr->dstPort, 100); ASSERT_EQ_UINT(outHdr->seq, 0); ASSERT_EQ_UINT(outHdr->ack, 1); ASSERT_EQ_HEX8(outHdr->flags, TCP_RST | TCP_ACK); free(outPkt); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_CLOSED, "connect", "goto SYN_SENT"); conn = CreateConn(); ASSERT_TRUE(TcpConnect(conn, &s_ipAddr, 80)); outPkt = PopPacket(); outHdr = (TcpHeader *)outPkt->data; TcpSwap(outHdr); ASSERT_TRUE(outHdr->srcPort >= 49152); ASSERT_EQ_UINT(outHdr->dstPort, 80); ASSERT_EQ_UINT(outHdr->seq, conn->iss); ASSERT_EQ_UINT(outHdr->ack, 0); ASSERT_EQ_HEX8(outHdr->flags, TCP_SYN); ASSERT_EQ_UINT(outHdr->windowSize, TCP_WINDOW_SIZE); ASSERT_EQ_UINT(outHdr->urgent, 0); free(outPkt); ExitState(conn, TCP_SYN_SENT); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_SYN_SENT, "Bad ACK, no RST", "RST sent"); conn = CreateConn(); EnterState(conn, TCP_SYN_SENT); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, 1000, conn->iss, TCP_ACK); TcpInput(inPkt); outPkt = PopPacket(); outHdr = (TcpHeader *)outPkt->data; TcpSwap(outHdr); ASSERT_EQ_UINT(outHdr->srcPort, conn->localPort); ASSERT_EQ_UINT(outHdr->dstPort, conn->remotePort); ASSERT_EQ_UINT(outHdr->seq, inHdr->ack); ASSERT_EQ_UINT(outHdr->ack, 0); ASSERT_EQ_HEX8(outHdr->flags, TCP_RST); free(outPkt); ExitState(conn, TCP_SYN_SENT); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_SYN_SENT, "Bad ACK, RST", "segment dropped"); conn = CreateConn(); EnterState(conn, TCP_SYN_SENT); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, 1000, conn->iss, TCP_RST | TCP_ACK); TcpInput(inPkt); ExitState(conn, TCP_SYN_SENT); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_SYN_SENT, "ACK, RST", "conn locally reset"); conn = CreateConn(); EnterState(conn, TCP_SYN_SENT); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, 1000, conn->iss + 1, TCP_RST | TCP_ACK); TcpInput(inPkt); ExpectError(TCP_CONN_RESET); ExitState(conn, TCP_CLOSED); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_SYN_SENT, "no ACK, RST", "segment dropped"); conn = CreateConn(); EnterState(conn, TCP_SYN_SENT); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, 1000, conn->iss + 1, TCP_RST); TcpInput(inPkt); ExitState(conn, TCP_SYN_SENT); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_SYN_SENT, "SYN, ACK", "goto ESTABLISHED"); conn = CreateConn(); EnterState(conn, TCP_SYN_SENT); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, 1000, conn->iss + 1, TCP_SYN | TCP_ACK); TcpInput(inPkt); ASSERT_EQ_UINT(conn->irs, 1000); ASSERT_EQ_UINT(conn->rcvNxt, 1001); outPkt = PopPacket(); outHdr = (TcpHeader *)outPkt->data; TcpSwap(outHdr); ASSERT_EQ_UINT(outHdr->srcPort, conn->localPort); ASSERT_EQ_UINT(outHdr->dstPort, conn->remotePort); ASSERT_EQ_UINT(outHdr->seq, conn->iss + 1); ASSERT_EQ_UINT(outHdr->ack, 1001); ASSERT_EQ_HEX8(outHdr->flags, TCP_ACK); free(outPkt); ExitState(conn, TCP_ESTABLISHED); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_SYN_SENT, "SYN, no ACK", "goto SYN_RECEIVED, resend SYN,ACK"); conn = CreateConn(); EnterState(conn, TCP_SYN_SENT); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, 1000, 0, TCP_SYN); TcpInput(inPkt); ASSERT_EQ_UINT(conn->irs, 1000); ASSERT_EQ_UINT(conn->rcvNxt, 1001); outPkt = PopPacket(); outHdr = (TcpHeader *)outPkt->data; TcpSwap(outHdr); ASSERT_EQ_UINT(outHdr->srcPort, conn->localPort); ASSERT_EQ_UINT(outHdr->dstPort, conn->remotePort); ASSERT_EQ_UINT(outHdr->seq, conn->iss); ASSERT_EQ_UINT(outHdr->ack, 1001); ASSERT_EQ_HEX8(outHdr->flags, TCP_SYN | TCP_ACK); free(outPkt); ExitState(conn, TCP_SYN_RECEIVED); TestCaseEnd(); // -------------------------------------------------------------------------------------------- uint generalStates[] = { TCP_SYN_RECEIVED, TCP_ESTABLISHED, TCP_FIN_WAIT_1, TCP_FIN_WAIT_2, TCP_CLOSE_WAIT, TCP_CLOSING, TCP_LAST_ACK, TCP_TIME_WAIT, 0, }; for (uint *pState = generalStates; *pState; ++pState) { uint state = *pState; TestCaseBegin(state, "Bad seq, no RST", "resend ACK"); conn = CreateConn(); EnterState(conn, state); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt - 1, conn->sndNxt, TCP_ACK); TcpInput(inPkt); outPkt = PopPacket(); outHdr = (TcpHeader *)outPkt->data; TcpSwap(outHdr); ASSERT_EQ_UINT(outHdr->srcPort, conn->localPort); ASSERT_EQ_UINT(outHdr->dstPort, conn->remotePort); ASSERT_EQ_UINT(outHdr->seq, conn->sndNxt); ASSERT_EQ_UINT(outHdr->ack, conn->rcvNxt); ASSERT_EQ_HEX8(outHdr->flags, TCP_ACK); free(outPkt); ExitState(conn, state); TestCaseEnd(); } // -------------------------------------------------------------------------------------------- for (uint *pState = generalStates; *pState; ++pState) { uint state = *pState; TestCaseBegin(state, "Bad seq, RST", "segment dropped"); conn = CreateConn(); EnterState(conn, state); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt - 1, conn->sndNxt, TCP_RST | TCP_ACK); TcpInput(inPkt); ExitState(conn, state); TestCaseEnd(); } // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_SYN_RECEIVED, "RST, active", "conn refused"); conn = CreateConn(); EnterState(conn, TCP_SYN_RECEIVED); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, 0, TCP_RST); TcpInput(inPkt); ExpectError(TCP_CONN_REFUSED); TestCaseEnd(); // -------------------------------------------------------------------------------------------- uint rstStates1[] = { TCP_ESTABLISHED, TCP_FIN_WAIT_1, TCP_FIN_WAIT_2, TCP_CLOSE_WAIT, 0, }; for (uint *pState = rstStates1; *pState; ++pState) { uint state = *pState; TestCaseBegin(state, "RST", "conn reset"); conn = CreateConn(); EnterState(conn, state); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, 0, TCP_RST); TcpInput(inPkt); ExpectError(TCP_CONN_RESET); TestCaseEnd(); } // -------------------------------------------------------------------------------------------- uint rstStates2[] = { TCP_CLOSING, TCP_LAST_ACK, TCP_TIME_WAIT, 0, }; for (uint *pState = rstStates2; *pState; ++pState) { uint state = *pState; TestCaseBegin(state, "RST", "conn closed"); conn = CreateConn(); EnterState(conn, state); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, 0, TCP_RST); TcpInput(inPkt); TestCaseEnd(); } // -------------------------------------------------------------------------------------------- for (uint *pState = generalStates; *pState; ++pState) { uint state = *pState; TestCaseBegin(state, "SYN", "conn reset, RST sent"); conn = CreateConn(); EnterState(conn, state); u16 localPort = conn->localPort; u16 remotePort = conn->remotePort; u32 rcvNxt = conn->rcvNxt; inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_SYN); TcpInput(inPkt); outPkt = PopPacket(); outHdr = (TcpHeader *)outPkt->data; TcpSwap(outHdr); ASSERT_EQ_UINT(outHdr->srcPort, localPort); ASSERT_EQ_UINT(outHdr->dstPort, remotePort); ASSERT_EQ_UINT(outHdr->seq, 0); ASSERT_EQ_UINT(outHdr->ack, rcvNxt); ASSERT_EQ_HEX8(outHdr->flags, TCP_RST | TCP_ACK); free(outPkt); ExpectError(TCP_CONN_RESET); TestCaseEnd(); } // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_SYN_RECEIVED, "bad ACK", "RST sent"); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_SYN_RECEIVED, "ACK", "goto ESTABLISHED"); TestCaseEnd(); // -------------------------------------------------------------------------------------------- uint ackStates[] = { TCP_ESTABLISHED, TCP_FIN_WAIT_1, TCP_FIN_WAIT_2, TCP_CLOSE_WAIT, TCP_CLOSING, 0 }; for (uint *pState = ackStates; *pState; ++pState) { uint state = *pState; TestCaseBegin(state, "ACK", "update pointers"); TestCaseEnd(); } // -------------------------------------------------------------------------------------------- for (uint *pState = ackStates; *pState; ++pState) { uint state = *pState; TestCaseBegin(state, "dup ACK", "ignore"); TestCaseEnd(); } // -------------------------------------------------------------------------------------------- for (uint *pState = ackStates; *pState; ++pState) { uint state = *pState; TestCaseBegin(state, "unsent ACK", "resend ACK"); TestCaseEnd(); } // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_FIN_WAIT_1, "ACK, FIN not ACK'd", "ignore"); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_CLOSING, "ACK, FIN not ACK'd", "ignore"); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_FIN_WAIT_1, "ACK, FIN ACK'd", "goto FIN-WAIT-2"); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_CLOSING, "ACK, FIN ACK'd", "goto TIME-WAIT"); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_LAST_ACK, "ACK, FIN not ACK'd", "ignore"); conn = CreateConn(); EnterState(conn, TCP_LAST_ACK); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt - 1, TCP_ACK); TcpInput(inPkt); ExitState(conn, TCP_LAST_ACK); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_LAST_ACK, "ACK, FIN ACK'd", "goto CLOSED"); conn = CreateConn(); EnterState(conn, TCP_LAST_ACK); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_ACK); TcpInput(inPkt); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_TIME_WAIT, "ACK, no FIN", "ignore"); conn = CreateConn(); EnterState(conn, TCP_TIME_WAIT); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_ACK); TcpInput(inPkt); ExitState(conn, TCP_TIME_WAIT); TestCaseEnd(); // -------------------------------------------------------------------------------------------- TestCaseBegin(TCP_TIME_WAIT, "FIN", "reset 2MSL timer"); conn = CreateConn(); EnterState(conn, TCP_TIME_WAIT); g_pitTicks += 1000; inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_FIN | TCP_ACK); TcpInput(inPkt); outPkt = PopPacket(); outHdr = (TcpHeader *)outPkt->data; TcpSwap(outHdr); ASSERT_EQ_UINT(outHdr->srcPort, conn->localPort); ASSERT_EQ_UINT(outHdr->dstPort, conn->remotePort); ASSERT_EQ_UINT(outHdr->seq, conn->sndNxt); ASSERT_EQ_UINT(outHdr->ack, conn->rcvNxt); ASSERT_EQ_HEX8(outHdr->flags, TCP_ACK); free(outPkt); ASSERT_EQ_UINT(conn->mslWait, g_pitTicks + 2 * TCP_MSL); ExitState(conn, TCP_TIME_WAIT); TestCaseEnd(); return EXIT_SUCCESS; }
// ------------------------------------------------------------------------------------------------ static void ExitState(TcpConn *conn, uint state) { NetBuf *inPkt; TcpHeader *inHdr; Packet *outPkt; TcpHeader *outHdr; ASSERT_EQ_UINT(conn->state, state); ASSERT_TRUE(ListIsEmpty(&s_outPackets)); switch (state) { case TCP_CLOSED: TcpClose(conn); break; case TCP_SYN_SENT: TcpClose(conn); break; case TCP_SYN_RECEIVED: inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_ACK); TcpInput(inPkt); ExitState(conn, TCP_ESTABLISHED); break; case TCP_ESTABLISHED: inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_FIN | TCP_ACK); TcpInput(inPkt); outPkt = PopPacket(); outHdr = (TcpHeader *)outPkt->data; TcpSwap(outHdr); ASSERT_EQ_UINT(outHdr->srcPort, conn->localPort); ASSERT_EQ_UINT(outHdr->dstPort, conn->remotePort); ASSERT_EQ_UINT(outHdr->seq, conn->sndNxt); ASSERT_EQ_UINT(outHdr->ack, conn->rcvNxt); ASSERT_EQ_HEX8(outHdr->flags, TCP_ACK); free(outPkt); ExitState(conn, TCP_CLOSE_WAIT); break; case TCP_FIN_WAIT_1: inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_FIN | TCP_ACK); TcpInput(inPkt); outPkt = PopPacket(); outHdr = (TcpHeader *)outPkt->data; TcpSwap(outHdr); ASSERT_EQ_UINT(outHdr->srcPort, conn->localPort); ASSERT_EQ_UINT(outHdr->dstPort, conn->remotePort); ASSERT_EQ_UINT(outHdr->seq, conn->sndNxt); ASSERT_EQ_UINT(outHdr->ack, conn->rcvNxt); ASSERT_EQ_HEX8(outHdr->flags, TCP_ACK); free(outPkt); ExitState(conn, TCP_TIME_WAIT); break; case TCP_FIN_WAIT_2: inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_FIN | TCP_ACK); TcpInput(inPkt); outPkt = PopPacket(); outHdr = (TcpHeader *)outPkt->data; TcpSwap(outHdr); ASSERT_EQ_UINT(outHdr->srcPort, conn->localPort); ASSERT_EQ_UINT(outHdr->dstPort, conn->remotePort); ASSERT_EQ_UINT(outHdr->seq, conn->sndNxt); ASSERT_EQ_UINT(outHdr->ack, conn->rcvNxt); ASSERT_EQ_HEX8(outHdr->flags, TCP_ACK); free(outPkt); ExitState(conn, TCP_TIME_WAIT); break; case TCP_CLOSE_WAIT: TcpClose(conn); outPkt = PopPacket(); outHdr = (TcpHeader *)outPkt->data; TcpSwap(outHdr); ASSERT_EQ_UINT(outHdr->srcPort, conn->localPort); ASSERT_EQ_UINT(outHdr->dstPort, conn->remotePort); ASSERT_EQ_UINT(outHdr->seq, conn->sndNxt - 1); ASSERT_EQ_UINT(outHdr->ack, conn->rcvNxt); ASSERT_EQ_HEX8(outHdr->flags, TCP_FIN | TCP_ACK); free(outPkt); ExitState(conn, TCP_LAST_ACK); break; case TCP_CLOSING: inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_ACK); TcpInput(inPkt); ExitState(conn, TCP_TIME_WAIT); break; case TCP_LAST_ACK: inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_ACK); TcpInput(inPkt); break; case TCP_TIME_WAIT: g_pitTicks += 2 * TCP_MSL; TcpPoll(); break; default: ASSERT_EQ_UINT(state, 0); break; } ASSERT_EQ_UINT(conn->state, TCP_CLOSED); }
// ------------------------------------------------------------------------------------------------ static void EnterState(TcpConn *conn, uint state) { NetBuf *inPkt; TcpHeader *inHdr; Packet *outPkt; //TcpHeader *outHdr; switch (state) { case TCP_SYN_SENT: ASSERT_TRUE(TcpConnect(conn, &s_ipAddr, 80)); outPkt = PopPacket(); free(outPkt); break; case TCP_SYN_RECEIVED: EnterState(conn, TCP_SYN_SENT); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, 1000, 0, TCP_SYN); TcpInput(inPkt); outPkt = PopPacket(); free(outPkt); break; case TCP_ESTABLISHED: EnterState(conn, TCP_SYN_SENT); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_SYN | TCP_ACK); TcpInput(inPkt); outPkt = PopPacket(); free(outPkt); break; case TCP_FIN_WAIT_1: EnterState(conn, TCP_ESTABLISHED); TcpClose(conn); outPkt = PopPacket(); free(outPkt); break; case TCP_FIN_WAIT_2: EnterState(conn, TCP_FIN_WAIT_1); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_ACK); TcpInput(inPkt); break; case TCP_CLOSE_WAIT: EnterState(conn, TCP_ESTABLISHED); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_FIN | TCP_ACK); TcpInput(inPkt); outPkt = PopPacket(); free(outPkt); break; case TCP_CLOSING: EnterState(conn, TCP_FIN_WAIT_1); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt - 1, TCP_FIN | TCP_ACK); TcpInput(inPkt); outPkt = PopPacket(); free(outPkt); break; case TCP_LAST_ACK: EnterState(conn, TCP_CLOSE_WAIT); TcpClose(conn); outPkt = PopPacket(); free(outPkt); break; case TCP_TIME_WAIT: EnterState(conn, TCP_FIN_WAIT_1); inPkt = NetAllocBuf(); inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_FIN | TCP_ACK); TcpInput(inPkt); outPkt = PopPacket(); free(outPkt); break; default: ASSERT_EQ_UINT(state, 0); break; } ASSERT_EQ_UINT(conn->state, state); ASSERT_TRUE(ListIsEmpty(&s_outPackets)); }
// ------------------------------------------------------------------------------------------------ static void ExpectError(uint error) { ASSERT_EQ_UINT(outError, error); outError = 0; }
int main(void) { struct diag_deque *head, *tail; struct diag_deque_elem *elem; intptr_t i; size_t len; head = diag_deque_new(); tail = diag_deque_new(); /* both are empty */ len = diag_deque_append(head, tail); ASSERT_EQ_UINT(0, len); ASSERT_EQ_UINT(0, head->length); ASSERT_EQ_UINT(0, tail->length); /* head is trivial */ i = 0; while (i < 29) { diag_deque_push(tail, i++); } len = diag_deque_append(head, tail); ASSERT_EQ_UINT(29, head->length); ASSERT_EQ_UINT(0, tail->length); i = 0; while ( (elem = diag_deque_shift(head)) ) { ASSERT_EQ_UINTPTR(i++, elem->attr); diag_free(elem); } ASSERT_EQ_UINTPTR(29, i); /* tail is trivial */ i = 0; while (i < 31) { diag_deque_push(head, i++); } len = diag_deque_append(head, tail); ASSERT_EQ_UINT(31, head->length); ASSERT_EQ_UINT(0, tail->length); i = 0; while ( (elem = diag_deque_shift(head)) ) { ASSERT_EQ_UINTPTR(i++, elem->attr); diag_free(elem); } ASSERT_EQ_UINTPTR(31, i); /* general */ i = 0; while (i < 100) { diag_deque_push(head, i++); } while (i < 300) { diag_deque_push(tail, i++); } len = diag_deque_append(head, tail); ASSERT_EQ_UINT(300, len); ASSERT_EQ_UINT(300, head->length); ASSERT_EQ_UINT(0, tail->length); i = 0; while ( (elem = diag_deque_shift(head)) ) { ASSERT_EQ_UINTPTR(i++, elem->attr); diag_free(elem); } ASSERT_EQ_UINTPTR(300, i); diag_deque_destroy(head); diag_deque_destroy(tail); return EXIT_SUCCESS; }