Style and include cleanups.
This commit is contained in:
19
adsbus.c
19
adsbus.c
@@ -13,8 +13,7 @@
|
|||||||
#include "json.h"
|
#include "json.h"
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
|
|
||||||
|
static void print_usage(const char *name) {
|
||||||
static void print_usage(char *argv[]) {
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\n"
|
"\n"
|
||||||
"Usage: %s [OPTION]...\n"
|
"Usage: %s [OPTION]...\n"
|
||||||
@@ -25,7 +24,7 @@ static void print_usage(char *argv[]) {
|
|||||||
"\t--dump=FORMAT\n"
|
"\t--dump=FORMAT\n"
|
||||||
"\t--incoming=[HOST/]PORT\n"
|
"\t--incoming=[HOST/]PORT\n"
|
||||||
"\t--listen=FORMAT=[HOST/]PORT\n"
|
"\t--listen=FORMAT=[HOST/]PORT\n"
|
||||||
, argv[0]);
|
, name);
|
||||||
backend_print_usage();
|
backend_print_usage();
|
||||||
client_print_usage();
|
client_print_usage();
|
||||||
}
|
}
|
||||||
@@ -56,9 +55,9 @@ static bool add_incoming(char *arg){
|
|||||||
char *port = strrchr(arg, '/');
|
char *port = strrchr(arg, '/');
|
||||||
if (port) {
|
if (port) {
|
||||||
*(port++) = '\0';
|
*(port++) = '\0';
|
||||||
incoming_new(arg, port, backend_new_fd, NULL);
|
incoming_new(arg, port, backend_new_fd_wrapper, NULL);
|
||||||
} else {
|
} else {
|
||||||
incoming_new(NULL, arg, backend_new_fd, NULL);
|
incoming_new(NULL, arg, backend_new_fd_wrapper, NULL);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -94,6 +93,7 @@ static bool parse_opts(int argc, char *argv[]) {
|
|||||||
{"incoming", required_argument, 0, 'i'},
|
{"incoming", required_argument, 0, 'i'},
|
||||||
{"listen", required_argument, 0, 'l'},
|
{"listen", required_argument, 0, 'l'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
|
{0, 0, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
int opt;
|
int opt;
|
||||||
@@ -109,7 +109,7 @@ static bool parse_opts(int argc, char *argv[]) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
print_usage(argv);
|
print_usage(argv[0]);
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
@@ -121,13 +121,13 @@ static bool parse_opts(int argc, char *argv[]) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print_usage(argv);
|
print_usage(argv[0]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
if (!handler(optarg)) {
|
if (!handler(optarg)) {
|
||||||
print_usage(argv);
|
print_usage(argv[0]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ static bool parse_opts(int argc, char *argv[]) {
|
|||||||
|
|
||||||
if (optind != argc) {
|
if (optind != argc) {
|
||||||
fprintf(stderr, "Not a flag: %s\n", argv[optind]);
|
fprintf(stderr, "Not a flag: %s\n", argv[optind]);
|
||||||
print_usage(argv);
|
print_usage(argv[0]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +143,6 @@ static bool parse_opts(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
server_init();
|
|
||||||
peer_init();
|
peer_init();
|
||||||
hex_init();
|
hex_init();
|
||||||
client_init();
|
client_init();
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "backend.h"
|
||||||
#include "airspy_adsb.h"
|
#include "airspy_adsb.h"
|
||||||
|
|
||||||
struct __attribute__((packed)) airspy_adsb_common_overlay {
|
struct __attribute__((packed)) airspy_adsb_common_overlay {
|
||||||
@@ -37,13 +37,16 @@ struct airspy_adsb_parser_state {
|
|||||||
struct mlat_state mlat_state;
|
struct mlat_state mlat_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool airspy_adsb_parse_common(struct airspy_adsb_common_overlay *, struct packet *, struct airspy_adsb_parser_state *);
|
static bool airspy_adsb_parse_common(const struct airspy_adsb_common_overlay *overlay, struct packet *packet, struct airspy_adsb_parser_state *state) {
|
||||||
|
if (overlay->semicolon1 != ';' ||
|
||||||
|
overlay->semicolon2 != ';' ||
|
||||||
void airspy_adsb_init() {
|
overlay->semicolon3 != ';') {
|
||||||
assert(sizeof(struct airspy_adsb_parser_state) <= PARSER_STATE_LEN);
|
return false;
|
||||||
assert(sizeof(struct airspy_adsb_mode_s_short_overlay) < BUF_LEN_MAX);
|
}
|
||||||
assert(sizeof(struct airspy_adsb_mode_s_long_overlay) < BUF_LEN_MAX);
|
uint16_t mlat_mhz = 2 * hex_to_int(overlay->mlat_precision, sizeof(overlay->mlat_precision) / 2);
|
||||||
|
packet->mlat_timestamp = mlat_timestamp_scale_in(hex_to_int(overlay->mlat_timestamp, sizeof(overlay->mlat_timestamp) / 2), UINT32_MAX, mlat_mhz, &state->mlat_state);
|
||||||
|
packet->rssi = rssi_scale_in(hex_to_int(overlay->rssi, sizeof(overlay->rssi) / 2), UINT16_MAX);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool airspy_adsb_parse_mode_s_short(struct buf *buf, struct packet *packet, struct airspy_adsb_parser_state *state) {
|
static bool airspy_adsb_parse_mode_s_short(struct buf *buf, struct packet *packet, struct airspy_adsb_parser_state *state) {
|
||||||
@@ -82,23 +85,16 @@ static bool airspy_adsb_parse_mode_s_long(struct buf *buf, struct packet *packet
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool airspy_adsb_parse(struct backend *backend, struct packet *packet) {
|
void airspy_adsb_init() {
|
||||||
struct buf *buf = &backend->buf;
|
assert(sizeof(struct airspy_adsb_parser_state) <= PARSER_STATE_LEN);
|
||||||
struct airspy_adsb_parser_state *state = (struct airspy_adsb_parser_state *) backend->parser_state;
|
assert(sizeof(struct airspy_adsb_mode_s_short_overlay) < BUF_LEN_MAX);
|
||||||
|
assert(sizeof(struct airspy_adsb_mode_s_long_overlay) < BUF_LEN_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool airspy_adsb_parse(struct buf *buf, struct packet *packet, void *state_in) {
|
||||||
|
struct airspy_adsb_parser_state *state = (struct airspy_adsb_parser_state *) state_in;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
airspy_adsb_parse_mode_s_short(buf, packet, state) ||
|
airspy_adsb_parse_mode_s_short(buf, packet, state) ||
|
||||||
airspy_adsb_parse_mode_s_long(buf, packet, state));
|
airspy_adsb_parse_mode_s_long(buf, packet, state));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool airspy_adsb_parse_common(struct airspy_adsb_common_overlay *overlay, struct packet *packet, struct airspy_adsb_parser_state *state) {
|
|
||||||
if (overlay->semicolon1 != ';' ||
|
|
||||||
overlay->semicolon2 != ';' ||
|
|
||||||
overlay->semicolon3 != ';') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
uint16_t mlat_mhz = 2 * hex_to_int(overlay->mlat_precision, sizeof(overlay->mlat_precision) / 2);
|
|
||||||
packet->mlat_timestamp = mlat_timestamp_scale_in(hex_to_int(overlay->mlat_timestamp, sizeof(overlay->mlat_timestamp) / 2), UINT32_MAX, mlat_mhz, &state->mlat_state);
|
|
||||||
packet->rssi = rssi_scale_in(hex_to_int(overlay->rssi, sizeof(overlay->rssi) / 2), UINT16_MAX);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "backend.h"
|
|
||||||
#include "common.h"
|
struct buf;
|
||||||
|
struct packet;
|
||||||
|
|
||||||
void airspy_adsb_init();
|
void airspy_adsb_init();
|
||||||
bool airspy_adsb_parse(struct backend *, struct packet *);
|
bool airspy_adsb_parse(struct buf *, struct packet *, void *);
|
||||||
|
|||||||
202
backend.c
202
backend.c
@@ -5,6 +5,7 @@
|
|||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "airspy_adsb.h"
|
#include "airspy_adsb.h"
|
||||||
#include "beast.h"
|
#include "beast.h"
|
||||||
@@ -13,14 +14,22 @@
|
|||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "backend.h"
|
#include "backend.h"
|
||||||
|
|
||||||
|
typedef bool (*parser_wrapper)(struct backend *, struct packet *);
|
||||||
|
typedef bool (*parser)(struct buf *, struct packet *, void *state);
|
||||||
|
struct backend {
|
||||||
|
struct peer peer;
|
||||||
|
char id[UUID_LEN];
|
||||||
|
const char *node;
|
||||||
|
const char *service;
|
||||||
|
struct addrinfo *addrs;
|
||||||
|
struct addrinfo *addr;
|
||||||
|
struct buf buf;
|
||||||
|
char parser_state[PARSER_STATE_LEN];
|
||||||
|
parser_wrapper parser_wrapper;
|
||||||
|
parser parser;
|
||||||
|
};
|
||||||
|
|
||||||
static bool backend_autodetect_parse(struct backend *, struct packet *);
|
static void backend_connect_result(struct backend *, int);
|
||||||
static void backend_connect(struct backend *);
|
|
||||||
static void backend_connect_next(struct backend *);
|
|
||||||
|
|
||||||
static void backend_connect_handler(struct peer *);
|
|
||||||
static void backend_read(struct peer *);
|
|
||||||
|
|
||||||
|
|
||||||
struct parser {
|
struct parser {
|
||||||
char *name;
|
char *name;
|
||||||
@@ -41,6 +50,24 @@ struct parser {
|
|||||||
};
|
};
|
||||||
#define NUM_PARSERS (sizeof(parsers) / sizeof(*parsers))
|
#define NUM_PARSERS (sizeof(parsers) / sizeof(*parsers))
|
||||||
|
|
||||||
|
static bool backend_parse_wrapper(struct backend *backend, struct packet *packet) {
|
||||||
|
return backend->parser(&backend->buf, packet, backend->parser_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool backend_autodetect_parse(struct backend *backend, struct packet *packet) {
|
||||||
|
struct buf *buf = &backend->buf;
|
||||||
|
void *state = backend->parser_state;
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_PARSERS; i++) {
|
||||||
|
if (parsers[i].parse(buf, packet, state)) {
|
||||||
|
fprintf(stderr, "B %s: Detected input format %s\n", backend->id, parsers[i].name);
|
||||||
|
backend->parser_wrapper = backend_parse_wrapper;
|
||||||
|
backend->parser = parsers[i].parse;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static struct backend *backend_create() {
|
static struct backend *backend_create() {
|
||||||
struct backend *backend = malloc(sizeof(*backend));
|
struct backend *backend = malloc(sizeof(*backend));
|
||||||
@@ -51,41 +78,62 @@ static struct backend *backend_create() {
|
|||||||
backend->service = NULL;
|
backend->service = NULL;
|
||||||
buf_init(&backend->buf);
|
buf_init(&backend->buf);
|
||||||
memset(backend->parser_state, 0, PARSER_STATE_LEN);
|
memset(backend->parser_state, 0, PARSER_STATE_LEN);
|
||||||
backend->parser = backend_autodetect_parse;
|
backend->parser_wrapper = backend_autodetect_parse;
|
||||||
return backend;
|
return backend;
|
||||||
}
|
}
|
||||||
|
|
||||||
void backend_new(char *node, char *service) {
|
static void backend_connect_handler(struct peer *peer) {
|
||||||
struct backend *backend = backend_create();
|
struct backend *backend = (struct backend *) peer;
|
||||||
backend->node = node;
|
|
||||||
backend->service = service;
|
peer_epoll_del(peer);
|
||||||
backend_connect(backend);
|
|
||||||
|
int error;
|
||||||
|
socklen_t len = sizeof(error);
|
||||||
|
assert(getsockopt(backend->peer.fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0);
|
||||||
|
backend_connect_result(backend, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void backend_new_fd(int fd, void *unused) {
|
static void backend_connect_next(struct backend *backend) {
|
||||||
struct backend *backend = backend_create();
|
if (backend->addr == NULL) {
|
||||||
backend->peer.fd = fd;
|
freeaddrinfo(backend->addrs);
|
||||||
backend->peer.event_handler = backend_read;
|
fprintf(stderr, "B %s: Can't connect to any addresses of %s/%s\n", backend->id, backend->node, backend->service);
|
||||||
peer_epoll_add((struct peer *) backend, EPOLLIN);
|
return;
|
||||||
|
}
|
||||||
fprintf(stderr, "B %s: New backend from incoming connection\n", backend->id);
|
|
||||||
}
|
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
|
||||||
|
assert(getnameinfo(backend->addr->ai_addr, backend->addr->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0);
|
||||||
static void backend_connect(struct backend *backend) {
|
fprintf(stderr, "B %s: Connecting to %s/%s...\n", backend->id, hbuf, sbuf);
|
||||||
fprintf(stderr, "B %s: Resolving %s/%s...\n", backend->id, backend->node, backend->service);
|
|
||||||
|
backend->peer.fd = socket(backend->addr->ai_family, backend->addr->ai_socktype | SOCK_NONBLOCK, backend->addr->ai_protocol);
|
||||||
struct addrinfo hints = {
|
assert(backend->peer.fd >= 0);
|
||||||
.ai_family = AF_UNSPEC,
|
|
||||||
.ai_socktype = SOCK_STREAM,
|
int result = connect(backend->peer.fd, backend->addr->ai_addr, backend->addr->ai_addrlen);
|
||||||
};
|
backend_connect_result(backend, result == 0 ? result : errno);
|
||||||
|
}
|
||||||
int gai_err = getaddrinfo(backend->node, backend->service, &hints, &backend->addrs);
|
|
||||||
if (gai_err) {
|
static void backend_read(struct peer *peer) {
|
||||||
fprintf(stderr, "B %s: Failed to resolve %s/%s: %s\n", backend->id, backend->node, backend->service, gai_strerror(gai_err));
|
struct backend *backend = (struct backend *) peer;
|
||||||
|
|
||||||
|
if (buf_fill(&backend->buf, backend->peer.fd) <= 0) {
|
||||||
|
fprintf(stderr, "B %s: Connection closed by backend\n", backend->id);
|
||||||
|
close(backend->peer.fd);
|
||||||
|
// TODO: reconnect
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct packet packet = {
|
||||||
|
.backend = backend,
|
||||||
|
};
|
||||||
|
while (backend->parser_wrapper(backend, &packet)) {
|
||||||
|
client_write(&packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backend->buf.length == BUF_LEN_MAX) {
|
||||||
|
fprintf(stderr, "B %s: Input buffer overrun. This probably means that adsbus doesn't understand the protocol that this source is speaking.\n", backend->id);
|
||||||
|
close(backend->peer.fd);
|
||||||
|
// TODO: reconnect
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
backend->addr = backend->addrs;
|
|
||||||
backend_connect_next(backend);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void backend_connect_result(struct backend *backend, int result) {
|
static void backend_connect_result(struct backend *backend, int result) {
|
||||||
@@ -114,69 +162,41 @@ static void backend_connect_result(struct backend *backend, int result) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void backend_connect_next(struct backend *backend) {
|
static void backend_connect(struct backend *backend) {
|
||||||
if (backend->addr == NULL) {
|
fprintf(stderr, "B %s: Resolving %s/%s...\n", backend->id, backend->node, backend->service);
|
||||||
freeaddrinfo(backend->addrs);
|
|
||||||
fprintf(stderr, "B %s: Can't connect to any addresses of %s/%s\n", backend->id, backend->node, backend->service);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
|
struct addrinfo hints = {
|
||||||
assert(getnameinfo(backend->addr->ai_addr, backend->addr->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0);
|
.ai_family = AF_UNSPEC,
|
||||||
fprintf(stderr, "B %s: Connecting to %s/%s...\n", backend->id, hbuf, sbuf);
|
.ai_socktype = SOCK_STREAM,
|
||||||
|
|
||||||
backend->peer.fd = socket(backend->addr->ai_family, backend->addr->ai_socktype | SOCK_NONBLOCK, backend->addr->ai_protocol);
|
|
||||||
assert(backend->peer.fd >= 0);
|
|
||||||
|
|
||||||
int result = connect(backend->peer.fd, backend->addr->ai_addr, backend->addr->ai_addrlen);
|
|
||||||
backend_connect_result(backend, result == 0 ? result : errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void backend_connect_handler(struct peer *peer) {
|
|
||||||
struct backend *backend = (struct backend *) peer;
|
|
||||||
|
|
||||||
peer_epoll_del(peer);
|
|
||||||
|
|
||||||
int error;
|
|
||||||
socklen_t len = sizeof(error);
|
|
||||||
assert(getsockopt(backend->peer.fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0);
|
|
||||||
backend_connect_result(backend, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void backend_read(struct peer *peer) {
|
|
||||||
struct backend *backend = (struct backend *) peer;
|
|
||||||
|
|
||||||
if (buf_fill(&backend->buf, backend->peer.fd) <= 0) {
|
|
||||||
fprintf(stderr, "B %s: Connection closed by backend\n", backend->id);
|
|
||||||
close(backend->peer.fd);
|
|
||||||
// TODO: reconnect
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct packet packet = {
|
|
||||||
.backend = backend,
|
|
||||||
};
|
};
|
||||||
while (backend->parser(backend, &packet)) {
|
|
||||||
client_write(&packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (backend->buf.length == BUF_LEN_MAX) {
|
int gai_err = getaddrinfo(backend->node, backend->service, &hints, &backend->addrs);
|
||||||
fprintf(stderr, "B %s: Input buffer overrun. This probably means that adsbus doesn't understand the protocol that this source is speaking.\n", backend->id);
|
if (gai_err) {
|
||||||
close(backend->peer.fd);
|
fprintf(stderr, "B %s: Failed to resolve %s/%s: %s\n", backend->id, backend->node, backend->service, gai_strerror(gai_err));
|
||||||
// TODO: reconnect
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
backend->addr = backend->addrs;
|
||||||
|
backend_connect_next(backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool backend_autodetect_parse(struct backend *backend, struct packet *packet) {
|
void backend_new(const char *node, const char *service) {
|
||||||
for (int i = 0; i < NUM_PARSERS; i++) {
|
struct backend *backend = backend_create();
|
||||||
if (parsers[i].parse(backend, packet)) {
|
backend->node = node;
|
||||||
fprintf(stderr, "B %s: Detected input format %s\n", backend->id, parsers[i].name);
|
backend->service = service;
|
||||||
backend->parser = parsers[i].parse;
|
backend_connect(backend);
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
}
|
void backend_new_fd(int fd) {
|
||||||
return false;
|
struct backend *backend = backend_create();
|
||||||
|
backend->peer.fd = fd;
|
||||||
|
backend->peer.event_handler = backend_read;
|
||||||
|
peer_epoll_add((struct peer *) backend, EPOLLIN);
|
||||||
|
|
||||||
|
fprintf(stderr, "B %s: New backend from incoming connection\n", backend->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void backend_new_fd_wrapper(int fd, void *unused) {
|
||||||
|
backend_new_fd(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void backend_print_usage() {
|
void backend_print_usage() {
|
||||||
|
|||||||
20
backend.h
20
backend.h
@@ -4,23 +4,9 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
#define PARSER_STATE_LEN 256
|
#define PARSER_STATE_LEN 256
|
||||||
struct backend;
|
|
||||||
struct addrinfo;
|
|
||||||
typedef bool (*parser)(struct backend *, struct packet *);
|
|
||||||
struct backend {
|
|
||||||
struct peer peer;
|
|
||||||
char id[UUID_LEN];
|
|
||||||
char *node;
|
|
||||||
char *service;
|
|
||||||
struct addrinfo *addrs;
|
|
||||||
struct addrinfo *addr;
|
|
||||||
struct buf buf;
|
|
||||||
char parser_state[PARSER_STATE_LEN];
|
|
||||||
parser parser;
|
|
||||||
};
|
|
||||||
|
|
||||||
void backend_new(char *, char *);
|
void backend_new(const char *, const char *);
|
||||||
void backend_new_fd(int, void *);
|
void backend_new_fd(int);
|
||||||
|
void backend_new_fd_wrapper(int, void *);
|
||||||
void backend_print_usage();
|
void backend_print_usage();
|
||||||
|
|||||||
23
beast.c
23
beast.c
@@ -1,10 +1,12 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "backend.h"
|
||||||
#include "beast.h"
|
#include "beast.h"
|
||||||
|
|
||||||
|
|
||||||
struct __attribute__((packed)) beast_common_overlay {
|
struct __attribute__((packed)) beast_common_overlay {
|
||||||
uint8_t one_a;
|
uint8_t one_a;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
@@ -28,12 +30,6 @@ struct beast_parser_state {
|
|||||||
struct mlat_state mlat_state;
|
struct mlat_state mlat_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
void beast_init() {
|
|
||||||
assert(sizeof(struct beast_parser_state) <= PARSER_STATE_LEN);
|
|
||||||
assert(sizeof(struct beast_mode_s_short_overlay) * 2 <= BUF_LEN_MAX);
|
|
||||||
assert(sizeof(struct beast_mode_s_long_overlay) * 2 <= BUF_LEN_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t beast_parse_mlat(uint8_t *mlat_timestamp) {
|
static uint64_t beast_parse_mlat(uint8_t *mlat_timestamp) {
|
||||||
return (
|
return (
|
||||||
((uint64_t) mlat_timestamp[0]) << 40 |
|
((uint64_t) mlat_timestamp[0]) << 40 |
|
||||||
@@ -44,7 +40,7 @@ static uint64_t beast_parse_mlat(uint8_t *mlat_timestamp) {
|
|||||||
((uint64_t) mlat_timestamp[5]));
|
((uint64_t) mlat_timestamp[5]));
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t beast_unescape(struct buf *out, struct buf *in, size_t out_bytes) {
|
static ssize_t beast_unescape(struct buf *out, const struct buf *in, size_t out_bytes) {
|
||||||
int o = 0, i = 0;
|
int o = 0, i = 0;
|
||||||
for (; i < in->length && o < out_bytes; i++, o++) {
|
for (; i < in->length && o < out_bytes; i++, o++) {
|
||||||
if (i > 0 && buf_chr(in, i) == 0x1a) {
|
if (i > 0 && buf_chr(in, i) == 0x1a) {
|
||||||
@@ -98,9 +94,14 @@ static bool beast_parse_mode_s_long(struct buf *buf, struct packet *packet, stru
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool beast_parse(struct backend *backend, struct packet *packet) {
|
void beast_init() {
|
||||||
struct buf *buf = &backend->buf;
|
assert(sizeof(struct beast_parser_state) <= PARSER_STATE_LEN);
|
||||||
struct beast_parser_state *state = (struct beast_parser_state *) backend->parser_state;
|
assert(sizeof(struct beast_mode_s_short_overlay) * 2 <= BUF_LEN_MAX);
|
||||||
|
assert(sizeof(struct beast_mode_s_long_overlay) * 2 <= BUF_LEN_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool beast_parse(struct buf *buf, struct packet *packet, void *state_in) {
|
||||||
|
struct beast_parser_state *state = (struct beast_parser_state *) state_in;
|
||||||
|
|
||||||
if (buf->length < sizeof(struct beast_common_overlay) ||
|
if (buf->length < sizeof(struct beast_common_overlay) ||
|
||||||
buf_chr(buf, 0) != 0x1a) {
|
buf_chr(buf, 0) != 0x1a) {
|
||||||
|
|||||||
7
beast.h
7
beast.h
@@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "backend.h"
|
|
||||||
#include "common.h"
|
struct buf;
|
||||||
|
struct packet;
|
||||||
|
|
||||||
void beast_init();
|
void beast_init();
|
||||||
bool beast_parse(struct backend *, struct packet *);
|
bool beast_parse(struct buf *, struct packet *, void *);
|
||||||
|
|||||||
28
client.c
28
client.c
@@ -12,7 +12,6 @@
|
|||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
|
||||||
|
|
||||||
struct client {
|
struct client {
|
||||||
struct peer peer;
|
struct peer peer;
|
||||||
char id[UUID_LEN];
|
char id[UUID_LEN];
|
||||||
@@ -38,11 +37,6 @@ struct serializer {
|
|||||||
};
|
};
|
||||||
#define NUM_SERIALIZERS (sizeof(serializers) / sizeof(*serializers))
|
#define NUM_SERIALIZERS (sizeof(serializers) / sizeof(*serializers))
|
||||||
|
|
||||||
|
|
||||||
void client_init() {
|
|
||||||
signal(SIGPIPE, SIG_IGN);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void client_hangup(struct client *client) {
|
static void client_hangup(struct client *client) {
|
||||||
fprintf(stderr, "C %s (%s): Client disconnected\n", client->id, client->serializer->name);
|
fprintf(stderr, "C %s (%s): Client disconnected\n", client->id, client->serializer->name);
|
||||||
if (client->prev) {
|
if (client->prev) {
|
||||||
@@ -61,15 +55,6 @@ static void client_hangup_wrapper(struct peer *peer) {
|
|||||||
client_hangup((struct client *) peer);
|
client_hangup((struct client *) peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct serializer *client_get_serializer(char *name) {
|
|
||||||
for (int i = 0; i < NUM_SERIALIZERS; i++) {
|
|
||||||
if (strcasecmp(serializers[i].name, name) == 0) {
|
|
||||||
return &serializers[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool client_hello(int fd, struct serializer *serializer) {
|
static bool client_hello(int fd, struct serializer *serializer) {
|
||||||
struct buf buf = BUF_INIT;
|
struct buf buf = BUF_INIT;
|
||||||
serializer->serialize(NULL, &buf);
|
serializer->serialize(NULL, &buf);
|
||||||
@@ -82,6 +67,19 @@ static bool client_hello(int fd, struct serializer *serializer) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void client_init() {
|
||||||
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct serializer *client_get_serializer(char *name) {
|
||||||
|
for (int i = 0; i < NUM_SERIALIZERS; i++) {
|
||||||
|
if (strcasecmp(serializers[i].name, name) == 0) {
|
||||||
|
return &serializers[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void client_add(int fd, struct serializer *serializer) {
|
void client_add(int fd, struct serializer *serializer) {
|
||||||
int flags = fcntl(fd, F_GETFL, 0);
|
int flags = fcntl(fd, F_GETFL, 0);
|
||||||
assert(flags >= 0);
|
assert(flags >= 0);
|
||||||
|
|||||||
1
client.h
1
client.h
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
void client_init();
|
void client_init();
|
||||||
struct serializer *client_get_serializer(char *);
|
struct serializer *client_get_serializer(char *);
|
||||||
void client_add(int, struct serializer *);
|
void client_add(int, struct serializer *);
|
||||||
|
|||||||
19
common.c
19
common.c
@@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
int epoll_fd;
|
int epoll_fd;
|
||||||
|
|
||||||
|
|
||||||
void peer_init() {
|
void peer_init() {
|
||||||
epoll_fd = epoll_create1(0);
|
epoll_fd = epoll_create1(0);
|
||||||
assert(epoll_fd >= 0);
|
assert(epoll_fd >= 0);
|
||||||
@@ -123,15 +122,15 @@ void hex_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hex_to_bin(uint8_t *out, char *in, size_t bytes) {
|
void hex_to_bin(uint8_t *out, const char *in, size_t bytes) {
|
||||||
uint8_t *in2 = (uint8_t *) in;
|
const uint8_t *in2 = (uint8_t *) in;
|
||||||
for (size_t i = 0, j = 0; i < bytes; i++, j += 2) {
|
for (size_t i = 0, j = 0; i < bytes; i++, j += 2) {
|
||||||
out[i] = (hex_table[in2[j]] << 4) | hex_table[in2[j + 1]];
|
out[i] = (hex_table[in2[j]] << 4) | hex_table[in2[j + 1]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t hex_to_int(char *in, size_t bytes) {
|
uint64_t hex_to_int(const char *in, size_t bytes) {
|
||||||
uint8_t *in2 = (uint8_t *) in;
|
const uint8_t *in2 = (uint8_t *) in;
|
||||||
uint64_t ret = 0;
|
uint64_t ret = 0;
|
||||||
bytes *= 2;
|
bytes *= 2;
|
||||||
for (size_t i = 0; i < bytes; i++) {
|
for (size_t i = 0; i < bytes; i++) {
|
||||||
@@ -141,7 +140,7 @@ uint64_t hex_to_int(char *in, size_t bytes) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hex_from_bin(char *out, uint8_t *in, size_t bytes) {
|
void hex_from_bin(char *out, const uint8_t *in, size_t bytes) {
|
||||||
for (size_t i = 0, j = 0; i < bytes; i++, j += 2) {
|
for (size_t i = 0, j = 0; i < bytes; i++, j += 2) {
|
||||||
out[j] = hex_char_table[in[i] >> 4];
|
out[j] = hex_char_table[in[i] >> 4];
|
||||||
out[j + 1] = hex_char_table[in[i] & 0xf];
|
out[j + 1] = hex_char_table[in[i] & 0xf];
|
||||||
@@ -154,11 +153,3 @@ void uuid_gen(char *out) {
|
|||||||
uuid_generate(uuid);
|
uuid_generate(uuid);
|
||||||
uuid_unparse(uuid, out);
|
uuid_unparse(uuid, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char server_id[UUID_LEN];
|
|
||||||
|
|
||||||
void server_init() {
|
|
||||||
uuid_gen(server_id);
|
|
||||||
fprintf(stderr, "S %s: Server start\n", server_id);
|
|
||||||
}
|
|
||||||
|
|||||||
13
common.h
13
common.h
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -83,18 +82,12 @@ uint32_t rssi_scale_in(uint32_t, uint32_t);
|
|||||||
//////// hex
|
//////// hex
|
||||||
|
|
||||||
void hex_init();
|
void hex_init();
|
||||||
void hex_to_bin(uint8_t *, char *, size_t);
|
void hex_to_bin(uint8_t *, const char *, size_t);
|
||||||
uint64_t hex_to_int(char *, size_t);
|
uint64_t hex_to_int(const char *, size_t);
|
||||||
void hex_from_bin(char *, uint8_t *, size_t);
|
void hex_from_bin(char *, const uint8_t *, size_t);
|
||||||
|
|
||||||
|
|
||||||
///////// uuid
|
///////// uuid
|
||||||
|
|
||||||
#define UUID_LEN 37
|
#define UUID_LEN 37
|
||||||
void uuid_gen(char *);
|
void uuid_gen(char *);
|
||||||
|
|
||||||
|
|
||||||
///////// server
|
|
||||||
|
|
||||||
extern char server_id[];
|
|
||||||
void server_init();
|
|
||||||
|
|||||||
@@ -6,21 +6,20 @@
|
|||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "incoming.h"
|
#include "incoming.h"
|
||||||
|
|
||||||
|
|
||||||
struct incoming {
|
struct incoming {
|
||||||
struct peer peer;
|
struct peer peer;
|
||||||
char id[UUID_LEN];
|
char id[UUID_LEN];
|
||||||
char *node;
|
const char *node;
|
||||||
char *service;
|
const char *service;
|
||||||
incoming_connection_handler handler;
|
incoming_connection_handler handler;
|
||||||
void *passthrough;
|
void *passthrough;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void incoming_handler(struct peer *peer) {
|
static void incoming_handler(struct peer *peer) {
|
||||||
struct incoming *incoming = (struct incoming *) peer;
|
struct incoming *incoming = (struct incoming *) peer;
|
||||||
|
|
||||||
@@ -47,7 +46,7 @@ static void incoming_handler(struct peer *peer) {
|
|||||||
incoming->handler(fd, incoming->passthrough);
|
incoming->handler(fd, incoming->passthrough);
|
||||||
}
|
}
|
||||||
|
|
||||||
void incoming_new(char *node, char *service, incoming_connection_handler handler, void *passthrough) {
|
void incoming_new(const char *node, const char *service, incoming_connection_handler handler, void *passthrough) {
|
||||||
struct incoming *incoming = malloc(sizeof(*incoming));
|
struct incoming *incoming = malloc(sizeof(*incoming));
|
||||||
incoming->peer.event_handler = incoming_handler;
|
incoming->peer.event_handler = incoming_handler;
|
||||||
uuid_gen(incoming->id);
|
uuid_gen(incoming->id);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
typedef void (*incoming_connection_handler)(int fd, void *);
|
typedef void (*incoming_connection_handler)(int fd, void *);
|
||||||
void incoming_new(char *, char *, incoming_connection_handler, void *);
|
void incoming_new(const char *, const char *, incoming_connection_handler, void *);
|
||||||
|
|||||||
33
json.c
33
json.c
@@ -7,23 +7,6 @@
|
|||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "json.h"
|
#include "json.h"
|
||||||
|
|
||||||
|
|
||||||
// Hobo JSON to avoid overhead. Assumes that we can't get quotes in the data.
|
|
||||||
|
|
||||||
void json_init() {
|
|
||||||
assert(JSON_INTEGER_IS_LONG_LONG);
|
|
||||||
}
|
|
||||||
|
|
||||||
int json_buf_append_callback(const char *buffer, size_t size, void *data) {
|
|
||||||
struct buf *buf = data;
|
|
||||||
if (buf->length + size + 1 > BUF_LEN_MAX) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memcpy(buf_at(buf, buf->length), buffer, size);
|
|
||||||
buf->length += size;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void json_serialize_to_buf(json_t *obj, struct buf *buf) {
|
static void json_serialize_to_buf(json_t *obj, struct buf *buf) {
|
||||||
assert(json_dump_callback(obj, json_buf_append_callback, buf, 0) == 0);
|
assert(json_dump_callback(obj, json_buf_append_callback, buf, 0) == 0);
|
||||||
json_decref(obj);
|
json_decref(obj);
|
||||||
@@ -32,7 +15,6 @@ static void json_serialize_to_buf(json_t *obj, struct buf *buf) {
|
|||||||
|
|
||||||
static void json_hello(struct buf *buf) {
|
static void json_hello(struct buf *buf) {
|
||||||
json_t *hello = json_pack("{sssIsIsI}",
|
json_t *hello = json_pack("{sssIsIsI}",
|
||||||
"server_id", server_id,
|
|
||||||
"mlat_timestamp_mhz", (json_int_t) MLAT_MHZ,
|
"mlat_timestamp_mhz", (json_int_t) MLAT_MHZ,
|
||||||
"mlat_timestamp_max", (json_int_t) MLAT_MAX,
|
"mlat_timestamp_max", (json_int_t) MLAT_MAX,
|
||||||
"rssi_max", (json_int_t) RSSI_MAX);
|
"rssi_max", (json_int_t) RSSI_MAX);
|
||||||
@@ -40,7 +22,6 @@ static void json_hello(struct buf *buf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void json_add_common(struct packet *packet, json_t *obj) {
|
static void json_add_common(struct packet *packet, json_t *obj) {
|
||||||
json_object_set_new(obj, "backend_id", json_string(packet->backend->id));
|
|
||||||
json_object_set_new(obj, "type", json_string(packet_type_names[packet->type]));
|
json_object_set_new(obj, "type", json_string(packet_type_names[packet->type]));
|
||||||
if (packet->mlat_timestamp) {
|
if (packet->mlat_timestamp) {
|
||||||
json_object_set_new(obj, "mlat_timestamp", json_integer(packet->mlat_timestamp));
|
json_object_set_new(obj, "mlat_timestamp", json_integer(packet->mlat_timestamp));
|
||||||
@@ -68,6 +49,10 @@ static void json_serialize_mode_s_long(struct packet *packet, struct buf *buf) {
|
|||||||
json_serialize_to_buf(out, buf);
|
json_serialize_to_buf(out, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void json_init() {
|
||||||
|
assert(JSON_INTEGER_IS_LONG_LONG);
|
||||||
|
}
|
||||||
|
|
||||||
void json_serialize(struct packet *packet, struct buf *buf) {
|
void json_serialize(struct packet *packet, struct buf *buf) {
|
||||||
if (!packet) {
|
if (!packet) {
|
||||||
json_hello(buf);
|
json_hello(buf);
|
||||||
@@ -87,3 +72,13 @@ void json_serialize(struct packet *packet, struct buf *buf) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int json_buf_append_callback(const char *buffer, size_t size, void *data) {
|
||||||
|
struct buf *buf = data;
|
||||||
|
if (buf->length + size + 1 > BUF_LEN_MAX) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(buf_at(buf, buf->length), buffer, size);
|
||||||
|
buf->length += size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
3
json.h
3
json.h
@@ -1,8 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
|
|
||||||
void json_init();
|
void json_init();
|
||||||
void json_serialize(struct packet *, struct buf *);
|
void json_serialize(struct packet *, struct buf *);
|
||||||
|
|
||||||
|
|||||||
15
raw.c
15
raw.c
@@ -1,12 +1,10 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "raw.h"
|
#include "raw.h"
|
||||||
|
|
||||||
|
|
||||||
struct __attribute__((packed)) raw_mode_s_short_overlay {
|
struct __attribute__((packed)) raw_mode_s_short_overlay {
|
||||||
char asterisk;
|
char asterisk;
|
||||||
char payload[14];
|
char payload[14];
|
||||||
@@ -21,12 +19,6 @@ struct __attribute__((packed)) raw_mode_s_long_overlay {
|
|||||||
char lf;
|
char lf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void raw_init() {
|
|
||||||
assert(sizeof(struct raw_mode_s_short_overlay) < BUF_LEN_MAX);
|
|
||||||
assert(sizeof(struct raw_mode_s_long_overlay) < BUF_LEN_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool raw_parse_mode_s_short(struct buf *buf, struct packet *packet) {
|
static bool raw_parse_mode_s_short(struct buf *buf, struct packet *packet) {
|
||||||
struct raw_mode_s_short_overlay *short_overlay = (struct raw_mode_s_short_overlay *) buf_at(buf, 0);
|
struct raw_mode_s_short_overlay *short_overlay = (struct raw_mode_s_short_overlay *) buf_at(buf, 0);
|
||||||
if (buf->length < sizeof(*short_overlay) ||
|
if (buf->length < sizeof(*short_overlay) ||
|
||||||
@@ -55,9 +47,12 @@ static bool raw_parse_mode_s_long(struct buf *buf, struct packet *packet) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool raw_parse(struct backend *backend, struct packet *packet) {
|
void raw_init() {
|
||||||
struct buf *buf = &backend->buf;
|
assert(sizeof(struct raw_mode_s_short_overlay) < BUF_LEN_MAX);
|
||||||
|
assert(sizeof(struct raw_mode_s_long_overlay) < BUF_LEN_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool raw_parse(struct buf *buf, struct packet *packet, void *state_in) {
|
||||||
return (
|
return (
|
||||||
raw_parse_mode_s_short(buf, packet) ||
|
raw_parse_mode_s_short(buf, packet) ||
|
||||||
raw_parse_mode_s_long(buf, packet));
|
raw_parse_mode_s_long(buf, packet));
|
||||||
|
|||||||
7
raw.h
7
raw.h
@@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "backend.h"
|
|
||||||
#include "common.h"
|
struct buf;
|
||||||
|
struct packet;
|
||||||
|
|
||||||
void raw_init();
|
void raw_init();
|
||||||
bool raw_parse(struct backend *, struct packet *);
|
bool raw_parse(struct buf *, struct packet *, void *);
|
||||||
|
|||||||
4
stats.c
4
stats.c
@@ -3,23 +3,19 @@
|
|||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "backend.h"
|
|
||||||
#include "json.h"
|
#include "json.h"
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
|
|
||||||
|
|
||||||
static struct stats_state {
|
static struct stats_state {
|
||||||
uint64_t total_count;
|
uint64_t total_count;
|
||||||
uint64_t type_count[NUM_TYPES];
|
uint64_t type_count[NUM_TYPES];
|
||||||
struct timespec start;
|
struct timespec start;
|
||||||
} stats_state = { 0 };
|
} stats_state = { 0 };
|
||||||
|
|
||||||
|
|
||||||
void stats_init() {
|
void stats_init() {
|
||||||
assert(clock_gettime(CLOCK_MONOTONIC, &stats_state.start) == 0);
|
assert(clock_gettime(CLOCK_MONOTONIC, &stats_state.start) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void stats_serialize(struct packet *packet, struct buf *buf) {
|
void stats_serialize(struct packet *packet, struct buf *buf) {
|
||||||
if (packet) {
|
if (packet) {
|
||||||
stats_state.total_count++;
|
stats_state.total_count++;
|
||||||
|
|||||||
Reference in New Issue
Block a user