2016-02-16 02:28:05 +00:00
|
|
|
#include <assert.h>
|
|
|
|
|
#include <stdio.h>
|
2016-02-17 00:21:28 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
#include <jansson.h>
|
2016-02-16 02:28:05 +00:00
|
|
|
|
2016-02-22 16:36:27 -08:00
|
|
|
#include "hex.h"
|
2016-02-22 16:41:34 -08:00
|
|
|
#include "buf.h"
|
2016-02-22 16:58:13 -08:00
|
|
|
#include "packet.h"
|
2016-02-22 16:36:27 -08:00
|
|
|
#include "rand.h"
|
2016-02-17 17:19:57 -08:00
|
|
|
#include "receive.h"
|
|
|
|
|
#include "send.h"
|
2016-02-22 21:55:45 -08:00
|
|
|
#include "server.h"
|
2016-02-22 16:27:44 -08:00
|
|
|
#include "uuid.h"
|
2016-02-22 16:36:27 -08:00
|
|
|
|
2016-02-16 02:28:05 +00:00
|
|
|
#include "json.h"
|
|
|
|
|
|
2016-02-23 14:27:54 -08:00
|
|
|
#define JSON_MAGIC "aDsB"
|
|
|
|
|
|
2016-02-23 13:49:23 -08:00
|
|
|
struct json_parser_state {
|
|
|
|
|
struct packet_mlat_state mlat_state;
|
|
|
|
|
uint16_t mlat_timestamp_mhz;
|
|
|
|
|
uint64_t mlat_timestamp_max;
|
|
|
|
|
uint32_t rssi_max;
|
|
|
|
|
bool have_header;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static json_t *json_prev = NULL;
|
2016-02-27 16:23:26 -08:00
|
|
|
static struct buf json_hello_buf = BUF_INIT;
|
2016-02-23 13:49:23 -08:00
|
|
|
|
2016-02-17 11:59:37 -08:00
|
|
|
static void json_serialize_to_buf(json_t *obj, struct buf *buf) {
|
|
|
|
|
assert(json_dump_callback(obj, json_buf_append_callback, buf, 0) == 0);
|
|
|
|
|
json_decref(obj);
|
|
|
|
|
buf_chr(buf, buf->length++) = '\n';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void json_add_common(struct packet *packet, json_t *obj) {
|
2016-03-03 22:00:02 -08:00
|
|
|
json_object_set_new(obj, "hops", json_integer(packet->hops));
|
2016-02-17 12:13:21 -08:00
|
|
|
json_object_set_new(obj, "type", json_string(packet_type_names[packet->type]));
|
2016-02-25 23:37:37 -08:00
|
|
|
json_object_set_new(obj, "source_id", json_string((const char *) packet->source_id));
|
2016-02-17 11:59:37 -08:00
|
|
|
if (packet->mlat_timestamp) {
|
2016-02-25 23:37:37 -08:00
|
|
|
json_object_set_new(obj, "mlat_timestamp", json_integer(packet->mlat_timestamp % INT64_MAX));
|
2016-02-17 11:59:37 -08:00
|
|
|
}
|
|
|
|
|
if (packet->rssi) {
|
|
|
|
|
json_object_set_new(obj, "rssi", json_integer(packet->rssi));
|
|
|
|
|
}
|
2016-02-16 02:28:05 +00:00
|
|
|
}
|
|
|
|
|
|
2016-02-27 21:50:15 -08:00
|
|
|
static void json_serialize_payload(struct packet *packet, struct buf *buf) {
|
|
|
|
|
size_t bytes = packet_payload_len[packet->type];
|
|
|
|
|
uint8_t hexbuf[PACKET_PAYLOAD_LEN_MAX * 2];
|
|
|
|
|
hex_from_bin_upper(hexbuf, packet->payload, bytes);
|
|
|
|
|
json_t *out = json_pack("{ss#}", "payload", hexbuf, bytes * 2);
|
2016-02-17 11:59:37 -08:00
|
|
|
json_add_common(packet, out);
|
|
|
|
|
json_serialize_to_buf(out, buf);
|
2016-02-16 02:28:05 +00:00
|
|
|
}
|
|
|
|
|
|
2016-02-23 14:27:54 -08:00
|
|
|
static bool json_parse_header(json_t *in, struct packet *packet, struct json_parser_state *state) {
|
|
|
|
|
const char *magic, *json_server_id;
|
|
|
|
|
json_int_t mlat_timestamp_mhz, mlat_timestamp_max, rssi_max;
|
|
|
|
|
if (json_unpack(
|
|
|
|
|
in, "{s:s, s:s, s:I, s:I, s:I}",
|
|
|
|
|
"magic", &magic,
|
|
|
|
|
"server_id", &json_server_id,
|
|
|
|
|
"mlat_timestamp_mhz", &mlat_timestamp_mhz,
|
|
|
|
|
"mlat_timestamp_max", &mlat_timestamp_max,
|
|
|
|
|
"rssi_max", &rssi_max)) {
|
2016-02-23 13:49:23 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-23 14:27:54 -08:00
|
|
|
if (strcmp(magic, JSON_MAGIC)) {
|
2016-02-23 13:49:23 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-25 23:37:37 -08:00
|
|
|
if (mlat_timestamp_mhz > UINT16_MAX ||
|
2016-02-26 23:36:05 -08:00
|
|
|
mlat_timestamp_mhz <= 0 ||
|
|
|
|
|
mlat_timestamp_max <= 0 ||
|
|
|
|
|
rssi_max > UINT32_MAX ||
|
|
|
|
|
rssi_max <= 0) {
|
2016-02-25 23:37:37 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
2016-02-23 13:49:23 -08:00
|
|
|
|
2016-02-25 23:37:37 -08:00
|
|
|
if (!strcmp(json_server_id, (const char *) server_id)) {
|
2016-02-23 14:27:54 -08:00
|
|
|
fprintf(stderr, "R %s: Attempt to receive json data from our own server ID (%s); loop!\n", packet->source_id, server_id);
|
|
|
|
|
return false;
|
2016-02-23 13:49:23 -08:00
|
|
|
}
|
|
|
|
|
|
2016-02-23 14:27:54 -08:00
|
|
|
fprintf(stderr, "R %s: Connected to server ID: %s\n", packet->source_id, json_server_id);
|
|
|
|
|
|
2016-03-03 22:00:02 -08:00
|
|
|
state->mlat_timestamp_mhz = (uint16_t) mlat_timestamp_mhz;
|
|
|
|
|
state->mlat_timestamp_max = (uint64_t) mlat_timestamp_max;
|
|
|
|
|
state->rssi_max = (uint32_t) rssi_max;
|
|
|
|
|
|
2016-02-23 14:27:54 -08:00
|
|
|
state->have_header = true;
|
|
|
|
|
packet->type = PACKET_TYPE_NONE;
|
2016-02-23 13:49:23 -08:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-23 14:27:54 -08:00
|
|
|
static bool json_parse_common(json_t *in, struct packet *packet, struct json_parser_state *state) {
|
|
|
|
|
if (!state->have_header) {
|
2016-02-23 13:56:54 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-03 22:00:02 -08:00
|
|
|
json_int_t hops;
|
|
|
|
|
|
|
|
|
|
if (json_unpack(
|
|
|
|
|
in, "{s:s, s:I}",
|
|
|
|
|
"source_id", &packet->source_id,
|
|
|
|
|
"hops", &hops)) {
|
2016-02-23 13:56:54 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-26 21:14:28 -08:00
|
|
|
if (!packet_validate_id(packet->source_id)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-03 22:00:02 -08:00
|
|
|
if (hops < 0 || hops > UINT32_MAX) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
packet->hops = (uint16_t) hops;
|
|
|
|
|
|
2016-02-23 14:27:54 -08:00
|
|
|
json_t *mlat_timestamp = json_object_get(in, "mlat_timestamp");
|
|
|
|
|
if (mlat_timestamp && json_is_integer(mlat_timestamp)) {
|
2016-02-25 23:37:37 -08:00
|
|
|
json_int_t val = json_integer_value(mlat_timestamp);
|
|
|
|
|
if (val < 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-02-23 14:27:54 -08:00
|
|
|
packet->mlat_timestamp = packet_mlat_timestamp_scale_in(
|
2016-02-25 23:37:37 -08:00
|
|
|
(uint64_t) val,
|
2016-02-23 14:27:54 -08:00
|
|
|
state->mlat_timestamp_max,
|
|
|
|
|
state->mlat_timestamp_mhz,
|
|
|
|
|
&state->mlat_state);
|
2016-02-23 13:56:54 -08:00
|
|
|
}
|
|
|
|
|
|
2016-02-23 14:27:54 -08:00
|
|
|
json_t *rssi = json_object_get(in, "rssi");
|
|
|
|
|
if (rssi && json_is_integer(rssi)) {
|
2016-02-25 23:37:37 -08:00
|
|
|
json_int_t val = json_integer_value(rssi);
|
|
|
|
|
if (val > state->rssi_max) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
packet->rssi = packet_rssi_scale_in((uint32_t) val, state->rssi_max);
|
2016-02-23 13:56:54 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-27 21:50:15 -08:00
|
|
|
static bool json_parse_payload(json_t *in, struct packet *packet, struct json_parser_state *state, enum packet_type type) {
|
|
|
|
|
size_t bytes = packet_payload_len[type];
|
2016-02-23 13:56:54 -08:00
|
|
|
if (!json_parse_common(in, packet, state)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
json_t *payload = json_object_get(in, "payload");
|
2016-02-27 21:50:15 -08:00
|
|
|
if (!payload || !json_is_string(payload) || json_string_length(payload) != bytes * 2) {
|
2016-02-23 13:56:54 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-27 21:50:15 -08:00
|
|
|
if (!hex_to_bin(packet->payload, (const uint8_t *) json_string_value(payload), bytes)) {
|
2016-02-26 14:09:37 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
2016-02-27 21:50:15 -08:00
|
|
|
packet->type = type;
|
2016-02-23 13:56:54 -08:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-27 21:50:15 -08:00
|
|
|
static bool json_parse_mode_ac(json_t *in, struct packet *packet, struct json_parser_state *state) {
|
|
|
|
|
return json_parse_payload(in, packet, state, PACKET_TYPE_MODE_AC);
|
|
|
|
|
}
|
2016-02-23 13:56:54 -08:00
|
|
|
|
2016-02-27 21:50:15 -08:00
|
|
|
static bool json_parse_mode_s_short(json_t *in, struct packet *packet, struct json_parser_state *state) {
|
|
|
|
|
return json_parse_payload(in, packet, state, PACKET_TYPE_MODE_S_SHORT);
|
|
|
|
|
}
|
2016-02-23 13:56:54 -08:00
|
|
|
|
2016-02-27 21:50:15 -08:00
|
|
|
static bool json_parse_mode_s_long(json_t *in, struct packet *packet, struct json_parser_state *state) {
|
|
|
|
|
return json_parse_payload(in, packet, state, PACKET_TYPE_MODE_S_LONG);
|
2016-02-23 13:56:54 -08:00
|
|
|
}
|
|
|
|
|
|
2016-02-17 16:40:09 -08:00
|
|
|
void json_init() {
|
2016-02-23 13:49:23 -08:00
|
|
|
assert(sizeof(struct json_parser_state) <= PARSER_STATE_LEN);
|
2016-02-17 16:40:09 -08:00
|
|
|
assert(JSON_INTEGER_IS_LONG_LONG);
|
2016-02-22 16:27:44 -08:00
|
|
|
|
|
|
|
|
size_t seed;
|
|
|
|
|
rand_fill(&seed, sizeof(seed));
|
|
|
|
|
json_object_seed(seed);
|
2016-02-27 16:23:26 -08:00
|
|
|
|
|
|
|
|
json_t *hello = json_pack(
|
|
|
|
|
"{s:s, s:s, s:s, s:s, s:I, s:I, s:I}",
|
|
|
|
|
"type", "header",
|
|
|
|
|
"magic", JSON_MAGIC,
|
|
|
|
|
"server_version", server_version,
|
|
|
|
|
"server_id", server_id,
|
|
|
|
|
"mlat_timestamp_mhz", (json_int_t) PACKET_MLAT_MHZ,
|
|
|
|
|
"mlat_timestamp_max", (json_int_t) PACKET_MLAT_MAX,
|
|
|
|
|
"rssi_max", (json_int_t) PACKET_RSSI_MAX);
|
|
|
|
|
json_serialize_to_buf(hello, &json_hello_buf);
|
2016-02-17 16:40:09 -08:00
|
|
|
}
|
|
|
|
|
|
2016-02-23 13:49:23 -08:00
|
|
|
void json_cleanup() {
|
|
|
|
|
if (json_prev) {
|
|
|
|
|
json_decref(json_prev);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool json_parse(struct buf *buf, struct packet *packet, void *state_in) {
|
|
|
|
|
struct json_parser_state *state = (struct json_parser_state *) state_in;
|
|
|
|
|
|
|
|
|
|
if (json_prev) {
|
|
|
|
|
json_decref(json_prev);
|
|
|
|
|
json_prev = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
json_error_t err;
|
2016-02-25 23:37:37 -08:00
|
|
|
json_t *in = json_loadb((const char *) buf_at(buf, 0), buf->length, JSON_DISABLE_EOF_CHECK | JSON_REJECT_DUPLICATES, &err);
|
2016-02-23 13:49:23 -08:00
|
|
|
if (!in) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (!json_is_object(in)) {
|
|
|
|
|
json_decref(in);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-02-23 13:56:54 -08:00
|
|
|
|
2016-02-23 13:49:23 -08:00
|
|
|
json_t *type = json_object_get(in, "type");
|
|
|
|
|
if (!type || !json_is_string(type)) {
|
|
|
|
|
json_decref(in);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const char *type_str = json_string_value(type);
|
2016-02-23 13:56:54 -08:00
|
|
|
bool (*parser)(json_t *, struct packet *, struct json_parser_state *) = NULL;
|
2016-02-23 13:49:23 -08:00
|
|
|
if (!strcmp(type_str, "header")) {
|
2016-02-23 13:56:54 -08:00
|
|
|
parser = json_parse_header;
|
2016-02-27 21:50:15 -08:00
|
|
|
} else if (!strcmp(type_str, "Mode-AC")) {
|
|
|
|
|
parser = json_parse_mode_ac;
|
2016-02-23 13:49:23 -08:00
|
|
|
} else if (!strcmp(type_str, "Mode-S short")) {
|
2016-02-23 13:56:54 -08:00
|
|
|
parser = json_parse_mode_s_short;
|
2016-02-23 13:49:23 -08:00
|
|
|
} else if (!strcmp(type_str, "Mode-S long")) {
|
2016-02-23 13:56:54 -08:00
|
|
|
parser = json_parse_mode_s_long;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!parser || !parser(in, packet, state)) {
|
2016-02-23 13:49:23 -08:00
|
|
|
json_decref(in);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-25 23:37:37 -08:00
|
|
|
assert(err.position > 0);
|
|
|
|
|
buf_consume(buf, (size_t) err.position);
|
2016-02-23 13:49:23 -08:00
|
|
|
while (buf->length && (buf_chr(buf, 0) == '\r' || buf_chr(buf, 0) == '\n')) {
|
|
|
|
|
buf_consume(buf, 1);
|
|
|
|
|
}
|
|
|
|
|
json_prev = in;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-17 00:21:28 +00:00
|
|
|
void json_serialize(struct packet *packet, struct buf *buf) {
|
2016-02-16 02:28:05 +00:00
|
|
|
switch (packet->type) {
|
2016-02-25 23:37:37 -08:00
|
|
|
case PACKET_TYPE_NONE:
|
|
|
|
|
break;
|
|
|
|
|
|
2016-02-27 21:50:15 -08:00
|
|
|
case PACKET_TYPE_MODE_AC:
|
2016-02-23 13:49:23 -08:00
|
|
|
case PACKET_TYPE_MODE_S_SHORT:
|
|
|
|
|
case PACKET_TYPE_MODE_S_LONG:
|
2016-02-27 21:50:15 -08:00
|
|
|
json_serialize_payload(packet, buf);
|
2016-02-17 00:21:28 +00:00
|
|
|
break;
|
2016-02-16 02:28:05 +00:00
|
|
|
}
|
|
|
|
|
}
|
2016-02-17 16:40:09 -08:00
|
|
|
|
2016-02-27 16:23:26 -08:00
|
|
|
void json_hello(struct buf **buf) {
|
|
|
|
|
*buf = &json_hello_buf;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-17 16:40:09 -08:00
|
|
|
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;
|
|
|
|
|
}
|