Factor out backend handling code.
This commit is contained in:
4
Makefile
4
Makefile
@@ -10,5 +10,5 @@ clean:
|
|||||||
%.o: %.c *.h
|
%.o: %.c *.h
|
||||||
$(CC) -c $(CFLAGS) $< -o $@
|
$(CC) -c $(CFLAGS) $< -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 airspy_adsb.o common.o
|
$(CC) $(LDFLAGS) -o adsbus adsbus.o backend.o airspy_adsb.o common.o
|
||||||
|
|||||||
136
adsbus.c
136
adsbus.c
@@ -2,11 +2,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@@ -18,31 +13,10 @@ struct opts {
|
|||||||
char *backend_service;
|
char *backend_service;
|
||||||
};
|
};
|
||||||
|
|
||||||
static parser parsers[] = {
|
|
||||||
airspy_adsb_parse,
|
|
||||||
};
|
|
||||||
#define NUM_PARSERS (sizeof(parsers) / sizeof(*parsers))
|
|
||||||
|
|
||||||
struct client {
|
struct client {
|
||||||
int placeholder;
|
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) {
|
static int parse_opts(int argc, char *argv[], struct opts *opts) {
|
||||||
int opt;
|
int opt;
|
||||||
@@ -63,89 +37,11 @@ static int parse_opts(int argc, char *argv[], struct opts *opts) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int connect_backend(struct opts *opts) {
|
static int loop(int epoll_fd) {
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
#define MAX_EVENTS 10
|
#define MAX_EVENTS 10
|
||||||
struct epoll_event events[MAX_EVENTS];
|
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) {
|
if (nfds == -1) {
|
||||||
perror("epoll_wait");
|
perror("epoll_wait");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -154,18 +50,8 @@ static int loop(int bfd) {
|
|||||||
for (int n = 0; n < nfds; n++) {
|
for (int n = 0; n < nfds; n++) {
|
||||||
struct peer *peer = events[n].data.ptr;
|
struct peer *peer = events[n].data.ptr;
|
||||||
switch (peer->type) {
|
switch (peer->type) {
|
||||||
case BACKEND:
|
case PEER_BACKEND:
|
||||||
if (buf_fill(&peer->backend.buf, peer->fd) < 0) {
|
if (!backend_read((struct backend *) peer)) {
|
||||||
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");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -191,13 +77,19 @@ int main(int argc, char *argv[]) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bfd = connect_backend(&opts);
|
int epoll_fd = epoll_create1(0);
|
||||||
if (bfd < 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);
|
fprintf(stderr, "Unable to connect to %s/%s\n", opts.backend_node, opts.backend_service);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
loop(bfd);
|
loop(epoll_fd);
|
||||||
close(bfd);
|
close(epoll_fd);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "backend.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
void airspy_adsb_init();
|
void airspy_adsb_init();
|
||||||
bool airspy_adsb_parse(struct backend *, struct packet *);
|
bool airspy_adsb_parse(struct backend *, struct packet *);
|
||||||
|
|||||||
109
backend.c
Normal file
109
backend.c
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
28
backend.h
Normal file
28
backend.h
Normal file
@@ -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 *);
|
||||||
32
common.h
32
common.h
@@ -1,8 +1,20 @@
|
|||||||
#include <stdbool.h>
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
//////// peer
|
||||||
|
|
||||||
|
// All specific peer structs must be castable to this.
|
||||||
|
struct peer {
|
||||||
|
enum peer_type {
|
||||||
|
PEER_BACKEND,
|
||||||
|
PEER_CLIENT,
|
||||||
|
} type;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//////// buf
|
//////// buf
|
||||||
|
|
||||||
#define BUF_LEN_MAX 256
|
#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
|
//////// hex
|
||||||
|
|
||||||
void hex_init();
|
void hex_init();
|
||||||
void hex_to_bin(char *, char *, size_t);
|
void hex_to_bin(char *, char *, size_t);
|
||||||
uint64_t hex_to_int(char *, size_t);
|
uint64_t hex_to_int(char *, size_t);
|
||||||
|
|||||||
Reference in New Issue
Block a user