diff --git a/adsbus/Makefile b/adsbus/Makefile index 2905d4c..bbbeaf9 100644 --- a/adsbus/Makefile +++ b/adsbus/Makefile @@ -6,7 +6,7 @@ LIBS ?= -ljansson -lprotobuf-c OBJ_NETWORK = incoming.o outgoing.o receive.o send.o OBJ_PROTOCOL = airspy_adsb.o beast.o json.o proto.o raw.o stats.o -OBJ_UTIL = buf.o hex.o opts.o packet.o peer.o rand.o resolve.o server.o socket.o uuid.o wakeup.o +OBJ_UTIL = buf.o hex.o list.o opts.o packet.o peer.o rand.o resolve.o server.o socket.o uuid.o wakeup.o OBJ_PROTO = adsb.pb-c.o all: adsbus diff --git a/adsbus/incoming.c b/adsbus/incoming.c index 531ed78..ffb9b52 100644 --- a/adsbus/incoming.c +++ b/adsbus/incoming.c @@ -8,6 +8,7 @@ #include #include +#include "list.h" #include "peer.h" #include "resolve.h" #include "socket.h" @@ -27,10 +28,10 @@ struct incoming { incoming_connection_handler handler; void *passthrough; uint32_t *count; - struct incoming *next; + struct list_head incoming_list; }; -static struct incoming *incoming_head = NULL; +static struct list_head incoming_head = LIST_HEAD_INIT(incoming_head); static void incoming_resolve_wrapper(struct peer *); @@ -137,11 +138,9 @@ static void incoming_resolve_wrapper(struct peer *peer) { } void incoming_cleanup() { - struct incoming *iter = incoming_head; - while (iter) { - struct incoming *next = iter->next; + struct incoming *iter, *next; + list_for_each_entry_safe(iter, next, &incoming_head, incoming_list) { incoming_del(iter); - iter = next; } } @@ -158,8 +157,7 @@ void incoming_new(char *node, char *service, incoming_connection_handler handler incoming->passthrough = passthrough; incoming->count = count; - incoming->next = incoming_head; - incoming_head = incoming; + list_add(&incoming->incoming_list, &incoming_head); incoming_resolve(incoming); } diff --git a/adsbus/list.c b/adsbus/list.c new file mode 100644 index 0000000..f8c2873 --- /dev/null +++ b/adsbus/list.c @@ -0,0 +1,24 @@ +#include + +#include "list.h" + +void list_head_init(struct list_head *head) { + head->next = head->prev = head; +} + +bool list_is_empty(const struct list_head *head) { + return head->next == head; +} + +void list_add(struct list_head *new, struct list_head *head) { + new->next = head; + new->prev = head->prev; + new->prev->next = new; + head->prev = new; +} + +void list_del(struct list_head *entry) { + entry->next->prev = entry->prev; + entry->prev->next = entry->next; + entry->prev = entry->next = NULL; +} diff --git a/adsbus/list.h b/adsbus/list.h new file mode 100644 index 0000000..68417f9 --- /dev/null +++ b/adsbus/list.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +#pragma GCC diagnostic ignored "-Wcast-align" +#pragma GCC diagnostic ignored "-Wgnu-statement-expression" +#pragma GCC diagnostic ignored "-Wlanguage-extension-token" + +#define offset_of(type, member) ((size_t) &((type *) NULL)->member) + +#define container_of(ptr, type, member) ({ \ + typeof( ((type *) NULL)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offset_of(type, member) );}) + +struct list_head { + struct list_head *next; + struct list_head *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +void list_head_init(struct list_head *); +bool list_is_empty(const struct list_head *); +void list_add(struct list_head *, struct list_head *); +void list_del(struct list_head *); diff --git a/adsbus/outgoing.c b/adsbus/outgoing.c index fc6b5d0..77f8f50 100644 --- a/adsbus/outgoing.c +++ b/adsbus/outgoing.c @@ -8,6 +8,7 @@ #include #include +#include "list.h" #include "peer.h" #include "resolve.h" #include "socket.h" @@ -28,10 +29,10 @@ struct outgoing { outgoing_connection_handler handler; void *passthrough; uint32_t *count; - struct outgoing *next; + struct list_head outgoing_list; }; -static struct outgoing *outgoing_head = NULL; +static struct list_head outgoing_head = LIST_HEAD_INIT(outgoing_head); static void outgoing_connect_result(struct outgoing *, int); static void outgoing_resolve(struct outgoing *); @@ -147,11 +148,9 @@ static void outgoing_del(struct outgoing *outgoing) { } void outgoing_cleanup() { - struct outgoing *iter = outgoing_head; - while (iter) { - struct outgoing *next = iter->next; + struct outgoing *iter, *next; + list_for_each_entry_safe(iter, next, &outgoing_head, outgoing_list) { outgoing_del(iter); - iter = next; } } @@ -167,8 +166,7 @@ void outgoing_new(char *node, char *service, outgoing_connection_handler handler outgoing->passthrough = passthrough; outgoing->count = count; - outgoing->next = outgoing_head; - outgoing_head = outgoing; + list_add(&outgoing->outgoing_list, &outgoing_head); outgoing_resolve(outgoing); } diff --git a/adsbus/send.c b/adsbus/send.c index 466f3b2..9f538b0 100644 --- a/adsbus/send.c +++ b/adsbus/send.c @@ -13,6 +13,7 @@ #include "beast.h" #include "buf.h" #include "json.h" +#include "list.h" #include "peer.h" #include "proto.h" #include "raw.h" @@ -26,15 +27,14 @@ struct send { struct peer *on_close; uint8_t id[UUID_LEN]; struct serializer *serializer; - struct send *prev; - struct send *next; + struct list_head send_list; }; typedef void (*serialize)(struct packet *, struct buf *); static struct serializer { char *name; serialize serialize; - struct send *send_head; + struct list_head send_head; } serializers[] = { { .name = "airspy_adsb", @@ -68,14 +68,7 @@ static void send_del(struct send *send) { peer_count_out--; peer_epoll_del((struct peer *) send); assert(!close(send->peer.fd)); - if (send->prev) { - send->prev->next = send->next; - } else { - send->serializer->send_head = send->next; - } - if (send->next) { - send->next->prev = send->prev; - } + list_del(&send->send_list); peer_call(send->on_close); free(send); } @@ -98,13 +91,17 @@ static bool send_hello(int fd, struct serializer *serializer) { void send_init() { assert(signal(SIGPIPE, SIG_IGN) != SIG_ERR); + for (size_t i = 0; i < NUM_SERIALIZERS; i++) { + list_head_init(&serializers[i].send_head); + } } void send_cleanup() { for (size_t i = 0; i < NUM_SERIALIZERS; i++) { struct serializer *serializer = &serializers[i]; - while (serializer->send_head) { - send_del(serializer->send_head); + struct send *iter, *next; + list_for_each_entry_safe(iter, next, &serializer->send_head, send_list) { + send_del(iter); } } } @@ -132,12 +129,7 @@ void send_new(int fd, struct serializer *serializer, struct peer *on_close) { send->on_close = on_close; uuid_gen(send->id); send->serializer = serializer; - send->prev = NULL; - send->next = serializer->send_head; - if (send->next) { - send->next->prev = send; - } - serializer->send_head = send; + list_add(&send->send_list, &serializer->send_head); peer_epoll_add((struct peer *) send, 0); @@ -157,7 +149,7 @@ void send_new_wrapper(int fd, void *passthrough, struct peer *on_close) { void send_write(struct packet *packet) { for (size_t i = 0; i < NUM_SERIALIZERS; i++) { struct serializer *serializer = &serializers[i]; - if (serializer->send_head == NULL) { + if (list_is_empty(&serializer->send_head)) { continue; } struct buf buf = BUF_INIT; @@ -165,14 +157,13 @@ void send_write(struct packet *packet) { if (buf.length == 0) { continue; } - struct send *send = serializer->send_head; - while (send) { - if (write(send->peer.fd, buf_at(&buf, 0), buf.length) != (ssize_t) buf.length) { + struct send *iter, *next; + list_for_each_entry_safe(iter, next, &serializer->send_head, send_list) { + if (write(iter->peer.fd, buf_at(&buf, 0), buf.length) != (ssize_t) buf.length) { // peer_loop() will see this shutdown and call send_del - int res = shutdown(send->peer.fd, SHUT_WR); + int res = shutdown(iter->peer.fd, SHUT_WR); assert(res == 0 || (res == -1 && errno == ENOTSOCK)); } - send = send->next; } } }