Multiple parser support.
This commit is contained in:
90
adsbus.c
90
adsbus.c
@@ -18,12 +18,34 @@ struct opts {
|
|||||||
char *backend_service;
|
char *backend_service;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef bool (*parser)(struct buf *, struct packet *);
|
typedef bool (*parser)(struct buf *, struct packet *, void *);
|
||||||
static parser parsers[] = {
|
static parser parsers[] = {
|
||||||
airspy_adsb_parse,
|
airspy_adsb_parse,
|
||||||
};
|
};
|
||||||
#define NUM_PARSERS (sizeof(parsers) / sizeof(*parsers))
|
#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) {
|
static int parse_opts(int argc, char *argv[], struct opts *opts) {
|
||||||
int opt;
|
int opt;
|
||||||
@@ -93,9 +115,22 @@ static int connect_backend(struct opts *opts) {
|
|||||||
|
|
||||||
|
|
||||||
static int loop(int bfd) {
|
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) {
|
if (efd == -1) {
|
||||||
perror("epoll_create");
|
perror("epoll_create1");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +138,7 @@ static int loop(int bfd) {
|
|||||||
struct epoll_event ev = {
|
struct epoll_event ev = {
|
||||||
.events = EPOLLIN,
|
.events = EPOLLIN,
|
||||||
.data = {
|
.data = {
|
||||||
.fd = bfd,
|
.ptr = &backend,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if (epoll_ctl(efd, EPOLL_CTL_ADD, bfd, &ev) == -1) {
|
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) {
|
while (1) {
|
||||||
#define MAX_EVENTS 10
|
#define MAX_EVENTS 10
|
||||||
struct epoll_event events[MAX_EVENTS];
|
struct epoll_event events[MAX_EVENTS];
|
||||||
@@ -127,20 +157,39 @@ static int loop(int bfd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int n = 0; n < nfds; n++) {
|
for (int n = 0; n < nfds; n++) {
|
||||||
if (events[n].data.fd == bfd) {
|
struct peer *peer = events[n].data.ptr;
|
||||||
if (buf_fill(&buf, bfd) < 0) {
|
switch (peer->type) {
|
||||||
fprintf(stderr, "Connection closed by backend\n");
|
case BACKEND:
|
||||||
return -1;
|
if (buf_fill(&peer->backend.buf, peer->fd) < 0) {
|
||||||
}
|
fprintf(stderr, "Connection closed by backend\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
struct packet packet;
|
struct packet packet;
|
||||||
while (parsers[0](&buf, &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) {
|
if (peer->backend.parser) {
|
||||||
fprintf(stderr, "Input buffer overrun. This probably means that adsbus doesn't understand the protocol that this source is speaking.\n");
|
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;
|
return -1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,6 +198,7 @@ static int loop(int bfd) {
|
|||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
hex_init();
|
hex_init();
|
||||||
|
airspy_adsb_init();
|
||||||
|
|
||||||
struct opts opts = {
|
struct opts opts = {
|
||||||
.backend_node = "localhost",
|
.backend_node = "localhost",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -5,19 +6,29 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "airspy_adsb.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 ||
|
if (buf->length < 35 ||
|
||||||
buf_chr(buf, 0) != '*') {
|
buf_chr(buf, 0) != '*') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
struct backend_state *state = state_in;
|
||||||
if (buf->length >= 35 &&
|
if (buf->length >= 35 &&
|
||||||
buf_chr(buf, 33) == '\r' &&
|
buf_chr(buf, 33) == '\r' &&
|
||||||
buf_chr(buf, 34) == '\n' &&
|
buf_chr(buf, 34) == '\n' &&
|
||||||
buf_chr(buf, 15) == ';') {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
packet->type = MODE_S_SHORT;
|
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, 47) == '\r' &&
|
||||||
buf_chr(buf, 48) == '\n' &&
|
buf_chr(buf, 48) == '\n' &&
|
||||||
buf_chr(buf, 29) == ';') {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
packet->type = MODE_S_LONG;
|
packet->type = MODE_S_LONG;
|
||||||
@@ -40,7 +51,7 @@ bool airspy_adsb_parse(struct buf *buf, struct packet *packet) {
|
|||||||
return false;
|
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] != ';' ||
|
if (in[8] != ';' ||
|
||||||
in[11] != ';' ||
|
in[11] != ';' ||
|
||||||
in[16] != ';') {
|
in[16] != ';') {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
#include <stdbool.h>
|
#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