diff --git a/Makefile b/Makefile index c89e29a..1682c95 100644 --- a/Makefile +++ b/Makefile @@ -10,5 +10,5 @@ clean: %.o: %.c *.h $(CC) -c $(CFLAGS) $< -o $@ -adsbus: adsbus.o airspy_adsb.o common.o - $(CC) $(LDFLAGS) -o adsbus adsbus.o airspy_adsb.o common.o +adsbus: adsbus.o backend.o airspy_adsb.o common.o + $(CC) $(LDFLAGS) -o adsbus adsbus.o backend.o airspy_adsb.o common.o diff --git a/adsbus.c b/adsbus.c index d041a53..f177b75 100644 --- a/adsbus.c +++ b/adsbus.c @@ -2,11 +2,6 @@ #include #include #include -#include -#include -#include -#include -#include #include #include "common.h" @@ -18,31 +13,10 @@ struct opts { char *backend_service; }; -static parser parsers[] = { - airspy_adsb_parse, -}; -#define NUM_PARSERS (sizeof(parsers) / sizeof(*parsers)) - struct client { int placeholder; }; -struct peer { - enum { - BACKEND, - CLIENT, - } type; - int fd; - union { - struct backend backend; - struct client client; - }; -}; -#define PEER_BACKEND_INIT { \ - .type = BACKEND, \ - .backend = BACKEND_INIT, \ -} - static int parse_opts(int argc, char *argv[], struct opts *opts) { int opt; @@ -63,89 +37,11 @@ static int parse_opts(int argc, char *argv[], struct opts *opts) { return 0; } -static int connect_backend(struct opts *opts) { - struct addrinfo hints = { - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_STREAM, - }; - - struct addrinfo *addrs; - - int gai_err = getaddrinfo(opts->backend_node, opts->backend_service, &hints, &addrs); - if (gai_err) { - fprintf(stderr, "getaddrinfo(%s/%s): %s\n", opts->backend_node, opts->backend_service, gai_strerror(gai_err)); - return -1; - } - - int bfd; - struct addrinfo *addr; - for (addr = addrs; addr != NULL; addr = addr->ai_next) { - bfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); - if (bfd == -1) { - perror("socket"); - continue; - } - - if (connect(bfd, addr->ai_addr, addr->ai_addrlen) != -1) { - break; - } - - close(bfd); - } - - if (addr == NULL) { - freeaddrinfo(addrs); - fprintf(stderr, "Can't connect to %s/%s\n", opts->backend_node, opts->backend_service); - return -1; - } - - char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; - if (getnameinfo(addr->ai_addr, addr->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) { - fprintf(stderr, "Connected to %s/%s\n", hbuf, sbuf); - } - - freeaddrinfo(addrs); - - return bfd; -} - -bool backend_autodetect_parse(struct backend *backend, struct packet *packet) { - for (int i = 0; i < NUM_PARSERS; i++) { - if (parsers[i](backend, packet)) { - backend->parser = parsers[i]; - return true; - } - } - return false; -} - -static int loop(int bfd) { - struct peer backend = PEER_BACKEND_INIT; - backend.fd = bfd; - - int efd = epoll_create1(0); - if (efd == -1) { - perror("epoll_create1"); - return -1; - } - - { - struct epoll_event ev = { - .events = EPOLLIN, - .data = { - .ptr = &backend, - }, - }; - if (epoll_ctl(efd, EPOLL_CTL_ADD, bfd, &ev) == -1) { - perror("epoll_ctl"); - return -1; - } - } - +static int loop(int epoll_fd) { while (1) { #define MAX_EVENTS 10 struct epoll_event events[MAX_EVENTS]; - int nfds = epoll_wait(efd, events, MAX_EVENTS, -1); + int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (nfds == -1) { perror("epoll_wait"); return -1; @@ -154,18 +50,8 @@ static int loop(int bfd) { for (int n = 0; n < nfds; n++) { struct peer *peer = events[n].data.ptr; switch (peer->type) { - case BACKEND: - if (buf_fill(&peer->backend.buf, peer->fd) < 0) { - fprintf(stderr, "Connection closed by backend\n"); - return -1; - } - - struct packet packet; - while (peer->backend.parser(&peer->backend, &packet)) { - } - - if (peer->backend.buf.length == BUF_LEN_MAX) { - fprintf(stderr, "Input buffer overrun. This probably means that adsbus doesn't understand the protocol that this source is speaking.\n"); + case PEER_BACKEND: + if (!backend_read((struct backend *) peer)) { return -1; } break; @@ -191,13 +77,19 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } - int bfd = connect_backend(&opts); - if (bfd < 0) { + int epoll_fd = epoll_create1(0); + if (epoll_fd == -1) { + perror("epoll_create1"); + return EXIT_FAILURE; + } + + struct backend backend = BACKEND_INIT; + if (!backend_connect(opts.backend_node, opts.backend_service, &backend, epoll_fd)) { fprintf(stderr, "Unable to connect to %s/%s\n", opts.backend_node, opts.backend_service); return EXIT_FAILURE; } - loop(bfd); - close(bfd); + loop(epoll_fd); + close(epoll_fd); return EXIT_SUCCESS; } diff --git a/airspy_adsb.h b/airspy_adsb.h index 358d579..ba93b42 100644 --- a/airspy_adsb.h +++ b/airspy_adsb.h @@ -1,4 +1,8 @@ +#pragma once + #include +#include "backend.h" +#include "common.h" void airspy_adsb_init(); bool airspy_adsb_parse(struct backend *, struct packet *); diff --git a/backend.c b/backend.c new file mode 100644 index 0000000..3d38527 --- /dev/null +++ b/backend.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include + +#include "airspy_adsb.h" +#include "backend.h" + + +static parser parsers[] = { + airspy_adsb_parse, +}; +#define NUM_PARSERS (sizeof(parsers) / sizeof(*parsers)) + + +bool backend_connect(char *node, char *service, struct backend *backend, int epoll_fd) { + assert(backend->type == PEER_BACKEND); + + struct addrinfo *addrs; + + { + struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }; + + int gai_err = getaddrinfo(node, service, &hints, &addrs); + if (gai_err) { + fprintf(stderr, "getaddrinfo(%s/%s): %s\n", node, service, gai_strerror(gai_err)); + return false; + } + } + + { + struct addrinfo *addr; + for (addr = addrs; addr != NULL; addr = addr->ai_next) { + backend->fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + if (backend->fd == -1) { + perror("socket"); + continue; + } + + if (connect(backend->fd, addr->ai_addr, addr->ai_addrlen) != -1) { + break; + } + + close(backend->fd); + } + + if (addr == NULL) { + freeaddrinfo(addrs); + fprintf(stderr, "Can't connect to %s/%s\n", node, service); + return false; + } + + char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; + if (getnameinfo(addr->ai_addr, addr->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) { + fprintf(stderr, "Connected to %s/%s\n", hbuf, sbuf); + } + } + + freeaddrinfo(addrs); + + { + struct epoll_event ev = { + .events = EPOLLIN, + .data = { + .ptr = backend, + }, + }; + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, backend->fd, &ev) == -1) { + perror("epoll_ctl"); + return false; + } + } + + return true; +} + +bool backend_read(struct backend *backend) { + if (buf_fill(&backend->buf, backend->fd) < 0) { + fprintf(stderr, "Connection closed by backend\n"); + return false; + } + + struct packet packet; + while (backend->parser(backend, &packet)) { + } + + if (backend->buf.length == BUF_LEN_MAX) { + fprintf(stderr, "Input buffer overrun. This probably means that adsbus doesn't understand the protocol that this source is speaking.\n"); + return false; + } + return true; +} + +bool backend_autodetect_parse(struct backend *backend, struct packet *packet) { + assert(backend->type == PEER_BACKEND); + + for (int i = 0; i < NUM_PARSERS; i++) { + if (parsers[i](backend, packet)) { + backend->parser = parsers[i]; + return true; + } + } + return false; +} diff --git a/backend.h b/backend.h new file mode 100644 index 0000000..afbb2a1 --- /dev/null +++ b/backend.h @@ -0,0 +1,28 @@ +#pragma once + +#include "common.h" + + +#define PARSER_STATE_LEN 256 +struct backend; +typedef bool (*parser)(struct backend *, struct packet *); +struct backend { + enum peer_type type; + int fd; + struct buf buf; + char parser_state[PARSER_STATE_LEN]; + parser parser; +}; + +#define BACKEND_INIT { \ + .type = PEER_BACKEND, \ + .fd = -1, \ + .buf = BUF_INIT, \ + .parser_state = { 0 }, \ + .parser = backend_autodetect_parse, \ +} + + +bool backend_connect(char *, char *, struct backend *, int); +bool backend_read(struct backend *); +bool backend_autodetect_parse(struct backend *, struct packet *); diff --git a/common.h b/common.h index 986928e..79f046e 100644 --- a/common.h +++ b/common.h @@ -1,8 +1,20 @@ -#include +#pragma once + #include #include +//////// peer + +// All specific peer structs must be castable to this. +struct peer { + enum peer_type { + PEER_BACKEND, + PEER_CLIENT, + } type; +}; + + //////// buf #define BUF_LEN_MAX 256 @@ -40,24 +52,8 @@ struct packet { }; -//////// backend - -#define PARSER_STATE_LEN 256 -struct backend; -typedef bool (*parser)(struct backend *, struct packet *); -struct backend { - struct buf buf; - char parser_state[PARSER_STATE_LEN]; - parser parser; -}; -#define BACKEND_INIT { \ - .buf = BUF_INIT, \ - .parser_state = { 0 }, \ - .parser = backend_autodetect_parse, \ -} - - //////// hex + void hex_init(); void hex_to_bin(char *, char *, size_t); uint64_t hex_to_int(char *, size_t);