moved include/microtcp.h to src/microtcp.h and fixed some mux bugs

This commit is contained in:
cozis
2023-05-19 22:11:47 +02:00
parent 464a1ee724
commit 6a4f644cc5
6 changed files with 141 additions and 119 deletions
+3 -3
View File
@@ -48,7 +48,7 @@ MEMDBG=valgrind
LIBDIR = 3p/lib LIBDIR = 3p/lib
INCDIR = 3p/include INCDIR = 3p/include
CFLAGS = $(CFLAGS_PLATFORM) -I$(INCDIR) -Iinclude/ -Wall -Wextra -DARP_DEBUG -DMICROTCP_DEBUG -DIP_DEBUG -DICMP_DEBUG -DTCP_DEBUG -DMICROTCP_BACKGROUND_THREAD -DMICROTCP_USING_TAP -DMICROTCP_USING_MUX CFLAGS = $(CFLAGS_PLATFORM) -I$(INCDIR) -Ibuild/ -Wall -Wextra -DARP_DEBUG -DMICROTCP_DEBUG -DIP_DEBUG -DICMP_DEBUG -DTCP_DEBUG -DMICROTCP_BACKGROUND_THREAD -DMICROTCP_USING_TAP -DMICROTCP_USING_MUX
LFLAGS = -ltuntap $(LFLAGS_PLATFORM) -L$(LIBDIR) LFLAGS = -ltuntap $(LFLAGS_PLATFORM) -L$(LIBDIR)
ifeq ($(MEMDBG),drmemory) ifeq ($(MEMDBG),drmemory)
@@ -91,11 +91,11 @@ build/echo_tcp: examples/echo_tcp.c $(LIBDIR)/libtuntap.a 3p/include/tuntap.h 3p
mkdir -p $(@D) mkdir -p $(@D)
gcc build/microtcp.c examples/echo_tcp.c -o $@ $(CFLAGS) $(LFLAGS) gcc build/microtcp.c examples/echo_tcp.c -o $@ $(CFLAGS) $(LFLAGS)
build/microtcp.h: include/microtcp.h build/microtcp.h: src/microtcp.h
mkdir -p $(@D) mkdir -p $(@D)
[ ! -e $@ ] || rm $@ [ ! -e $@ ] || rm $@
echo "#define MICROTCP_AMALGAMATION" >> $@ echo "#define MICROTCP_AMALGAMATION" >> $@
cat include/microtcp.h >> $@ cat src/microtcp.h >> $@
build/microtcp.c: 3p/include/tinycthread.h 3p/src/tinycthread.c $(wildcard src/*.c src/*.h) build/microtcp.c: 3p/include/tinycthread.h 3p/src/tinycthread.c $(wildcard src/*.c src/*.h)
mkdir -p $(@D) mkdir -p $(@D)
+3 -3
View File
@@ -697,7 +697,7 @@ arp_process_result_t arp_process_packet(arp_state_t *state, const void *packet,
ARP_DEBUG_LOG("Invalid hardware or protocol address size %d or %d (expected %d and %d)", packet2->hardware_len, packet2->protocol_len, 6, 4); ARP_DEBUG_LOG("Invalid hardware or protocol address size %d or %d (expected %d and %d)", packet2->hardware_len, packet2->protocol_len, 6, 4);
return ARP_PROCESS_RESULT_INVALID; return ARP_PROCESS_RESULT_INVALID;
} }
/*
ARP_DEBUG_LOG("ARP from %d.%d.%d.%d to %d.%d.%d.%d", ARP_DEBUG_LOG("ARP from %d.%d.%d.%d to %d.%d.%d.%d",
((uint8_t*) &packet2->sender_protocol_address)[0], ((uint8_t*) &packet2->sender_protocol_address)[0],
((uint8_t*) &packet2->sender_protocol_address)[1], ((uint8_t*) &packet2->sender_protocol_address)[1],
@@ -707,7 +707,7 @@ arp_process_result_t arp_process_packet(arp_state_t *state, const void *packet,
((uint8_t*) &packet2->target_protocol_address)[1], ((uint8_t*) &packet2->target_protocol_address)[1],
((uint8_t*) &packet2->target_protocol_address)[2], ((uint8_t*) &packet2->target_protocol_address)[2],
((uint8_t*) &packet2->target_protocol_address)[3]); ((uint8_t*) &packet2->target_protocol_address)[3]);
*/
bool merge = arp_translation_table_update(&state->table, packet2->sender_hardware_address, bool merge = arp_translation_table_update(&state->table, packet2->sender_hardware_address,
packet2->sender_protocol_address, state->cache_timeout); packet2->sender_protocol_address, state->cache_timeout);
@@ -740,7 +740,7 @@ arp_process_result_t arp_process_packet(arp_state_t *state, const void *packet,
state->send(state->send_data, packet2->sender_hardware_address); state->send(state->send_data, packet2->sender_hardware_address);
} }
} else { } else {
ARP_DEBUG_LOG("Request not for me"); //ARP_DEBUG_LOG("Request not for me");
} }
return ARP_PROCESS_RESULT_OK; return ARP_PROCESS_RESULT_OK;
+3 -3
View File
@@ -252,7 +252,7 @@ void ip_process_packet(ip_state_t *ip_state, const void *packet, size_t len)
IP_DEBUG_LOG("Dropping IP packet with invalid checksum"); IP_DEBUG_LOG("Dropping IP packet with invalid checksum");
return; return;
} }
/*
IP_DEBUG_LOG("Received packet for %d.%d.%d.%d (I'm %d.%d.%d.%d)", IP_DEBUG_LOG("Received packet for %d.%d.%d.%d (I'm %d.%d.%d.%d)",
((uint8_t*) &packet2->dst_ip)[0], ((uint8_t*) &packet2->dst_ip)[0],
((uint8_t*) &packet2->dst_ip)[1], ((uint8_t*) &packet2->dst_ip)[1],
@@ -262,9 +262,9 @@ void ip_process_packet(ip_state_t *ip_state, const void *packet, size_t len)
((uint8_t*) &ip_state->ip)[1], ((uint8_t*) &ip_state->ip)[1],
((uint8_t*) &ip_state->ip)[2], ((uint8_t*) &ip_state->ip)[2],
((uint8_t*) &ip_state->ip)[3]); ((uint8_t*) &ip_state->ip)[3]);
*/
if (packet2->dst_ip != ip_state->ip) { if (packet2->dst_ip != ip_state->ip) {
IP_DEBUG_LOG("Packet not for me"); // IP_DEBUG_LOG("Packet not for me");
return; return;
} }
+51 -30
View File
@@ -1132,6 +1132,8 @@ microtcp_mux_t *microtcp_mux_create(microtcp_t *mtcp)
return mux; return mux;
} }
static bool mux_poll(microtcp_mux_t *mux, microtcp_muxevent_t *ev);
void microtcp_mux_destroy(microtcp_mux_t *mux) void microtcp_mux_destroy(microtcp_mux_t *mux)
{ {
// Unregister all idle sockets // Unregister all idle sockets
@@ -1144,7 +1146,7 @@ void microtcp_mux_destroy(microtcp_mux_t *mux)
// Consume all previously reported events // Consume all previously reported events
// to make sure that when unregistering // to make sure that when unregistering
// the entries are actually removed // the entries are actually removed
while (microtcp_mux_poll(mux, NULL)); while (mux_poll(mux, NULL));
// Unreagister all sockets that have events // Unreagister all sockets that have events
while (mux->ready_queue_head) { while (mux->ready_queue_head) {
@@ -1181,6 +1183,8 @@ move_mux_entry_to_free_list(mux_entry_t *entry)
microtcp_mux_t *mux = entry->mux; microtcp_mux_t *mux = entry->mux;
// If the entry is in a list, unlink it // If the entry is in a list, unlink it
if (mux->ready_queue_tail == entry)
mux->ready_queue_tail = entry->mux_next;
if (entry->mux_prev) if (entry->mux_prev)
*entry->mux_prev = entry->mux_next; *entry->mux_prev = entry->mux_next;
if (entry->sock_prev) if (entry->sock_prev)
@@ -1197,6 +1201,8 @@ move_mux_entry_to_free_list(mux_entry_t *entry)
static void static void
move_mux_entry_to_idle_list(mux_entry_t *entry) move_mux_entry_to_idle_list(mux_entry_t *entry)
{ {
microtcp_mux_t *mux = entry->mux;
// To be moved to the idle list the entry // To be moved to the idle list the entry
// must be associated to a socket so it // must be associated to a socket so it
// must be in a socket mux list, therefore // must be in a socket mux list, therefore
@@ -1205,11 +1211,12 @@ move_mux_entry_to_idle_list(mux_entry_t *entry)
// Make sure the entry is unlinked relative // Make sure the entry is unlinked relative
// to the lists in the mux // to the lists in the mux
if (mux->ready_queue_tail == entry)
mux->ready_queue_tail = entry->mux_next;
if (entry->mux_prev) if (entry->mux_prev)
*entry->mux_prev = entry->mux_next; *entry->mux_prev = entry->mux_next;
// Now actually insert it into the idle list // Now actually insert it into the idle list
microtcp_mux_t *mux = entry->mux;
entry->mux_prev = &mux->idle_list; entry->mux_prev = &mux->idle_list;
entry->mux_next = mux->idle_list; entry->mux_next = mux->idle_list;
if (mux->idle_list) if (mux->idle_list)
@@ -1286,15 +1293,17 @@ bool microtcp_mux_register(microtcp_mux_t *mux, microtcp_socket_t *sock, int eve
// Push it into the idle list of the mux // Push it into the idle list of the mux
entry->mux_prev = &mux->idle_list; entry->mux_prev = &mux->idle_list;
entry->mux_next = mux->idle_list; entry->mux_next = mux->idle_list;
if (mux->idle_list) if (mux->idle_list)
mux->idle_list->mux_prev = &entry->mux_next; mux->idle_list->mux_prev = &entry->mux_next;
mux->idle_list = entry;
// Push it into the socket mux list // Push it into the socket mux list
entry->sock_prev = &sock->mux_list; entry->sock_prev = &sock->mux_list;
entry->sock_next = sock->mux_list; entry->sock_next = sock->mux_list;
if (sock->mux_list) if (sock->mux_list)
sock->mux_list->sock_prev = &entry->sock_next; sock->mux_list->sock_prev = &entry->sock_next;
sock->mux_list = entry;
// Initialize the entry // Initialize the entry
entry->sock = sock; entry->sock = sock;
@@ -1312,17 +1321,14 @@ bool microtcp_mux_register(microtcp_mux_t *mux, microtcp_socket_t *sock, int eve
return true; return true;
} }
bool microtcp_mux_poll(microtcp_mux_t *mux, microtcp_muxevent_t *ev) static bool mux_poll(microtcp_mux_t *mux, microtcp_muxevent_t *ev)
{ {
LOCK_WHEN_THREADED(mux->mtcp);
if (!mux->ready_queue_head)
return false; // No events occurred
// Get the tail of the queue (without popping it) // Get the tail of the queue (without popping it)
mux_entry_t *entry = mux->ready_queue_tail; mux_entry_t *entry = mux->ready_queue_head;
if (!entry) {
UNLOCK_WHEN_THREADED(mux->mtcp);
return false; // No events occurred
}
// If this socket was in the ready queue // If this socket was in the ready queue
// it must have triggered events // it must have triggered events
@@ -1347,7 +1353,6 @@ bool microtcp_mux_poll(microtcp_mux_t *mux, microtcp_muxevent_t *ev)
// we put the entry into the idle list // we put the entry into the idle list
move_mux_entry_to_idle_list(entry); move_mux_entry_to_idle_list(entry);
UNLOCK_WHEN_THREADED(mux->mtcp);
return true; return true;
} }
@@ -1355,13 +1360,16 @@ bool microtcp_mux_wait(microtcp_mux_t *mux, microtcp_muxevent_t *ev)
{ {
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
LOCK_WHEN_THREADED(mux->mtcp); LOCK_WHEN_THREADED(mux->mtcp);
while (!microtcp_mux_poll(mux, ev)) while (!mux_poll(mux, ev)) {
MICROTCP_DEBUG_LOG("Multiplexer waiting for an event");
if (cnd_wait(&mux->queue_not_empty, &mux->mtcp->lock) != thrd_success) if (cnd_wait(&mux->queue_not_empty, &mux->mtcp->lock) != thrd_success)
abort(); abort();
MICROTCP_DEBUG_LOG("Multiplexer woke up for an event");
}
UNLOCK_WHEN_THREADED(mux->mtcp); UNLOCK_WHEN_THREADED(mux->mtcp);
return true; return true;
#else #else
return microtcp_mux_poll(mux, ev); return mux_poll(mux, ev);
#endif #endif
} }
@@ -1372,45 +1380,58 @@ signal_events_to_muxes_associated_to_socket(microtcp_socket_t *socket, int event
assert(events); // If no events need to be signaled then assert(events); // If no events need to be signaled then
// this function has no reason to be called. // this function has no reason to be called.
MICROTCP_DEBUG_LOG("Socket about to signal to multiplexers");
mux_entry_t *entry = socket->mux_list; mux_entry_t *entry = socket->mux_list;
while (entry) { while (entry) {
microtcp_mux_t *mux = entry->mux; microtcp_mux_t *mux = entry->mux;
bool first_event_of_socket = (entry->triggered_events == 0); // Mask the bitmask of triggered events [events] with
entry->triggered_events |= events & entry->events_of_interest; // the bitmask of events that this multiplexer is
// interested in.
int newly_triggered_events = events & entry->events_of_interest;
if (first_event_of_socket) { // If there are no previously triggered events by this
// socket and the socket just generated some events the
// mux is interested in, then we need to move the socket-mux
// structure from the idle list to the ready queue of the mux.
bool first_event_of_socket_in_mux = (entry->triggered_events == 0) && newly_triggered_events;
entry->triggered_events |= newly_triggered_events;
if (first_event_of_socket_in_mux) {
// Is this the first socket structure of the muxes
// ready queue? If it is, we'll need to wake it up
bool queue_was_empty = (mux->ready_queue_head == NULL); bool queue_was_empty = (mux->ready_queue_head == NULL);
// No entries were already triggered so // Unlink it from the idle list
// it's necessary to move the entry from
// the mux's idle list to ready queue
// Unlink it from the idle queue
*entry->mux_prev = entry->mux_next; *entry->mux_prev = entry->mux_next;
if (entry->mux_next) if (entry->mux_next)
entry->mux_next->mux_prev = entry->mux_prev; entry->mux_next->mux_prev = entry->mux_prev;
// Add it to the queue // Add it to the queue
entry->mux_prev = &mux->ready_queue_head; if (mux->ready_queue_tail)
entry->mux_next = mux->ready_queue_head; entry->mux_prev = &mux->ready_queue_tail->mux_next;
if (mux->ready_queue_head) else {
mux->ready_queue_head->mux_prev = &entry->mux_next; entry->mux_prev = &mux->ready_queue_head;
else mux->ready_queue_head = entry;
mux->ready_queue_tail = entry; }
mux->ready_queue_head = entry; entry->mux_next = NULL;
mux->ready_queue_tail = entry;
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
MICROTCP_DEBUG_LOG("Signaling event to multiplexer");
if (queue_was_empty) if (queue_was_empty)
cnd_signal(&mux->queue_not_empty); cnd_signal(&mux->queue_not_empty);
MICROTCP_DEBUG_LOG("Signaled event to multiplexer");
#else #else
(void) queue_was_empty; (void) queue_was_empty;
#endif #endif
} }
entry = entry->sock_next; entry = entry->sock_next;
} }
MICROTCP_DEBUG_LOG("Socket signaled to multiplexers");
} }
#endif #endif
+78 -79
View File
@@ -1,80 +1,79 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <assert.h> #include <assert.h>
#include <stdbool.h> #include <stdbool.h>
typedef struct microtcp_t microtcp_t; typedef struct microtcp_t microtcp_t;
typedef struct microtcp_socket_t microtcp_socket_t; typedef struct microtcp_socket_t microtcp_socket_t;
#define MICROTCP_MAX_BUFFERS 8 #define MICROTCP_MAX_BUFFERS 8
#define MICROTCP_MAX_SOCKETS 32 #define MICROTCP_MAX_SOCKETS 32
#define MICROTCP_MAX_MUX_ENTRIES 32 #define MICROTCP_MAX_MUX_ENTRIES 32
typedef enum { typedef enum {
MICROTCP_ERRCODE_NONE = 0, MICROTCP_ERRCODE_NONE = 0,
// Returned by microtcp_open and microtcp_accept // Returned by microtcp_open and microtcp_accept
MICROTCP_ERRCODE_SOCKETLIMIT, MICROTCP_ERRCODE_SOCKETLIMIT,
// Returned by microtcp_open // Returned by microtcp_open
MICROTCP_ERRCODE_TCPERROR, MICROTCP_ERRCODE_TCPERROR,
MICROTCP_ERRCODE_BADCONDVAR, MICROTCP_ERRCODE_BADCONDVAR,
// Returned by microtcp_accept // Returned by microtcp_accept
MICROTCP_ERRCODE_NOTLISTENER, MICROTCP_ERRCODE_NOTLISTENER,
MICROTCP_ERRCODE_CANTBLOCK, MICROTCP_ERRCODE_CANTBLOCK,
// Returned by microtcp_recv and microtcp_send // Returned by microtcp_recv and microtcp_send
MICROTCP_ERRCODE_NOTCONNECTION, MICROTCP_ERRCODE_NOTCONNECTION,
// Returned by microtcp_accept, microtcp_recv and microtcp_send // Returned by microtcp_accept, microtcp_recv and microtcp_send
MICROTCP_ERRCODE_WOULDBLOCK, MICROTCP_ERRCODE_WOULDBLOCK,
} microtcp_errcode_t; } microtcp_errcode_t;
typedef struct { typedef struct {
void *data; void *data;
void (*free)(void *data); void (*free)(void *data);
int (*send)(void *data, const void *src, size_t len); int (*send)(void *data, const void *src, size_t len);
int (*recv)(void *data, void *dst, size_t len); int (*recv)(void *data, void *dst, size_t len);
} microtcp_callbacks_t; } microtcp_callbacks_t;
#ifdef MICROTCP_USING_TAP #ifdef MICROTCP_USING_TAP
bool microtcp_callbacks_create_for_tap(const char *ip, const char *mac, microtcp_callbacks_t *callbacks); bool microtcp_callbacks_create_for_tap(const char *ip, const char *mac, microtcp_callbacks_t *callbacks);
microtcp_t *microtcp_create(const char *tap_ip, const char *stack_ip, const char *tap_mac, const char *stack_mac); microtcp_t *microtcp_create(const char *tap_ip, const char *stack_ip, const char *tap_mac, const char *stack_mac);
#endif #endif
microtcp_t *microtcp_create_using_callbacks(const char *ip, const char *mac, microtcp_callbacks_t callbacks); microtcp_t *microtcp_create_using_callbacks(const char *ip, const char *mac, microtcp_callbacks_t callbacks);
void microtcp_destroy(microtcp_t *mtcp); void microtcp_destroy(microtcp_t *mtcp);
const char *microtcp_strerror(microtcp_errcode_t errcode); const char *microtcp_strerror(microtcp_errcode_t errcode);
microtcp_socket_t *microtcp_open(microtcp_t *mtcp, uint16_t port, microtcp_errcode_t *errcode); microtcp_socket_t *microtcp_open(microtcp_t *mtcp, uint16_t port, microtcp_errcode_t *errcode);
microtcp_socket_t *microtcp_accept(microtcp_socket_t *socket, bool no_block, microtcp_errcode_t *errcode); microtcp_socket_t *microtcp_accept(microtcp_socket_t *socket, bool no_block, microtcp_errcode_t *errcode);
void microtcp_close(microtcp_socket_t *socket); void microtcp_close(microtcp_socket_t *socket);
size_t microtcp_send(microtcp_socket_t *socket, const void *src, size_t len, bool no_block, microtcp_errcode_t *errcode); size_t microtcp_send(microtcp_socket_t *socket, const void *src, size_t len, bool no_block, microtcp_errcode_t *errcode);
size_t microtcp_recv(microtcp_socket_t *socket, void *dst, size_t len, bool no_block, microtcp_errcode_t *errcode); size_t microtcp_recv(microtcp_socket_t *socket, void *dst, size_t len, bool no_block, microtcp_errcode_t *errcode);
void microtcp_step(microtcp_t *mtcp); void microtcp_step(microtcp_t *mtcp);
void microtcp_process_packet(microtcp_t *mtcp, const void *packet, size_t len); void microtcp_process_packet(microtcp_t *mtcp, const void *packet, size_t len);
#ifdef MICROTCP_USING_MUX #ifdef MICROTCP_USING_MUX
typedef enum { typedef enum {
MICROTCP_MUX_ACCEPT = 1, MICROTCP_MUX_ACCEPT = 1,
MICROTCP_MUX_RECV = 2, MICROTCP_MUX_RECV = 2,
MICROTCP_MUX_SEND = 4, MICROTCP_MUX_SEND = 4,
} microtcp_muxeventid_t; } microtcp_muxeventid_t;
typedef struct { typedef struct {
void *userp; void *userp;
int events; int events;
microtcp_socket_t *socket; microtcp_socket_t *socket;
} microtcp_muxevent_t; } microtcp_muxevent_t;
typedef struct microtcp_mux_t microtcp_mux_t; typedef struct microtcp_mux_t microtcp_mux_t;
microtcp_mux_t *microtcp_mux_create(microtcp_t *mtcp); microtcp_mux_t *microtcp_mux_create(microtcp_t *mtcp);
void microtcp_mux_destroy(microtcp_mux_t *mux); void microtcp_mux_destroy(microtcp_mux_t *mux);
bool microtcp_mux_register(microtcp_mux_t *mux, microtcp_socket_t *sock, int events, void *userp); bool microtcp_mux_register(microtcp_mux_t *mux, microtcp_socket_t *sock, int events, void *userp);
bool microtcp_mux_unregister(microtcp_mux_t *mux, microtcp_socket_t *sock, int events); bool microtcp_mux_unregister(microtcp_mux_t *mux, microtcp_socket_t *sock, int events);
bool microtcp_mux_poll(microtcp_mux_t *mux, microtcp_muxevent_t *ev); bool microtcp_mux_wait(microtcp_mux_t *mux, microtcp_muxevent_t *ev);
bool microtcp_mux_wait(microtcp_mux_t *mux, microtcp_muxevent_t *ev);
#endif #endif
+3 -1
View File
@@ -311,7 +311,7 @@ move_from_non_established_list_to_non_accepted_queue(tcp_connection_t *connectio
void tcp_process_segment(tcp_state_t *state, ip_address_t sender, void tcp_process_segment(tcp_state_t *state, ip_address_t sender,
tcp_segment_t *segment, size_t len) tcp_segment_t *segment, size_t len)
{ {
TCP_DEBUG_LOG("Received TCP segment"); // TCP_DEBUG_LOG("Received TCP segment");
assert(len >= sizeof(tcp_segment_t)); assert(len >= sizeof(tcp_segment_t));
size_t data_offset = SEGMENT_OFFSET(segment) * sizeof(uint32_t); // Length (in bytes) of the TCP header, size_t data_offset = SEGMENT_OFFSET(segment) * sizeof(uint32_t); // Length (in bytes) of the TCP header,
@@ -320,6 +320,8 @@ void tcp_process_segment(tcp_state_t *state, ip_address_t sender,
size_t options_len = data_offset - sizeof(tcp_segment_t); // The number of bytes of the options is size_t options_len = data_offset - sizeof(tcp_segment_t); // The number of bytes of the options is
// the size of the whole header minus the // the size of the whole header minus the
// size of the header without options. // size of the header without options.
(void) options_len;
size_t payload_size = len - data_offset; size_t payload_size = len - data_offset;
void *payload_addr = (uint8_t*) segment + data_offset; // The segment->payload doesn't refer to the void *payload_addr = (uint8_t*) segment + data_offset; // The segment->payload doesn't refer to the
// first byte of the payload but to the first // first byte of the payload but to the first