From: John Hodge Date: Sun, 16 Mar 2014 09:09:21 +0000 (+0800) Subject: Tools/NetTest - TCP stack testing, going well X-Git-Url: https://git.ucc.asn.au/?p=tpg%2Facess2.git;a=commitdiff_plain;h=d2f1a4c62225533351551870cbe44d94a4ec4fab Tools/NetTest - TCP stack testing, going well --- diff --git a/Tools/NetTest/Makefile b/Tools/NetTest/Makefile index c7118d22..f76c8b47 100644 --- a/Tools/NetTest/Makefile +++ b/Tools/NetTest/Makefile @@ -18,9 +18,9 @@ K_OBJ += vfs/acls.o vfs/io.o vfs/fs/devfs.o # Modules MODULES := IPStack # Local kernel soruces (same as above, but located in same directory as Makefile) -L_OBJ = vfs_shim.o nic.o tcpclient.o tcpserver.o helpers.o mode_cmdline.o +L_OBJ = vfs_shim.o nic.o tcpclient.o tcpserver.o helpers.o cmdline_backend.o # Native Sources (compiled as usual) -N_OBJ = main.o tap.o +N_OBJ = main.o tap.o mode_cmdline.o # Compilation Options CFLAGS := -Wall -std=gnu99 -g -Werror -O0 -pthread diff --git a/Tools/NetTest/cmdline_backend.c b/Tools/NetTest/cmdline_backend.c new file mode 100644 index 00000000..f95895aa --- /dev/null +++ b/Tools/NetTest/cmdline_backend.c @@ -0,0 +1,62 @@ +/* + */ +#define DEBUG 1 +#include "cmdline.h" +#include "tcpserver.h" +#include +#include +#include + +// === PROTOTYES === +void Cmdline_Backend_Thread(void *unused); + +// === GLOBALS === +tThread *gpCmdline_WorkerThread; +tNetTest_TCPServer *gpCmdline_TCPEchoServer; + +// === CODE === +void Cmdline_Backend_StartThread(void) +{ + ASSERT(!gpCmdline_WorkerThread); + gpCmdline_WorkerThread = Proc_SpawnWorker(Cmdline_Backend_Thread, NULL); +} + +void Cmdline_Backend_Thread(void *unused) +{ + Threads_SetName("Cmdline Worker"); + for( ;; ) + { + fd_set rfd, wfd, efd; + int max = -1; + + FD_ZERO(&rfd); + + LOG("gpCmdline_TCPEchoServer = %p", gpCmdline_TCPEchoServer); + if(gpCmdline_TCPEchoServer) + max = MAX(max, NetTest_TCPServer_FillSelect(gpCmdline_TCPEchoServer, &rfd)); + + memcpy(&wfd, &rfd, sizeof(rfd)); + memcpy(&efd, &rfd, sizeof(rfd)); + + LOG("max = %i", max); + int rv = VFS_Select(max+1, &rfd, &wfd, &efd, NULL, THREAD_EVENT_USER1, true); + LOG("rv = %i", rv); + + if(gpCmdline_TCPEchoServer) + NetTest_TCPServer_HandleSelect(gpCmdline_TCPEchoServer, &rfd, &wfd, &efd); + } +} + +void Cmdline_Backend_StartEchoServer(int Port) +{ + if(gpCmdline_TCPEchoServer) + { + // Oops, two + } + else + { + gpCmdline_TCPEchoServer = NetTest_TCPServer_Create(Port); + Log_Debug("Cmdline", "Echo Server = %p", gpCmdline_TCPEchoServer); + Threads_PostEvent(gpCmdline_WorkerThread, THREAD_EVENT_USER1); + } +} diff --git a/Tools/NetTest/include/cmdline.h b/Tools/NetTest/include/cmdline.h new file mode 100644 index 00000000..6c96e3fa --- /dev/null +++ b/Tools/NetTest/include/cmdline.h @@ -0,0 +1,10 @@ +/* + */ +#ifndef _CMDLINE_H_ +#define _CMDLINE_H_ + +extern void Cmdline_Backend_StartThread(void); +extern void Cmdline_Backend_StartEchoServer(int Port); + +#endif + diff --git a/Tools/NetTest/include/nettest.h b/Tools/NetTest/include/nettest.h index 47059934..5edee29c 100644 --- a/Tools/NetTest/include/nettest.h +++ b/Tools/NetTest/include/nettest.h @@ -8,7 +8,9 @@ #ifndef _NETTEST_H_ #define _NETTEST_H_ -#include +#ifndef NULL +# include +#endif extern int NativeNic_AddDev(char *Desc); @@ -25,6 +27,7 @@ extern void NetTest_Suite_Netcat(const char *Addr, int Port); extern void NetTest_Suite_Cmdline(void); extern int Net_ParseAddress(const char *String, void *Addr); +extern int Net_OpenSocket(int AddrType, void *Addr, const char *Filename); extern int Net_OpenSocket_TCPC(int AddrType, void *Addr, int Port); #endif diff --git a/Tools/NetTest/include/tcpserver.h b/Tools/NetTest/include/tcpserver.h new file mode 100644 index 00000000..9601f3f7 --- /dev/null +++ b/Tools/NetTest/include/tcpserver.h @@ -0,0 +1,17 @@ +/* + */ +#ifndef _TCPSERVER_H_ +#define _TCPSERVER_H_ + +#include +#include + +typedef struct sNetTest_TCPServer tNetTest_TCPServer; + +extern tNetTest_TCPServer *NetTest_TCPServer_Create(int Port); +extern void NetTest_TCPServer_Close(tNetTest_TCPServer *Srv); +extern int NetTest_TCPServer_FillSelect(tNetTest_TCPServer *Srv, fd_set *fds); +extern void NetTest_TCPServer_HandleSelect(tNetTest_TCPServer *Srv, const fd_set *rfds, const fd_set *wfds, const fd_set *efds); + +#endif + diff --git a/Tools/NetTest/mode_cmdline.c b/Tools/NetTest/mode_cmdline.c index 5a175172..05a39332 100644 --- a/Tools/NetTest/mode_cmdline.c +++ b/Tools/NetTest/mode_cmdline.c @@ -2,26 +2,40 @@ */ #include #include +#include #include +#include "cmdline.h" // === CODE === void NetTest_Suite_Cmdline(void) { char line[BUFSIZ]; + Cmdline_Backend_StartThread(); while( fgets(line, sizeof(line)-1, stdin) ) { - const char *cmd = strtok(line, " "); + const char *const sep = " \n\r"; + const char *cmd = strtok(line, sep); if(!cmd) continue; if( strcmp(cmd, "exit") == 0 ) { return ; } - else if( strcmp(cmd, "request") == 0 ) { - //const char *addr = strtok(NULL, " "); + else if( strcmp(cmd, "tcp_echo_server") == 0 ) { + const char *port_str = strtok(NULL, sep); + char *end; + int port = strtol(port_str, &end, 0); + if(*end != '\0') { + fprintf(stderr, "ERROR: Port number '%s' not valid\n", port_str); + continue ; + } + Cmdline_Backend_StartEchoServer(port); + // TODO: Allow stopping of the server? } else { fprintf(stderr, "ERROR: Unknown command '%s'\n", cmd); } } + + // TODO: Tear down backend? } diff --git a/Tools/NetTest/tcpserver.c b/Tools/NetTest/tcpserver.c index e69de29b..d38b442f 100644 --- a/Tools/NetTest/tcpserver.c +++ b/Tools/NetTest/tcpserver.c @@ -0,0 +1,92 @@ +/* + * Acess2 Networking Test Suite (NetTest) + * - By John Hodge (thePowersGang) + * + * tcpserver.c + * - TCP Client tester + */ +#include +#include +#include +#include "tcpserver.h" + +#define MAX_CLIENTS 4 + +struct sNetTest_TCPServer +{ + int ServerFD; + int nClients; + struct sClient { + int FD; + } Clients[MAX_CLIENTS]; +}; + +// === CODE === +tNetTest_TCPServer *NetTest_TCPServer_Create(int Port) +{ + tNetTest_TCPServer *ret; + ret = calloc(sizeof(*ret), 1); + ret->ServerFD = VFS_Open("/Devices/ip/1/tcps", VFS_OPENFLAG_READ); + ASSERT(ret->ServerFD >= 0); + VFS_IOCtl(ret->ServerFD, 4, &Port); + return ret; +} + +void NetTest_TCPServer_Close(tNetTest_TCPServer *Srv) +{ + VFS_Close(Srv->ServerFD); + for( int i = 0; i < Srv->nClients; i ++ ) + { + struct sClient *client = &Srv->Clients[i]; + VFS_Close(client->FD); + } + free(Srv); +} + +int NetTest_TCPServer_FillSelect(tNetTest_TCPServer *Srv, fd_set *fds) +{ + ASSERT(Srv->ServerFD >= 0); + int max = -1; + + if( Srv->nClients == MAX_CLIENTS ) { + max = Srv->ServerFD; + FD_SET(Srv->ServerFD, fds); + } + for( int i = 0; i < Srv->nClients; i ++ ) + { + int fd = Srv->Clients[i].FD; + if( fd > max ) max = fd; + FD_SET(fd, fds); + } + return max; +} + +void NetTest_TCPServer_HandleSelect(tNetTest_TCPServer *Srv, const fd_set *rfds, const fd_set *wfds, const fd_set *efds) +{ + if( FD_ISSET(Srv->ServerFD, rfds) ) + { + // New connection! + ASSERT(Srv->nClients != MAX_CLIENTS); + struct sClient *client = &Srv->Clients[Srv->nClients++]; + client->FD = VFS_OpenChild(Srv->ServerFD, "", VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE); + } + + for( int i = 0; i < Srv->nClients; i ++ ) + { + struct sClient *client = &Srv->Clients[i]; + if( FD_ISSET(client->FD, rfds) ) + { + // RX'd data on client + } + + if( FD_ISSET(client->FD, efds) ) + { + // Drop client + VFS_Close(client->FD); + memmove(client, client+1, (Srv->nClients-i-1) * sizeof(*client)); + Srv->nClients --; + i --; // counteract i++ + } + } +} + diff --git a/Tools/NetTest_Runner/include/stack.h b/Tools/NetTest_Runner/include/stack.h index 40c92d64..7ac2083b 100644 --- a/Tools/NetTest_Runner/include/stack.h +++ b/Tools/NetTest_Runner/include/stack.h @@ -15,7 +15,7 @@ extern void Stack_AddArg(const char *Fmt, ...); extern int Stack_Start(const char *Subcommand); extern void Stack_Kill(void); -extern int Stack_SendCommand(const char *CommandString); +extern int Stack_SendCommand(const char *CommandString, ...); #endif diff --git a/Tools/NetTest_Runner/include/tcp.h b/Tools/NetTest_Runner/include/tcp.h index a96d921a..effc3adb 100644 --- a/Tools/NetTest_Runner/include/tcp.h +++ b/Tools/NetTest_Runner/include/tcp.h @@ -12,9 +12,20 @@ #define TCP_FIN 0x01 #define TCP_SYN 0x02 #define TCP_RST 0x04 +#define TCP_PSH 0x08 +#define TCP_ACK 0x10 +#define TCP_URG 0x20 extern void TCP_Send(int IF, int AF, const void *IP, short sport, short dport, uint32_t seq, uint32_t ack, uint8_t flags, uint16_t window, size_t data_len, const void *data); -extern bool TCP_Pkt_Check(size_t len, const void *data, size_t *ofs, int AF, const void *IP, short sport, short dport, uint8_t flags); + + +// The following skip the next check of each field +extern void TCP_SkipCheck_Seq(bool Skip); + +extern bool TCP_Pkt_Check(size_t len, const void *data, size_t *ofs, int AF, const void *IP, short sport, short dport, uint32_t seq, uint32_t ack, uint8_t flags); + +// - Get a field from a previously validated packet +extern uint32_t TCP_Pkt_GetSeq(size_t len, const void *data, int AF); #endif diff --git a/Tools/NetTest_Runner/include/test.h b/Tools/NetTest_Runner/include/test.h index 7a325860..3559fafd 100644 --- a/Tools/NetTest_Runner/include/test.h +++ b/Tools/NetTest_Runner/include/test.h @@ -5,7 +5,7 @@ #define TEST_SETNAME(name) test_setname(name) #define TEST_ASSERT(cnd) do{if(!(cnd)) {test_assertion_fail(__FILE__,__LINE__,"%s",#cnd);return false;}}while(0) -#define TEST_ASSERT_REL(a,r,b) do{long long a_val=(a),b_val=(b);if(!(a_val r b_val)) {test_assertion_fail(__FILE__,__LINE__,"%s(0x%llx)%s%s(%llx)",#a,a_val,#r,#b,b_val);return false;}}while(0) +#define TEST_ASSERT_REL(a,r,b) do{long long a_val=(a),b_val=(b);if(!(a_val r b_val)) {test_assertion_fail(__FILE__,__LINE__,"%s(0x%llx)%s%s(0x%llx)",#a,a_val,#r,#b,b_val);return false;}}while(0) #define TEST_WARN(msg...) test_message(__FILE__,__LINE__,msg) extern void test_setname(const char *name); diff --git a/Tools/NetTest_Runner/ip.c b/Tools/NetTest_Runner/ip.c index bebcf739..628fdbe8 100644 --- a/Tools/NetTest_Runner/ip.c +++ b/Tools/NetTest_Runner/ip.c @@ -94,8 +94,19 @@ bool IP_Pkt_Check(size_t len, const void *data, size_t *ofs_out, int AF, const v tIPv4Hdr hdr; memcpy(&hdr, (const uint8_t*)data + ofs, sizeof(hdr)); TEST_ASSERT_REL(hdr.VerLen >> 4, ==, 4); + TEST_ASSERT_REL(IP_Checksum(IP_CHECKSUM_START, sizeof(hdr), &hdr), ==, 0); + + TEST_ASSERT_REL(ntohs(hdr.TotalLength), <=, len - ofs); + TEST_ASSERT_REL(ntohs(hdr.FragmentInfo), ==, 0); + + TEST_ASSERT_REL(hdr.TTL, >, 1); // >1 because there's no intervening hops + TEST_ASSERT_REL(hdr.Protocol, ==, proto); + + TEST_ASSERT( memcmp(hdr.SrcAddr, Src, 4) == 0 ); + TEST_ASSERT( memcmp(hdr.DstAddr, Dst, 4) == 0 ); - return false; + *ofs_out = ofs + (hdr.VerLen & 0xF) * 4; + return true; } else { TEST_WARN("Invalid AF(%i) in IP_Pkt_Check", AF); diff --git a/Tools/NetTest_Runner/link.c b/Tools/NetTest_Runner/link.c index 53dfde54..96fddaf4 100644 --- a/Tools/NetTest_Runner/link.c +++ b/Tools/NetTest_Runner/link.c @@ -38,8 +38,8 @@ bool Link_Pkt_Check(size_t len, const void *data, size_t *ofs_out, const uint8_t *data8 = data; TEST_ASSERT_REL(len, >=, 6+6+2); - if(Src) TEST_ASSERT( memcmp(data8+0, Src, 6) == 0 ); - if(Dst) TEST_ASSERT( memcmp(data8+6, Dst, 6) == 0 ); + if(Dst) TEST_ASSERT( memcmp(data8+0, Dst, 6) == 0 ); + if(Src) TEST_ASSERT( memcmp(data8+6, Src, 6) == 0 ); TEST_ASSERT_REL( ntohs(*(uint16_t*)(data8+12)), ==, Proto ); diff --git a/Tools/NetTest_Runner/stack.c b/Tools/NetTest_Runner/stack.c index c359d848..65f83522 100644 --- a/Tools/NetTest_Runner/stack.c +++ b/Tools/NetTest_Runner/stack.c @@ -123,9 +123,18 @@ void Stack_Kill(void) } } -int Stack_SendCommand(const char *CommandString) +int Stack_SendCommand(const char *Fmt, ...) { - write(giStack_InFD, CommandString, strlen(CommandString)); + va_list args; + va_start(args, Fmt); + size_t len = vsnprintf(NULL, 0, Fmt, args); + va_end(args); + char command[len+1]; + va_start(args, Fmt); + vsnprintf(command, len+1, Fmt, args); + va_end(args); + + write(giStack_InFD, command, len); write(giStack_InFD, "\n", 1); return 0; } diff --git a/Tools/NetTest_Runner/tcp.c b/Tools/NetTest_Runner/tcp.c index 56c55717..0bf0a67f 100644 --- a/Tools/NetTest_Runner/tcp.c +++ b/Tools/NetTest_Runner/tcp.c @@ -19,6 +19,23 @@ typedef struct { } __attribute__((packed)) tTCPHeader; // === CODE === +uint16_t TCP_int_GetPseudoHeader(int AF, const void *SrcAddr, const void *DstAddr, uint8_t pctl, size_t Len) +{ + if( AF == 4 ) { + uint8_t phdr[12]; + memcpy(phdr+0, SrcAddr, 4); + memcpy(phdr+4, DstAddr, 4); + phdr[8] = 0; + phdr[9] = pctl; + *(uint16_t*)(phdr+10) = htons(Len); + return IP_Checksum(IP_CHECKSUM_START, 12, phdr); + } + else { + TEST_WARN("TCP unknown AF %i", AF); + return 0; + } +} + void TCP_Send(int IF, int AF, const void *IP, short sport, short dport, uint32_t seq, uint32_t ack, uint8_t flags, uint16_t window, size_t data_len, const void *data @@ -29,13 +46,14 @@ void TCP_Send(int IF, int AF, const void *IP, short sport, short dport, hdr.DPort = htons(dport); hdr.Seq = htonl(seq); hdr.Ack = htonl(ack); - hdr.DataOfs = sizeof(hdr)/4; + hdr.DataOfs = (sizeof(hdr)/4) << 4; hdr.Flags = flags; hdr.Window = htons(window); hdr.Checksum = htons(0); hdr.UrgPtr = htons(0); - uint16_t checksum = IP_CHECKSUM_START; + uint16_t checksum; + checksum = TCP_int_GetPseudoHeader(AF, BLOB(HOST_IP), IP, IPPROTO_TCP, sizeof(hdr)+data_len); checksum = IP_Checksum(checksum, sizeof(hdr), &hdr); checksum = IP_Checksum(checksum, data_len, data); hdr.Checksum = htons( checksum ); @@ -45,30 +63,56 @@ void TCP_Send(int IF, int AF, const void *IP, short sport, short dport, IP_Send(IF, AF, BLOB(HOST_IP), IP, IPPROTO_TCP, 2, buflens, bufs); } -bool TCP_Pkt_Check(size_t len, const void *data, size_t *out_ofs, int AF, const void *IP, short sport, short dport, - uint8_t flags) +struct { + bool Seq; + bool Ack; + bool SPort; +} gTCP_Skips; + +void TCP_SkipCheck_Seq(bool Skip) { + gTCP_Skips.Seq = Skip; +} + +bool TCP_Pkt_Check(size_t len, const void *data, size_t *out_ofs, + int AF, const void *IP, short sport, short dport, + uint32_t seq, uint32_t ack, uint8_t flags) { size_t ofs; if( !IP_Pkt_Check(len, data, &ofs, AF, IP, BLOB(HOST_IP), IPPROTO_TCP) ) return false; + // TODO: IP has its own length field, use that? tTCPHeader hdr; TEST_ASSERT_REL(len - ofs, >=, sizeof(hdr)); memcpy(&hdr, (char*)data + ofs, sizeof(hdr)); - TEST_ASSERT_REL( ntohs(hdr.SPort), ==, sport ); + TEST_ASSERT_REL( hdr.DataOfs >> 4, >=, sizeof(hdr)/4 ); + if( !gTCP_Skips.SPort ) TEST_ASSERT_REL( ntohs(hdr.SPort), ==, sport ); TEST_ASSERT_REL( ntohs(hdr.DPort), ==, dport ); - // TODO: Checks on Seq/Ack + if( !gTCP_Skips.Seq ) TEST_ASSERT_REL( ntohl(hdr.Seq), ==, seq ); + if( !gTCP_Skips.Ack ) TEST_ASSERT_REL( ntohl(hdr.Ack), ==, ack ); TEST_ASSERT_REL( hdr.Flags, ==, flags); uint16_t real_cksum = htons(hdr.Checksum); hdr.Checksum = 0; - uint16_t calc_cksum = IP_CHECKSUM_START; + uint16_t calc_cksum; + calc_cksum = TCP_int_GetPseudoHeader(AF, IP, BLOB(HOST_IP), IPPROTO_TCP, len-ofs); calc_cksum = IP_Checksum(calc_cksum, sizeof(hdr), &hdr); calc_cksum = IP_Checksum(calc_cksum, len - ofs - sizeof(hdr), (char*)data+ofs+sizeof(hdr)); TEST_ASSERT_REL( real_cksum, ==, calc_cksum ); - + + memset(&gTCP_Skips, 0, sizeof(gTCP_Skips)); + *out_ofs = ofs + sizeof(hdr); return true; } +uint32_t TCP_Pkt_GetSeq(size_t len, const void *data, int AF) { + size_t ofs; + IP_Pkt_Check(len, data, &ofs, AF, NULL, NULL, IPPROTO_TCP); + + tTCPHeader hdr; + memcpy(&hdr, (char*)data + ofs, sizeof(hdr)); + return ntohl(hdr.Seq); +} + diff --git a/Tools/NetTest_Runner/test_tcp.c b/Tools/NetTest_Runner/test_tcp.c index a19c85b2..32f79c0f 100644 --- a/Tools/NetTest_Runner/test_tcp.c +++ b/Tools/NetTest_Runner/test_tcp.c @@ -7,20 +7,90 @@ #include "arp.h" #include "tcp.h" +#define TEST_ASSERT_rx() TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, ERX_TIMEOUT) ) +#define TEST_ASSERT_no_rx() TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, NRX_TIMEOUT) == 0 ) + bool Test_TCP_Basic(void) { TEST_SETNAME(__func__); size_t rxlen, ofs; char rxbuf[MTU]; + const int ERX_TIMEOUT = 1000; // Expect RX timeout (timeout=failure) + const int NRX_TIMEOUT = 1000; // Not expect RX timeout (timeout=success) + + const char testblob[] = "HelloWorld, this is some random testing data for TCP\xFF\x00\x66\x12\x12"; + const size_t testblob_len = sizeof(testblob); - // 1. Test connection to closed port + // 1. Test packets to closed port + // > RFC793 Pg.65 + const uint16_t our_window = 0x1000; uint32_t seq_tx = 0x1000; - uint32_t seq_exp = 0; - TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_SYN, 0x1000, 0, NULL); + uint32_t seq_exp = 0x33456; + + // 1.1. Send SYN packet + TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_SYN, 0x1000, testblob_len, testblob); + // Expect a TCP_RST|TCP_ACK with SEQ=0,ACK=SEQ+LEN + TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, ERX_TIMEOUT) ); + TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), 80, 1234, + 0, seq_tx+testblob_len, TCP_RST|TCP_ACK) ); + TEST_ASSERT_REL(ofs, ==, rxlen); - TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, 1000) ); - TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), 80, 1234, TCP_RST) ); + // 1.2. Send a SYN,ACK packet + TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_SYN|TCP_ACK, 0x1000, 0, NULL); + // Expect a TCP_RST with SEQ=ACK + TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, ERX_TIMEOUT) ); + TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), 80, 1234, seq_exp, seq_tx+0, TCP_RST) ); TEST_ASSERT_REL(ofs, ==, rxlen); + // 1.3. Send a RST packet + TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_RST, 0x1000, 0, NULL); + // Expect nothing + TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, NRX_TIMEOUT) == 0 ); + + // 1.3. Send a RST,ACK packet + TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_RST|TCP_ACK, 0x1000, 0, NULL); + // Expect nothing + TEST_ASSERT_no_rx(); + + + // 2. Establishing connection with a server + const int server_port = 1024; + const int local_port = 11234; + Stack_SendCommand("tcp_echo_server %i", server_port); + + // >>> STATE: LISTEN + + // 2.1. Send RST + TCP_Send(0, 4, BLOB(TEST_IP), local_port, server_port, seq_tx, seq_exp, TCP_RST, our_window, 0, NULL); + // - Expect nothing + TEST_ASSERT_no_rx(); + // 2.2. Send ACK + TCP_Send(0, 4, BLOB(TEST_IP), local_port, server_port, seq_tx, seq_exp, TCP_ACK, our_window, 0, NULL); + // - Expect RST + TEST_ASSERT_rx(); + TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), 80, 1234, seq_exp, seq_tx+0, TCP_RST) ); + + // 2.3. Begin hanshake (SYN) + // TODO: "If the SYN bit is set, check the security." + TCP_Send(0, 4, BLOB(TEST_IP), local_port, server_port, seq_tx, 0, TCP_SYN, our_window, 0, NULL); + // - Expect SYN,ACK with ACK == SEQ+1 + TEST_ASSERT_rx(); + TCP_SkipCheck_Seq(true); + TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), server_port, local_port, + 0, seq_tx+1, TCP_SYN|TCP_ACK) ); + seq_exp = TCP_Pkt_GetSeq(rxlen, rxbuf, 4); + + // >>> STATE: SYN-RECEIVED + // TODO: Test other transitions from SYN-RECEIVED + + // 2.4. Complete handshake, TCP ACK + TCP_Send(0,4,BLOB(TEST_IP), local_port, server_port, seq_tx, seq_exp, TCP_ACK, our_window, 0, NULL); + // - Expect nothing + TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, NRX_TIMEOUT) == 0 ); + + // >>> STATE: ESTABLISHED + + // 2.5. Send data + return true; } diff --git a/Tools/nativelib/logging.c b/Tools/nativelib/logging.c index e9925ac1..292b8a52 100644 --- a/Tools/nativelib/logging.c +++ b/Tools/nativelib/logging.c @@ -110,9 +110,9 @@ void Debug_HexDump(const char *Prefix, const void *Data, size_t Length) void Debug_TraceEnter(const char *Function, const char *Format, ...) { - const char *Ident = "Trace"; LOG_LOCK_ACQUIRE(); - LOGHDR("37","T"); + //const char *Ident = "Trace"; + //LOGHDR("37","T"); for( int i = 0; i < giDebug_TraceLevel; i ++ ) fprintf(stderr, " "); fprintf(stderr, "%s: (", Function); @@ -171,9 +171,9 @@ void Debug_TraceEnter(const char *Function, const char *Format, ...) void Debug_TraceLog(const char *Function, const char *Format, ...) { - const char *Ident = "Trace"; LOG_LOCK_ACQUIRE(); - LOGHDR("37","T"); + //const char *Ident = "Trace"; + //LOGHDR("37","T"); for( int i = 0; i < giDebug_TraceLevel; i ++ ) fprintf(stderr, " "); @@ -195,9 +195,9 @@ void Debug_TraceLeave(const char *Function, char Type, ...) Log_Error("Debug", "Function %s called LEAVE without ENTER", Function); } - const char *Ident = "Trace"; LOG_LOCK_ACQUIRE(); - LOGHDR("37","T"); + //const char *Ident = "Trace"; + //LOGHDR("37","T"); va_list args; va_start(args, Type); diff --git a/Tools/nativelib/threads.c b/Tools/nativelib/threads.c index cc508fbf..93db6c3c 100644 --- a/Tools/nativelib/threads.c +++ b/Tools/nativelib/threads.c @@ -5,6 +5,7 @@ * threads.c * - Threads handling */ +#define DEBUG 1 #include #include #include @@ -84,6 +85,7 @@ void Threads_AddActive(tThread *Thread) { Thread->Status = THREAD_STAT_ACTIVE; // Increment state-change semaphore + LOG("Waking %p(%i %s)", Thread, Thread->TID, Thread->ThreadName); Threads_int_SemSignal(Thread->WaitSemaphore); } @@ -149,6 +151,7 @@ void Threads_int_WaitForStatusEnd(enum eThreadStatus Status) Log_Warning("Threads", "Thread %p(%i %s) rescheduled while in %s state", us, us->TID, us->ThreadName, casTHREAD_STAT[Status]); } + LOG("%p(%i %s) Awake", us, us->TID, us->ThreadName); } int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock) diff --git a/Tools/nativelib/threads_int.c b/Tools/nativelib/threads_int.c index 8ab9b341..87c60b1a 100644 --- a/Tools/nativelib/threads_int.c +++ b/Tools/nativelib/threads_int.c @@ -8,6 +8,7 @@ * POSIX Mutex/Semaphore management * Wait state */ +#define DEBUG 1 #include #include #include @@ -109,9 +110,12 @@ void Threads_int_SemWaitAll(tThreadIntSem *Sem) if( Threads_int_ThreadingEnabled() ) { // TODO: Handle multiples + LOG("Waiting on %p", Sem); sem_wait( (void*)Sem ); - while( sem_trywait((void*)Sem) ) + LOG("Wait 1 done, cleaning up"); + while( sem_trywait((void*)Sem) == 0 ) ; + LOG("Wait over"); } else {