Multiple parser support.

This commit is contained in:
Ian Gulliver
2016-02-15 06:47:40 +00:00
parent 487ecd170c
commit bb1e5cf2ff
4 changed files with 93 additions and 26 deletions

View File

@@ -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",

View File

@@ -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] != ';') {

View File

@@ -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 *);

View File

@@ -2,6 +2,11 @@
#include <unistd.h> #include <unistd.h>
//////// misc
#define PARSER_STATE_LEN 256
//////// buf //////// buf
#define BUF_LEN_MAX 256 #define BUF_LEN_MAX 256