From bb1e5cf2ff5abdeda584b49acbff0d0e13560bc5 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Mon, 15 Feb 2016 06:47:40 +0000 Subject: [PATCH] Multiple parser support. --- adsbus.c | 90 +++++++++++++++++++++++++++++++++++++++------------ airspy_adsb.c | 21 +++++++++--- airspy_adsb.h | 3 +- common.h | 5 +++ 4 files changed, 93 insertions(+), 26 deletions(-) diff --git a/adsbus.c b/adsbus.c index 485e3a3..49f15ad 100644 --- a/adsbus.c +++ b/adsbus.c @@ -18,12 +18,34 @@ struct opts { char *backend_service; }; -typedef bool (*parser)(struct buf *, struct packet *); +typedef bool (*parser)(struct buf *, struct packet *, void *); static parser parsers[] = { airspy_adsb_parse, }; #define NUM_PARSERS (sizeof(parsers) / sizeof(*parsers)) +struct backend { + struct buf buf; + char parser_state[PARSER_STATE_LEN]; + parser parser; +}; + +struct client { + int placeholder; +}; + +struct peer { + enum { + BACKEND, + CLIENT, + } type; + int fd; + union { + struct backend backend; + struct client client; + }; +}; + static int parse_opts(int argc, char *argv[], struct opts *opts) { int opt; @@ -93,9 +115,22 @@ static int connect_backend(struct opts *opts) { static int loop(int bfd) { - int efd = epoll_create(10); + struct peer backend = { + .type = BACKEND, + .fd = bfd, + .backend = { + .buf = { + .start = 0, + .length = 0, + }, + .parser_state = { 0 }, + .parser = NULL, + }, + }; + + int efd = epoll_create1(0); if (efd == -1) { - perror("epoll_create"); + perror("epoll_create1"); return -1; } @@ -103,7 +138,7 @@ static int loop(int bfd) { struct epoll_event ev = { .events = EPOLLIN, .data = { - .fd = bfd, + .ptr = &backend, }, }; if (epoll_ctl(efd, EPOLL_CTL_ADD, bfd, &ev) == -1) { @@ -112,11 +147,6 @@ static int loop(int bfd) { } } - struct buf buf = { - .start = 0, - .length = 0, - }; - while (1) { #define MAX_EVENTS 10 struct epoll_event events[MAX_EVENTS]; @@ -127,20 +157,39 @@ static int loop(int bfd) { } for (int n = 0; n < nfds; n++) { - if (events[n].data.fd == bfd) { - if (buf_fill(&buf, bfd) < 0) { - fprintf(stderr, "Connection closed by backend\n"); - return -1; - } + 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 (parsers[0](&buf, &packet)) { - } + struct packet packet; + if (!peer->backend.parser) { + // Attempt to autodetect format + for (int i = 0; i < NUM_PARSERS; i++) { + if (parsers[i](&peer->backend.buf, &packet, peer->backend.parser_state)) { + peer->backend.parser = parsers[i]; + break; + } + } + } - if (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"); + if (peer->backend.parser) { + while (peer->backend.parser(&peer->backend.buf, &packet, peer->backend.parser_state)) { + } + } + + 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"); + return -1; + } + break; + + default: + fprintf(stderr, "Unpossible: unknown peer type.\n"); return -1; - } } } } @@ -149,6 +198,7 @@ static int loop(int bfd) { int main(int argc, char *argv[]) { hex_init(); + airspy_adsb_init(); struct opts opts = { .backend_node = "localhost", diff --git a/airspy_adsb.c b/airspy_adsb.c index 922e205..e70c616 100644 --- a/airspy_adsb.c +++ b/airspy_adsb.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,19 +6,29 @@ #include "common.h" #include "airspy_adsb.h" -static bool airspy_adsb_parse_common(char *, struct packet *); +struct backend_state { + uint64_t mlat_timestamp_last; + uint64_t mlat_timestamp_generation; +}; + +static bool airspy_adsb_parse_common(char *, struct packet *, struct backend_state *); -bool airspy_adsb_parse(struct buf *buf, struct packet *packet) { +void airspy_adsb_init() { + assert(sizeof(struct backend_state) <= PARSER_STATE_LEN); +} + +bool airspy_adsb_parse(struct buf *buf, struct packet *packet, void *state_in) { if (buf->length < 35 || buf_chr(buf, 0) != '*') { return false; } + struct backend_state *state = state_in; if (buf->length >= 35 && buf_chr(buf, 33) == '\r' && buf_chr(buf, 34) == '\n' && buf_chr(buf, 15) == ';') { - if (!airspy_adsb_parse_common(buf_at(buf, 16), packet)) { + if (!airspy_adsb_parse_common(buf_at(buf, 16), packet, state)) { return false; } packet->type = MODE_S_SHORT; @@ -29,7 +40,7 @@ bool airspy_adsb_parse(struct buf *buf, struct packet *packet) { buf_chr(buf, 47) == '\r' && buf_chr(buf, 48) == '\n' && buf_chr(buf, 29) == ';') { - if (!airspy_adsb_parse_common(buf_at(buf, 30), packet)) { + if (!airspy_adsb_parse_common(buf_at(buf, 30), packet, state)) { return false; } packet->type = MODE_S_LONG; @@ -40,7 +51,7 @@ bool airspy_adsb_parse(struct buf *buf, struct packet *packet) { return false; } -static bool airspy_adsb_parse_common(char *in, struct packet *packet) { +static bool airspy_adsb_parse_common(char *in, struct packet *packet, struct backend_state *state) { if (in[8] != ';' || in[11] != ';' || in[16] != ';') { diff --git a/airspy_adsb.h b/airspy_adsb.h index 3195572..092a4d9 100644 --- a/airspy_adsb.h +++ b/airspy_adsb.h @@ -1,3 +1,4 @@ #include -bool airspy_adsb_parse(struct buf *, struct packet *); +void airspy_adsb_init(); +bool airspy_adsb_parse(struct buf *, struct packet *, void *); diff --git a/common.h b/common.h index e6db328..78a6600 100644 --- a/common.h +++ b/common.h @@ -2,6 +2,11 @@ #include +//////// misc + +#define PARSER_STATE_LEN 256 + + //////// buf #define BUF_LEN_MAX 256