Added posix non-blocking sockets, new tests
All checks were successful
/ unit_test (push) Successful in 51s
All checks were successful
/ unit_test (push) Successful in 51s
This commit is contained in:
parent
5c3cd8bf1e
commit
1490f8dba1
8 changed files with 310 additions and 42 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,6 +1,7 @@
|
||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
*.pcap
|
*.pcap
|
||||||
|
*.so
|
||||||
build/*
|
build/*
|
||||||
test/unit/unit
|
test/unit/unit
|
||||||
tags
|
tags
|
||||||
|
|
39
Makefile
39
Makefile
|
@ -1,39 +1,62 @@
|
||||||
CC?=gcc
|
CC?=gcc
|
||||||
CFLAGS:=-Wall -Werror -Wextra -I.
|
CFLAGS:=-Wall -Werror -Wextra -I.
|
||||||
|
CFLAGS+=-g -ggdb
|
||||||
|
LDFLAGS+=-pthread
|
||||||
|
|
||||||
OBJ=build/femtotcp.o \
|
OBJ=build/femtotcp.o \
|
||||||
build/test/test_linux_eventloop.o build/port/posix/linux_tap.o
|
build/port/posix/linux_tap.o
|
||||||
|
|
||||||
all: build/test-evloop
|
EXE=build/tcpecho build/test-evloop
|
||||||
|
LIB=libfemtotcp.so
|
||||||
|
|
||||||
|
|
||||||
|
all: $(EXE) $(LIB)
|
||||||
|
|
||||||
#Static library
|
#Static library
|
||||||
static: CFLAGS+=-static
|
static: CFLAGS+=-static
|
||||||
static: libtcpip.a
|
static: libtcpip.a
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
libtcpip.a: $(OBJ)
|
libtcpip.a: $(OBJ)
|
||||||
@ar rcs $@ $^
|
@ar rcs $@ $^
|
||||||
|
|
||||||
|
libfemtotcp.so:CFLAGS+=-fPIC
|
||||||
|
libfemtotcp.so: build/pie/port/posix/bsd_socket.o build/pie/femtotcp.o \
|
||||||
|
build/pie/port/posix/linux_tap.o
|
||||||
|
@mkdir -p `dirname $@` || true
|
||||||
|
@echo "[LD] $@"
|
||||||
|
@$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ -Wl,--start-group $(^) -Wl,--end-group
|
||||||
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rf build
|
@rm -rf build
|
||||||
@make -C src/test/unit clean
|
@make -C src/test/unit clean
|
||||||
|
|
||||||
# Test
|
asan: $(EXE) $(LIB)
|
||||||
asan: build/test-evloop
|
|
||||||
asan:CFLAGS+=-fsanitize=address
|
asan:CFLAGS+=-fsanitize=address
|
||||||
asan:LDFLAGS+=-static-libasan
|
asan:LDFLAGS+=-static-libasan
|
||||||
build/test:CFLAGS+=-g -ggdb -DTEST_MAIN -DETHERNET
|
|
||||||
build/test:LDFLAGS+=-pthread
|
|
||||||
|
|
||||||
|
|
||||||
build/test-evloop: $(OBJ)
|
# Test
|
||||||
|
build/test-evloop: $(OBJ) build/test/test_linux_eventloop.o
|
||||||
@echo "[LD] $@"
|
@echo "[LD] $@"
|
||||||
@$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ)
|
@$(CC) $(CFLAGS) $(LDFLAGS) -o $@ -Wl,--start-group $(^) -Wl,--end-group
|
||||||
|
|
||||||
|
build/tcpecho: $(OBJ) build/port/posix/bsd_socket.o build/test/tcp_echo.o
|
||||||
|
@echo "[LD] $@"
|
||||||
|
@$(CC) $(CFLAGS) $(LDFLAGS) -o $@ -Wl,--start-group $(^) -Wl,--end-group
|
||||||
|
|
||||||
build/%.o: src/%.c
|
build/%.o: src/%.c
|
||||||
@mkdir -p `dirname $@` || true
|
@mkdir -p `dirname $@` || true
|
||||||
@echo "[CC] $<"
|
@echo "[CC] $<"
|
||||||
@$(CC) $(CFLAGS) -c $< -o $@
|
@$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
build/pie/%.o: src/%.c
|
||||||
|
@mkdir -p `dirname $@` || true
|
||||||
|
@echo "[CC] $<"
|
||||||
|
@$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
unit:
|
unit:
|
||||||
@make -C src/test/unit
|
@make -C src/test/unit
|
||||||
@mkdir -p build/test/
|
@mkdir -p build/test/
|
||||||
|
|
4
config.h
4
config.h
|
@ -11,4 +11,8 @@
|
||||||
|
|
||||||
#define MAX_NEIGHBORS 16
|
#define MAX_NEIGHBORS 16
|
||||||
|
|
||||||
|
/* Linux test configuration */
|
||||||
|
#define FEMTOTCP_IP "10.10.10.2"
|
||||||
|
#define LINUX_IP "10.10.10.1"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,6 +12,7 @@ typedef uint32_t ip4;
|
||||||
#define ee32(x) __builtin_bswap32(x)
|
#define ee32(x) __builtin_bswap32(x)
|
||||||
#define DEBUG
|
#define DEBUG
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
|
#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
|
||||||
|
@ -39,9 +40,15 @@ struct ipconf {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Socket interface */
|
/* Socket interface */
|
||||||
|
#define MARK_TCP_SOCKET 0x1000 /* Mark a socket as TCP */
|
||||||
|
#define MARK_UDP_SOCKET 0x4000 /* Mark a socket as UDP */
|
||||||
|
|
||||||
|
|
||||||
#ifndef FEMTO_POSIX
|
#ifndef FEMTO_POSIX
|
||||||
#define IPSTACK_SOCK_STREAM 1
|
#define IPSTACK_SOCK_STREAM 1
|
||||||
#define IPSTACK_SOCK_DGRAM 2
|
#define IPSTACK_SOCK_DGRAM 2
|
||||||
|
|
||||||
|
|
||||||
struct ipstack_sockaddr_in {
|
struct ipstack_sockaddr_in {
|
||||||
uint16_t sin_family;
|
uint16_t sin_family;
|
||||||
uint16_t sin_port;
|
uint16_t sin_port;
|
||||||
|
@ -96,6 +103,8 @@ ip4 atoip4(const char *ip);
|
||||||
#define CB_EVENT_TIMEOUT 0x08 /* Timeout */
|
#define CB_EVENT_TIMEOUT 0x08 /* Timeout */
|
||||||
void ipstack_register_callback(struct ipstack *s, int sock_fd, void (*cb)(int sock_fd, uint16_t events, void *arg), void *arg);
|
void ipstack_register_callback(struct ipstack *s, int sock_fd, void (*cb)(int sock_fd, uint16_t events, void *arg), void *arg);
|
||||||
|
|
||||||
|
/* External requirements */
|
||||||
|
uint32_t ipstack_getrandom(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,6 @@
|
||||||
#define MAX_TIMERS MAX_TCPSOCKETS * 3
|
#define MAX_TIMERS MAX_TCPSOCKETS * 3
|
||||||
|
|
||||||
/* Constants */
|
/* Constants */
|
||||||
#define MARK_TCP_SOCKET 0x1000 /* Mark a socket as TCP */
|
|
||||||
#define MARK_UDP_SOCKET 0x4000 /* Mark a socket as UDP */
|
|
||||||
|
|
||||||
#define IPPROTO_ICMP 0x01
|
#define IPPROTO_ICMP 0x01
|
||||||
#define IPPROTO_TCP 0x06
|
#define IPPROTO_TCP 0x06
|
||||||
|
|
|
@ -1,11 +1,39 @@
|
||||||
/* POSIX socket calls wrapper for femtoTCP */
|
/* POSIX socket calls wrapper for femtoTCP */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#define FEMTO_POSIX
|
#define FEMTO_POSIX
|
||||||
|
#include "config.h"
|
||||||
#include "femtotcp.h"
|
#include "femtotcp.h"
|
||||||
|
|
||||||
static __thread int in_the_stack = 0;
|
static __thread int in_the_stack = 1;
|
||||||
static __thread struct ipstack IPSTACK;
|
static struct ipstack *IPSTACK = NULL;
|
||||||
|
|
||||||
|
/* host_ functions are the original functions from the libc */
|
||||||
|
static int (*host_socket ) (int domain, int type, int protocol) = NULL;
|
||||||
|
static int (*host_bind ) (int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
static int (*host_connect ) (int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
static int (*host_accept ) (int sockfd, struct sockaddr *addr, socklen_t *addrlen);
|
||||||
|
static int (*host_listen ) (int sockfd, int backlog);
|
||||||
|
static ssize_t (*host_recvfrom) (int sockfd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen);
|
||||||
|
static ssize_t (*host_recv ) (int sockfd, void *buf, size_t len, int flags);
|
||||||
|
static ssize_t (*host_read ) (int sockfd, void *buf, size_t len);
|
||||||
|
static ssize_t (*host_sendto ) (int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
static ssize_t (*host_send ) (int sockfd, const void *buf, size_t len, int flags);
|
||||||
|
static ssize_t (*host_write ) (int sockfd, const void *buf, size_t len);
|
||||||
|
static int (*host_close ) (int sockfd);
|
||||||
|
static int (*host_setsockopt) (int sockfd, int level, int optname, const void *optval, socklen_t optlen);
|
||||||
|
static int (*host_getsockopt) (int sockfd, int level, int optname, void *optval, socklen_t *optlen);
|
||||||
|
static int (*host_getsockname) (int sockfd, struct sockaddr *addr, socklen_t *addrlen);
|
||||||
|
static int (*host_getpeername) (int sockfd, struct sockaddr *addr, socklen_t *addrlen);
|
||||||
|
|
||||||
|
|
||||||
#define swap_socketcall(call, name) \
|
#define swap_socketcall(call, name) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -13,51 +41,192 @@ static __thread struct ipstack IPSTACK;
|
||||||
if (host_##call == NULL) { \
|
if (host_##call == NULL) { \
|
||||||
*(void **)(&host_##call) = dlsym(RTLD_NEXT, name); \
|
*(void **)(&host_##call) = dlsym(RTLD_NEXT, name); \
|
||||||
if ((msg = dlerror()) != NULL) \
|
if ((msg = dlerror()) != NULL) \
|
||||||
fprintf (stderr, "%s: dlsym(%s): %s\n", "picotcp", name, msg); \
|
fprintf (stderr, "%s: dlsym(%s): %s\n", "femtoTCP", name, msg); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define conditional_steal_call(call, fd, ...) \
|
#define conditional_steal_call(call, fd, ...) \
|
||||||
if(in_the_stack) { \
|
if(in_the_stack) { \
|
||||||
return host_##call(i, ## __VA_ARGS__); \
|
return host_##call(fd, ## __VA_ARGS__); \
|
||||||
} else { \
|
} else { \
|
||||||
if (get_femto_fd(i) > -1) { \
|
if ((fd & (MARK_TCP_SOCKET | MARK_UDP_SOCKET)) != 0) { \
|
||||||
int __femto_retval = ft_posix_##call(&IPSTACK, fd, ## __VA_ARGS__); \
|
int __femto_retval = ft_##call(IPSTACK, fd, ## __VA_ARGS__); \
|
||||||
if (__femto_retval < 0) { \
|
if (__femto_retval < 0) { \
|
||||||
errno = __femto_retval; \
|
errno = __femto_retval; \
|
||||||
return -1; \
|
return -1; \
|
||||||
} \
|
} \
|
||||||
return __femto_retval; \
|
return __femto_retval; \
|
||||||
}else { \
|
}else { \
|
||||||
return host_##call(i, ## __VA_ARGS__); \
|
return host_##call(fd, ## __VA_ARGS__); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generator for a wrapper function intercepting the return value
|
#define conditional_steal_blocking_call(call, fd, ...) \
|
||||||
* '-11' (EAGAIN). It keeps blocking until the underlying femtoTCP
|
if(in_the_stack) { \
|
||||||
* stack is ready to process the call.
|
return host_##call(fd, ## __VA_ARGS__); \
|
||||||
*/
|
} else { \
|
||||||
#define GEN_SOCKET_CALL(call) \
|
if ((fd & (MARK_TCP_SOCKET | MARK_UDP_SOCKET)) != 0) { \
|
||||||
int ft_posix_##call(struct ipstack *ipstack, int fd, ...) { \
|
int __femto_retval; \
|
||||||
int ret; \
|
do { \
|
||||||
va_list args; \
|
__femto_retval = ft_##call(IPSTACK, fd, ## __VA_ARGS__); \
|
||||||
va_start(args, fd); \
|
if (__femto_retval == -11) { \
|
||||||
do { \
|
usleep(1000); \
|
||||||
ret = call(fd, args); \
|
} \
|
||||||
if (ret == -11) { \
|
} while (__femto_retval == -11); \
|
||||||
pthread_yield(); \
|
if (__femto_retval < 0) { \
|
||||||
|
errno = __femto_retval; \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
return __femto_retval; \
|
||||||
|
}else { \
|
||||||
|
return host_##call(fd, ## __VA_ARGS__); \
|
||||||
} \
|
} \
|
||||||
} while (ret == -11); \
|
}
|
||||||
va_end(args); \
|
|
||||||
return ret; \
|
|
||||||
|
int ft_setsockopt(struct ipstack *ipstack, int fd, int level, int optname, const void *optval, socklen_t optlen) {
|
||||||
|
(void)ipstack;
|
||||||
|
(void)fd;
|
||||||
|
(void)level;
|
||||||
|
(void)optname;
|
||||||
|
(void)optval;
|
||||||
|
(void)optlen;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft_getsockopt(struct ipstack *ipstack, int fd, int level, int optname, void *optval, socklen_t *optlen) {
|
||||||
|
(void)ipstack;
|
||||||
|
(void)fd;
|
||||||
|
(void)level;
|
||||||
|
(void)optname;
|
||||||
|
(void)optval;
|
||||||
|
(void)optlen;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int socket(int domain, int type, int protocol) {
|
||||||
|
if (in_the_stack) {
|
||||||
|
return host_socket(domain, type, protocol);
|
||||||
|
} else {
|
||||||
|
return ft_socket(IPSTACK, domain, type, protocol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int listen(int sockfd, int backlog) {
|
||||||
|
conditional_steal_call(listen, sockfd, backlog);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||||
|
conditional_steal_call(bind, sockfd, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen) {
|
||||||
|
conditional_steal_call(getsockopt, sockfd, level, optname, optval, optlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
|
||||||
|
conditional_steal_call(getpeername, sockfd, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
|
||||||
|
conditional_steal_call(getsockname, sockfd, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) {
|
||||||
|
conditional_steal_call(setsockopt, sockfd, level, optname, optval, optlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int close(int sockfd) {
|
||||||
|
conditional_steal_call(close, sockfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Blocking calls */
|
||||||
|
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
|
||||||
|
conditional_steal_blocking_call(accept, sockfd, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||||
|
conditional_steal_blocking_call(connect, sockfd, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen) {
|
||||||
|
conditional_steal_blocking_call(recvfrom, sockfd, buf, len, flags, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t recv(int sockfd, void *buf, size_t len, int flags) {
|
||||||
|
conditional_steal_blocking_call(recv, sockfd, buf, len, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t read(int sockfd, void *buf, size_t len) {
|
||||||
|
conditional_steal_blocking_call(read, sockfd, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen) {
|
||||||
|
conditional_steal_blocking_call(sendto, sockfd, buf, len, flags, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t send(int sockfd, const void *buf, size_t len, int flags) {
|
||||||
|
conditional_steal_blocking_call(send, sockfd, buf, len, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t write(int sockfd, const void *buf, size_t len) {
|
||||||
|
conditional_steal_blocking_call(write, sockfd, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GEN_SOCKET_CALL(acccept)
|
|
||||||
GEN_SOCKET_CALL(bind)
|
/* Catch-all function to initialize a new tap device as the network interface.
|
||||||
GEN_SOCKET_CALL(close)
|
* This is defined in port/linux.c
|
||||||
GEN_SOCKET_CALL(connect)
|
* */
|
||||||
GEN_SOCKET_CALL(sendto)
|
extern int tap_init(struct ll *dev, const char *name, uint32_t host_ip);
|
||||||
GEN_SOCKET_CALL(recvfrom)
|
|
||||||
|
void *ft_posix_ip_loop(void *arg) {
|
||||||
|
struct ipstack *ipstack = (struct ipstack *)arg;
|
||||||
|
uint32_t ms_next;
|
||||||
|
struct timeval tv;
|
||||||
|
while (1) {
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
ms_next = ipstack_poll(ipstack, tv.tv_sec * 1000 + tv.tv_usec / 1000);
|
||||||
|
usleep(ms_next * 1000);
|
||||||
|
in_the_stack = 1;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__((constructor)) init_femto_posix() {
|
||||||
|
struct in_addr linux_ip;
|
||||||
|
struct ll *tapdev;
|
||||||
|
pthread_t ipstack_thread;
|
||||||
|
if (IPSTACK)
|
||||||
|
return;
|
||||||
|
inet_aton(LINUX_IP, &linux_ip);
|
||||||
|
swap_socketcall(socket, "socket");
|
||||||
|
swap_socketcall(bind, "bind");
|
||||||
|
swap_socketcall(listen, "listen");
|
||||||
|
swap_socketcall(accept, "accept");
|
||||||
|
swap_socketcall(connect, "connect");
|
||||||
|
swap_socketcall(sendto, "sendto");
|
||||||
|
swap_socketcall(recvfrom, "recvfrom");
|
||||||
|
swap_socketcall(recv, "recv");
|
||||||
|
swap_socketcall(send, "send");
|
||||||
|
swap_socketcall(close, "close");
|
||||||
|
swap_socketcall(write, "write");
|
||||||
|
swap_socketcall(read, "read");
|
||||||
|
swap_socketcall(getsockname, "getsockname");
|
||||||
|
swap_socketcall(getpeername, "getpeername");
|
||||||
|
swap_socketcall(setsockopt, "getaddrinfo");
|
||||||
|
swap_socketcall(getsockopt, "freeaddrinfo");
|
||||||
|
ipstack_init_static(&IPSTACK);
|
||||||
|
tapdev = ipstack_getdev(IPSTACK);
|
||||||
|
if (tap_init(tapdev, "femt0", linux_ip.s_addr) < 0) {
|
||||||
|
perror("tap init");
|
||||||
|
}
|
||||||
|
ipstack_ipconfig_set(IPSTACK, atoip4(FEMTOTCP_IP), atoip4("255.255.255.0"),
|
||||||
|
atoip4(LINUX_IP));
|
||||||
|
printf("IP: manually configured - %s\n", FEMTOTCP_IP);
|
||||||
|
sleep(1);
|
||||||
|
pthread_create(&ipstack_thread, NULL, ft_posix_ip_loop, IPSTACK);
|
||||||
|
in_the_stack = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
65
src/test/tcp_echo.c
Normal file
65
src/test/tcp_echo.c
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#define PORT 8
|
||||||
|
#define BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int server_fd, client_fd;
|
||||||
|
struct sockaddr_in address;
|
||||||
|
int addrlen = sizeof(address);
|
||||||
|
char buffer[BUFFER_SIZE];
|
||||||
|
|
||||||
|
// Create a socket
|
||||||
|
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
|
||||||
|
perror("Socket failed");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
printf("Socket created: %d\n", server_fd);
|
||||||
|
|
||||||
|
// Bind to the specified port
|
||||||
|
address.sin_family = AF_INET;
|
||||||
|
address.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
address.sin_port = htons(PORT);
|
||||||
|
|
||||||
|
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
|
||||||
|
perror("Bind failed");
|
||||||
|
close(server_fd);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
printf("Bind successful\n");
|
||||||
|
|
||||||
|
// Start listening for incoming connections
|
||||||
|
if (listen(server_fd, 3) < 0) {
|
||||||
|
perror("Listen failed");
|
||||||
|
close(server_fd);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
printf("Echo server listening on port %d\n", PORT);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
// Accept a client connection
|
||||||
|
if ((client_fd = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0) {
|
||||||
|
perror("Accept failed");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Client connected, fd: %d\n", client_fd);
|
||||||
|
|
||||||
|
ssize_t bytes_read;
|
||||||
|
while ((bytes_read = read(client_fd, buffer, BUFFER_SIZE)) > 0) {
|
||||||
|
write(client_fd, buffer, bytes_read); // Echo data back to the client
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Client disconnected\n");
|
||||||
|
close(client_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(server_fd);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -3,15 +3,14 @@
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "femtotcp.h"
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "femtotcp.h"
|
||||||
|
|
||||||
//#define DHCP
|
//#define DHCP
|
||||||
#define FEMTOTCP_IP "10.10.10.2"
|
|
||||||
#define LINUX_IP "10.10.10.1"
|
|
||||||
#define TEST_SIZE (8 * 1024)
|
#define TEST_SIZE (8 * 1024)
|
||||||
|
|
||||||
#define BUFFER_SIZE TEST_SIZE
|
#define BUFFER_SIZE TEST_SIZE
|
||||||
|
|
Loading…
Reference in a new issue