Fixed TCP client, added client tests
This commit is contained in:
parent
574abdca7b
commit
b0b199fc66
2 changed files with 197 additions and 26 deletions
|
@ -8,17 +8,10 @@
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "femtotcp.h"
|
||||
#include "config.h"
|
||||
|
||||
/* Config (TODO: move to some config.h later) */
|
||||
|
||||
#define LINK_MTU 1536
|
||||
|
||||
#define MAX_TCPSOCKETS 2
|
||||
#define MAX_UDPSOCKETS 2
|
||||
#define RXBUF_SIZE LINK_MTU * 8
|
||||
#define TXBUF_SIZE LINK_MTU * 2
|
||||
|
||||
#define MAX_NEIGHBORS 16
|
||||
/* Fixed size binary heap: each element is a timer. */
|
||||
#define MAX_TIMERS MAX_TCPSOCKETS * 3
|
||||
|
||||
/* Constants */
|
||||
#define MARK_TCP_SOCKET 0x1000 /* Mark a socket as TCP */
|
||||
|
@ -519,8 +512,6 @@ struct ipstack_timer {
|
|||
void (*cb)(void *arg);
|
||||
};
|
||||
|
||||
/* Fixed size binary heap: each element is a timer. */
|
||||
#define MAX_TIMERS MAX_TCPSOCKETS * 3
|
||||
/* Timer binary heap */
|
||||
struct timers_binheap {
|
||||
struct ipstack_timer timers[MAX_TIMERS];
|
||||
|
@ -1038,6 +1029,13 @@ static void tcp_input(struct ipstack *S, struct ipstack_tcp_seg *tcp, uint32_t f
|
|||
return; /* discard */
|
||||
}
|
||||
|
||||
if (t->sock.tcp.state > TCP_LISTEN) {
|
||||
if (t->dst_port != ee16(tcp->src_port) || t->remote_ip != ee32(tcp->ip.src)) {
|
||||
/* Not the right socket */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check IP ttl */
|
||||
if (tcp->ip.ttl == 0) {
|
||||
/* Send ICMP TTL exceeded */
|
||||
|
@ -1200,7 +1198,15 @@ int ft_connect(struct ipstack *s, int sockfd, const struct ipstack_sockaddr *add
|
|||
struct ipstack_tcp_seg tcp;
|
||||
if (!addr)
|
||||
return -2;
|
||||
ts = &s->tcpsockets[sockfd];
|
||||
if (sockfd & MARK_UDP_SOCKET) {
|
||||
ts = &s->udpsockets[sockfd & ~MARK_UDP_SOCKET];
|
||||
ts->dst_port = ee16(sin->sin_port);
|
||||
ts->remote_ip = ee32(sin->sin_addr.s_addr);
|
||||
return 0;
|
||||
}
|
||||
if ((sockfd & MARK_TCP_SOCKET) == 0)
|
||||
return -1;
|
||||
ts = &s->tcpsockets[sockfd & ~MARK_TCP_SOCKET];
|
||||
if (ts->sock.tcp.state == TCP_ESTABLISHED)
|
||||
return 0;
|
||||
if (ts->sock.tcp.state == TCP_SYN_SENT)
|
||||
|
@ -1216,7 +1222,7 @@ int ft_connect(struct ipstack *s, int sockfd, const struct ipstack_sockaddr *add
|
|||
if (ts->src_port < 1024)
|
||||
ts->src_port += 1024;
|
||||
ts->dst_port = ee16(sin->sin_port);
|
||||
tcp.src_port = ts->src_port;
|
||||
tcp.src_port = ee16(ts->src_port);
|
||||
tcp.dst_port = sin->sin_port;
|
||||
tcp.seq = ts->sock.tcp.seq;
|
||||
tcp.ack = 0;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
//#define DHCP
|
||||
#define FEMTOTCP_IP "10.10.10.2"
|
||||
|
@ -20,13 +21,16 @@ static int exit_ok = 0, exit_count = 0;
|
|||
static uint8_t buf[TEST_SIZE];
|
||||
static int tot_sent = 0;
|
||||
static int tot_recv = 0;
|
||||
static int server_closing = 0;
|
||||
static int femtotcp_closing = 0;
|
||||
static int closed = 0;
|
||||
static int conn_fd = -1;
|
||||
static int client_connected = 0;
|
||||
static const uint8_t test_pattern[16] = "Test pattern - -";
|
||||
|
||||
static void socket_cb(int fd, uint16_t event, void *arg)
|
||||
static void server_cb(int fd, uint16_t event, void *arg)
|
||||
{
|
||||
int ret = 0;
|
||||
printf("Called socket_cb, events: %04x fd %d\n", event, fd & (~0x1000));
|
||||
printf("Called server_cb, events: %04x fd %d\n", event, fd & (~0x1000));
|
||||
|
||||
if ((fd == listen_fd) && (event & CB_EVENT_READABLE) && (client_fd == -1)) {
|
||||
client_fd = ft_accept((struct ipstack *)arg, listen_fd, NULL, NULL);
|
||||
|
@ -52,7 +56,7 @@ static void socket_cb(int fd, uint16_t event, void *arg)
|
|||
}
|
||||
if ((event & CB_EVENT_WRITABLE) || ((ret > 0) && !closed)) {
|
||||
int snd_ret;
|
||||
if ((tot_sent >= 4096) && server_closing) {
|
||||
if ((tot_sent >= 4096) && femtotcp_closing) {
|
||||
ft_close((struct ipstack *)arg, client_fd);
|
||||
printf("Server: I closed the connection.\n");
|
||||
closed = 1;
|
||||
|
@ -88,13 +92,74 @@ static void socket_cb(int fd, uint16_t event, void *arg)
|
|||
(void)arg;
|
||||
}
|
||||
|
||||
static void client_cb(int fd, uint16_t event, void *arg)
|
||||
{
|
||||
struct ipstack *s = (struct ipstack *)arg;
|
||||
uint32_t i;
|
||||
int ret;
|
||||
static unsigned int total_r = 0, total_w = 0;
|
||||
printf("Called client_cb, events: %04x fd %d\n", event, fd & (~0x1000));
|
||||
if (fd == conn_fd) {
|
||||
if ((event & CB_EVENT_WRITABLE) && (client_connected == 0)) {
|
||||
printf("Client: connected\n");
|
||||
client_connected = 1;
|
||||
}
|
||||
}
|
||||
if (total_w == 0) {
|
||||
for (i = 0; i < sizeof(buf); i += sizeof(test_pattern)) {
|
||||
memcpy(buf + i, test_pattern, sizeof(test_pattern));
|
||||
}
|
||||
}
|
||||
if (client_connected && (event & CB_EVENT_WRITABLE) && (total_w < sizeof(buf))) {
|
||||
ret = ft_sendto(s, fd, buf + total_w, sizeof(buf) - total_w, 0, NULL, 0);
|
||||
if (ret <= 0) {
|
||||
printf("Test client write: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
total_w += ret;
|
||||
}
|
||||
|
||||
static int test_echoserver(struct ipstack *s, int active_close)
|
||||
while ((total_r < total_w) && (event & CB_EVENT_READABLE)) {
|
||||
ret = ft_recvfrom(s, fd, buf + total_r, sizeof(buf) - total_r, 0, NULL, NULL);
|
||||
if (ret < 0){
|
||||
if (ret != -11) {
|
||||
printf("Client read: %d\n", ret);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ret == 0) {
|
||||
printf("Client read: server has closed the connection.\n");
|
||||
return;
|
||||
}
|
||||
total_r += ret;
|
||||
printf("Client RX total: %u\n", total_r);
|
||||
}
|
||||
if (total_r == sizeof(buf)) {
|
||||
exit_ok = 1;
|
||||
for (i = 0; i < sizeof(buf); i += sizeof(test_pattern)) {
|
||||
if (memcmp(buf + i, test_pattern, sizeof(test_pattern))) {
|
||||
printf("test client: pattern mismatch\n");
|
||||
printf("at position %d\n", i);
|
||||
buf[i + 16] = 0;
|
||||
printf("%s\n", &buf[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (femtotcp_closing) {
|
||||
ft_close(s, fd);
|
||||
conn_fd = -1;
|
||||
}
|
||||
printf("Test client: success\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int test_loop(struct ipstack *s, int active_close)
|
||||
{
|
||||
exit_ok = 0;
|
||||
exit_count = 0;
|
||||
tot_sent = 0;
|
||||
server_closing = active_close;
|
||||
femtotcp_closing = active_close;
|
||||
closed = 0;
|
||||
|
||||
while(1) {
|
||||
|
@ -118,7 +183,6 @@ void *pt_echoclient(void *arg)
|
|||
unsigned total_r = 0;
|
||||
unsigned i;
|
||||
uint8_t buf[BUFFER_SIZE];
|
||||
uint8_t test_pattern[16] = "Test pattern - -";
|
||||
uint32_t *srv_addr = (uint32_t *)arg;
|
||||
struct sockaddr_in remote_sock = {
|
||||
.sin_family = AF_INET,
|
||||
|
@ -131,6 +195,7 @@ void *pt_echoclient(void *arg)
|
|||
return (void *)-1;
|
||||
}
|
||||
sleep(1);
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int));
|
||||
printf("Connecting to echo server\n");
|
||||
ret = connect(fd, (struct sockaddr *)&remote_sock, sizeof(remote_sock));
|
||||
if (ret < 0) {
|
||||
|
@ -154,7 +219,7 @@ void *pt_echoclient(void *arg)
|
|||
}
|
||||
if (ret == 0) {
|
||||
printf("test client read: server has closed the connection.\n");
|
||||
if (server_closing)
|
||||
if (femtotcp_closing)
|
||||
return (void *)0;
|
||||
else
|
||||
return (void *)-1;
|
||||
|
@ -175,6 +240,60 @@ void *pt_echoclient(void *arg)
|
|||
return (void *)0;
|
||||
}
|
||||
|
||||
static void *pt_echoserver(void *arg)
|
||||
{
|
||||
int fd, ret;
|
||||
unsigned total_r = 0;
|
||||
uint8_t buf[BUFFER_SIZE];
|
||||
struct sockaddr_in local_sock = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = ntohs(8), /* Echo */
|
||||
.sin_addr.s_addr = 0
|
||||
};
|
||||
femtotcp_closing = (uintptr_t)arg;
|
||||
fd = socket(AF_INET, IPSTACK_SOCK_STREAM, 0);
|
||||
if (fd < 0) {
|
||||
printf("test server socket: %d\n", fd);
|
||||
return (void *)-1;
|
||||
}
|
||||
local_sock.sin_addr.s_addr = inet_addr(LINUX_IP);
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int));
|
||||
ret = bind(fd, (struct sockaddr *)&local_sock, sizeof(local_sock));
|
||||
if (ret < 0) {
|
||||
printf("test server bind: %d (%s)\n", ret, strerror(errno));
|
||||
return (void *)-1;
|
||||
}
|
||||
ret = listen(fd, 1);
|
||||
if (ret < 0) {
|
||||
printf("test server listen: %d\n", ret);
|
||||
return (void *)-1;
|
||||
}
|
||||
printf("Waiting for client\n");
|
||||
ret = accept(fd, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
printf("test server accept: %d\n", ret);
|
||||
return (void *)-1;
|
||||
}
|
||||
printf("test server: client %d connected\n", ret);
|
||||
fd = ret;
|
||||
while (1) {
|
||||
ret = read(fd, buf + total_r, sizeof(buf) - total_r);
|
||||
if (ret < 0) {
|
||||
printf("failed test server read: %d (%s) \n", ret, strerror(errno));
|
||||
return (void *)-1;
|
||||
}
|
||||
if (ret == 0) {
|
||||
printf("test server read: client has closed the connection.\n");
|
||||
if (femtotcp_closing)
|
||||
return (void *)0;
|
||||
else
|
||||
return (void *)-1;
|
||||
}
|
||||
total_r += ret;
|
||||
write(fd, buf + total_r - ret, ret);
|
||||
}
|
||||
}
|
||||
|
||||
extern int tap_init(struct ll *dev, const char *name, uint32_t host_ip);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
@ -191,6 +310,7 @@ int main(int argc, char **argv)
|
|||
.sin_port = ee16(8), /* Echo */
|
||||
.sin_addr.s_addr = 0
|
||||
};
|
||||
struct ipstack_sockaddr_in remote_sock;
|
||||
|
||||
int ret, test_ret = 0;
|
||||
(void)argc;
|
||||
|
@ -210,7 +330,6 @@ int main(int argc, char **argv)
|
|||
perror("tap init");
|
||||
return 2;
|
||||
}
|
||||
|
||||
system("tcpdump -i femt0 -w test.pcap &");
|
||||
|
||||
#ifdef DHCP
|
||||
|
@ -233,9 +352,11 @@ int main(int argc, char **argv)
|
|||
inet_pton(AF_INET, FEMTOTCP_IP, &srv_ip);
|
||||
#endif
|
||||
|
||||
printf("TCP server tests\n");
|
||||
|
||||
listen_fd = ft_socket(s, AF_INET, IPSTACK_SOCK_STREAM, 0);
|
||||
printf("socket: %04x\n", listen_fd);
|
||||
ipstack_register_callback(s, listen_fd, socket_cb, s);
|
||||
ipstack_register_callback(s, listen_fd, server_cb, s);
|
||||
|
||||
pthread_create(&pt, NULL, pt_echoclient, &srv_ip);
|
||||
printf("Starting test: echo server close-wait\n");
|
||||
|
@ -243,7 +364,7 @@ int main(int argc, char **argv)
|
|||
printf("bind: %d\n", ret);
|
||||
ret = ft_listen(s, listen_fd, 1);
|
||||
printf("listen: %d\n", ret);
|
||||
ret = test_echoserver(s, 0);
|
||||
ret = test_loop(s, 0);
|
||||
pthread_join(pt, (void **)&test_ret);
|
||||
printf("Test echo server close-wait: %d\n", ret);
|
||||
printf("Test linux client: %d\n", test_ret);
|
||||
|
@ -251,12 +372,56 @@ int main(int argc, char **argv)
|
|||
|
||||
pthread_create(&pt, NULL, pt_echoclient, &srv_ip);
|
||||
printf("Starting test: echo server active close\n");
|
||||
ret = test_echoserver(s, 1);
|
||||
ret = test_loop(s, 1);
|
||||
printf("Test echo server close-wait: %d\n", ret);
|
||||
pthread_join(pt, (void **)&test_ret);
|
||||
printf("Test linux client: %d\n", test_ret);
|
||||
sleep(1);
|
||||
|
||||
ft_close(s, listen_fd);
|
||||
/* End TCP Server tests */
|
||||
|
||||
|
||||
/* Client side test: client is closing the connection */
|
||||
remote_sock.sin_family = AF_INET;
|
||||
remote_sock.sin_port = ee16(8);
|
||||
remote_sock.sin_addr.s_addr = inet_addr(LINUX_IP);
|
||||
printf("TCP client tests\n");
|
||||
conn_fd = ft_socket(s, AF_INET, IPSTACK_SOCK_STREAM, 0);
|
||||
printf("client socket: %04x\n", conn_fd);
|
||||
ipstack_register_callback(s, conn_fd, client_cb, s);
|
||||
printf("Connecting to %s:8\n", LINUX_IP);
|
||||
ft_connect(s, conn_fd, (struct ipstack_sockaddr *)&remote_sock, sizeof(remote_sock));
|
||||
pthread_create(&pt, NULL, pt_echoserver, (void*)1);
|
||||
printf("Starting test: echo client active close\n");
|
||||
ret = test_loop(s, 1);
|
||||
printf("Test echo client active close: %d\n", ret);
|
||||
pthread_join(pt, (void **)&test_ret);
|
||||
printf("Test linux server: %d\n", test_ret);
|
||||
|
||||
if (conn_fd >= 0) {
|
||||
ft_close(s, conn_fd);
|
||||
conn_fd = -1;
|
||||
}
|
||||
|
||||
/* Client side test: server is closing the connection */
|
||||
/* Excluded for now as linux cannot bind twice on port 8 */
|
||||
#if 0
|
||||
conn_fd = ft_socket(s, AF_INET, IPSTACK_SOCK_STREAM, 0);
|
||||
if (conn_fd < 0) {
|
||||
printf("cannot create socket: %d\n", conn_fd);
|
||||
}
|
||||
printf("client socket: %04x\n", conn_fd);
|
||||
ipstack_register_callback(s, conn_fd, client_cb, s);
|
||||
printf("Connecting to %s:8\n", LINUX_IP);
|
||||
ft_connect(s, conn_fd, (struct ipstack_sockaddr *)&remote_sock, sizeof(remote_sock));
|
||||
pthread_create(&pt, NULL, pt_echoserver, (void*)0);
|
||||
printf("Starting test: echo client passive close\n");
|
||||
ret = test_loop(s, 0);
|
||||
printf("Test echo client, server closing: %d\n", ret);
|
||||
pthread_join(pt, (void **)&test_ret);
|
||||
printf("Test linux server: %d\n", test_ret);
|
||||
#endif
|
||||
|
||||
|
||||
system("killall tcpdump");
|
||||
|
|
Loading…
Reference in a new issue