Multiple parser support.
This commit is contained in:
90
adsbus.c
90
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",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -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] != ';') {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
bool airspy_adsb_parse(struct buf *, struct packet *);
|
||||
void airspy_adsb_init();
|
||||
bool airspy_adsb_parse(struct buf *, struct packet *, void *);
|
||||
|
||||
Reference in New Issue
Block a user