Switch everything over to safe_snprintf

Rework the aircraft json overflow/resize case
Add more fields to the json, reorder to match header ordering
This commit is contained in:
Oliver Jowett 2018-03-07 20:10:50 +00:00
parent 0608e31965
commit d8f568e0ce

239
net_io.c
View file

@ -1106,7 +1106,7 @@ static const char *jsonEscapeString(const char *str) {
*out++ = '\\'; *out++ = '\\';
*out++ = ch; *out++ = ch;
} else if (ch < 32 || ch > 127) { } else if (ch < 32 || ch > 127) {
out += snprintf(out, end - out, "\\u%04x", ch); out = safe_snprintf(out, end, "\\u%04x", ch);
} else { } else {
*out++ = ch; *out++ = ch;
} }
@ -1118,36 +1118,66 @@ static const char *jsonEscapeString(const char *str) {
static char *append_flags(char *p, char *end, struct aircraft *a, datasource_t source) static char *append_flags(char *p, char *end, struct aircraft *a, datasource_t source)
{ {
p += snprintf(p, end-p, "["); p = safe_snprintf(p, end, "[");
if (a->squawk_valid.source == source)
p += snprintf(p, end-p, "\"squawk\","); char *start = p;
if (a->callsign_valid.source == source) if (a->callsign_valid.source == source)
p += snprintf(p, end-p, "\"callsign\","); p = safe_snprintf(p, end, "\"callsign\",");
if (a->position_valid.source == source)
p += snprintf(p, end-p, "\"lat\",\"lon\",");
if (a->altitude_baro_valid.source == source) if (a->altitude_baro_valid.source == source)
p += snprintf(p, end-p, "\"altitude\","); p = safe_snprintf(p, end, "\"altitude\",");
if (a->altitude_geom_valid.source == source) if (a->altitude_geom_valid.source == source)
p += snprintf(p, end-p, "\"alt_geom\","); p = safe_snprintf(p, end, "\"alt_geom\",");
if (a->track_valid.source == source)
p += snprintf(p, end-p, "\"track\",");
if (a->mag_heading_valid.source == source)
p += snprintf(p, end-p, "\"mag_heading\",");
if (a->true_heading_valid.source == source)
p += snprintf(p, end-p, "\"true_heading\",");
if (a->gs_valid.source == source) if (a->gs_valid.source == source)
p += snprintf(p, end-p, "\"gs\","); p = safe_snprintf(p, end, "\"gs\",");
if (a->ias_valid.source == source) if (a->ias_valid.source == source)
p += snprintf(p, end-p, "\"ias\","); p = safe_snprintf(p, end, "\"ias\",");
if (a->tas_valid.source == source) if (a->tas_valid.source == source)
p += snprintf(p, end-p, "\"tas\","); p = safe_snprintf(p, end, "\"tas\",");
if (a->mach_valid.source == source)
p = safe_snprintf(p, end, "\"mach\",");
if (a->track_valid.source == source)
p = safe_snprintf(p, end, "\"track\",");
if (a->track_rate_valid.source == source)
p = safe_snprintf(p, end, "\"track_rate\",");
if (a->roll_valid.source == source)
p = safe_snprintf(p, end, "\"roll\",");
if (a->mag_heading_valid.source == source)
p = safe_snprintf(p, end, "\"mag_heading\",");
if (a->true_heading_valid.source == source)
p = safe_snprintf(p, end, "\"true_heading\",");
if (a->baro_rate_valid.source == source) if (a->baro_rate_valid.source == source)
p += snprintf(p, end-p, "\"baro_rate\","); p = safe_snprintf(p, end, "\"baro_rate\",");
if (a->geom_rate_valid.source == source) if (a->geom_rate_valid.source == source)
p += snprintf(p, end-p, "\"geom_rate\","); p = safe_snprintf(p, end, "\"geom_rate\",");
if (p[-1] != '[') if (a->squawk_valid.source == source)
p = safe_snprintf(p, end, "\"squawk\",");
if (a->emergency_valid.source == source)
p = safe_snprintf(p, end, "\"emergency\",");
if (a->nav_qnh_valid.source == source)
p = safe_snprintf(p, end, "\"nav_qnh\",");
if (a->nav_altitude_valid.source == source)
p = safe_snprintf(p, end, "\"nav_altitude\",");
if (a->nav_heading_valid.source == source)
p = safe_snprintf(p, end, "\"nav_heading\",");
if (a->nav_modes_valid.source == source)
p = safe_snprintf(p, end, "\"nav_modes\",");
if (a->position_valid.source == source)
p = safe_snprintf(p, end, "\"lat\",\"lon\",\"nic\",\"rc\",");
if (a->nic_baro_valid.source == source)
p = safe_snprintf(p, end, "\"nic_baro\",");
if (a->nac_p_valid.source == source)
p = safe_snprintf(p, end, "\"nac_p\",");
if (a->nac_v_valid.source == source)
p = safe_snprintf(p, end, "\"nac_v\",");
if (a->sil_valid.source == source)
p = safe_snprintf(p, end, "\"sil\",\"sil_type\",");
if (a->gva_valid.source == source)
p = safe_snprintf(p, end, "\"gva\",");
if (a->sda_valid.source == source)
p = safe_snprintf(p, end, "\"sda\",");
if (start > p)
--p; --p;
p += snprintf(p, end-p, "]"); p = safe_snprintf(p, end, "]");
return p; return p;
} }
@ -1173,11 +1203,11 @@ static char *append_nav_modes(char *p, char *end, nav_modes_t flags, const char
} }
if (!first) { if (!first) {
p += snprintf(p, end-p, "%s", sep); p = safe_snprintf(p, end, "%s", sep);
} }
first = 0; first = 0;
p += snprintf(p, end-p, "%s%s%s", quote, nav_modes_names[i].name, quote); p = safe_snprintf(p, end, "%s%s%s", quote, nav_modes_names[i].name, quote);
} }
return p; return p;
@ -1240,13 +1270,16 @@ static const char *sil_type_enum_string(sil_type_t type)
char *generateAircraftJson(const char *url_path, int *len) { char *generateAircraftJson(const char *url_path, int *len) {
uint64_t now = mstime(); uint64_t now = mstime();
struct aircraft *a; struct aircraft *a;
int buflen = 1024; // The initial buffer is incremented as needed int buflen = 32768; // The initial buffer is resized as needed
char *buf = (char *) malloc(buflen), *p = buf, *end = buf+buflen; char *buf = (char *) malloc(buflen), *p = buf, *end = buf+buflen;
char *line_start;
int first = 1; int first = 1;
MODES_NOTUSED(url_path); MODES_NOTUSED(url_path);
p += snprintf(p, end-p, _messageNow = now;
p = safe_snprintf(p, end,
"{ \"now\" : %.1f,\n" "{ \"now\" : %.1f,\n"
" \"messages\" : %u,\n" " \"messages\" : %u,\n"
" \"aircraft\" : [", " \"aircraft\" : [",
@ -1263,82 +1296,102 @@ char *generateAircraftJson(const char *url_path, int *len) {
else else
*p++ = ','; *p++ = ',';
p += snprintf(p, end-p, "\n {\"hex\":\"%s%06x\"", (a->addr & MODES_NON_ICAO_ADDRESS) ? "~" : "", a->addr & 0xFFFFFF); retry:
line_start = p;
p = safe_snprintf(p, end, "\n {\"hex\":\"%s%06x\"", (a->addr & MODES_NON_ICAO_ADDRESS) ? "~" : "", a->addr & 0xFFFFFF);
if (a->addrtype != ADDR_ADSB_ICAO) if (a->addrtype != ADDR_ADSB_ICAO)
p += snprintf(p, end-p, ",\"type\":\"%s\"", addrtype_enum_string(a->addrtype)); p = safe_snprintf(p, end, ",\"type\":\"%s\"", addrtype_enum_string(a->addrtype));
if (a->adsb_version >= 0)
p += snprintf(p, end-p, ",\"version\":%d", a->adsb_version);
if (trackDataValid(&a->squawk_valid))
p += snprintf(p, end-p, ",\"squawk\":\"%04x\"", a->squawk);
if (trackDataValid(&a->callsign_valid)) if (trackDataValid(&a->callsign_valid))
p += snprintf(p, end-p, ",\"flight\":\"%s\"", jsonEscapeString(a->callsign)); p = safe_snprintf(p, end, ",\"flight\":\"%s\"", jsonEscapeString(a->callsign));
if (trackDataValid(&a->position_valid))
p += snprintf(p, end-p, ",\"lat\":%f,\"lon\":%f,\"nic\":%u,\"rc\":%u\"seen_pos\":%.1f", a->lat, a->lon, a->pos_nic, a->pos_rc, (now - a->position_valid.updated)/1000.0);
if (trackDataValid(&a->airground_valid) && a->airground_valid.source >= SOURCE_MODE_S_CHECKED && a->airground == AG_GROUND) if (trackDataValid(&a->airground_valid) && a->airground_valid.source >= SOURCE_MODE_S_CHECKED && a->airground == AG_GROUND)
p += snprintf(p, end-p, ",\"altitude\":\"ground\""); p = safe_snprintf(p, end, ",\"altitude\":\"ground\"");
else { else {
if (trackDataValid(&a->altitude_baro_valid)) if (trackDataValid(&a->altitude_baro_valid))
p += snprintf(p, end-p, ",\"altitude\":%d", a->altitude_baro); p = safe_snprintf(p, end, ",\"altitude\":%d", a->altitude_baro);
if (trackDataValid(&a->altitude_geom_valid)) if (trackDataValid(&a->altitude_geom_valid))
p += snprintf(p, end-p, ",\"alt_geom\":%d", a->altitude_geom); p = safe_snprintf(p, end, ",\"alt_geom\":%d", a->altitude_geom);
} }
if (trackDataValid(&a->baro_rate_valid))
p += snprintf(p, end-p, ",\"baro_rate\":%d", a->baro_rate);
if (trackDataValid(&a->geom_rate_valid))
p += snprintf(p, end-p, ",\"geom_rate\":%d", a->geom_rate);
if (trackDataValid(&a->track_valid))
p += snprintf(p, end-p, ",\"track\":%.1f", a->track);
if (trackDataValid(&a->track_rate_valid))
p += snprintf(p, end-p, ",\"track_rate\":%.2f", a->track_rate);
if (trackDataValid(&a->mag_heading_valid))
p += snprintf(p, end-p, ",\"mag_heading\":%.1f", a->mag_heading);
if (trackDataValid(&a->true_heading_valid))
p += snprintf(p, end-p, ",\"true_heading\":%.1f", a->true_heading);
if (trackDataValid(&a->gs_valid)) if (trackDataValid(&a->gs_valid))
p += snprintf(p, end-p, ",\"gs\":%.1f", a->gs); p = safe_snprintf(p, end, ",\"gs\":%.1f", a->gs);
if (trackDataValid(&a->ias_valid)) if (trackDataValid(&a->ias_valid))
p += snprintf(p, end-p, ",\"ias\":%u", a->ias); p = safe_snprintf(p, end, ",\"ias\":%u", a->ias);
if (trackDataValid(&a->tas_valid)) if (trackDataValid(&a->tas_valid))
p += snprintf(p, end-p, ",\"tas\":%u", a->tas); p = safe_snprintf(p, end, ",\"tas\":%u", a->tas);
if (trackDataValid(&a->mach_valid)) if (trackDataValid(&a->mach_valid))
p += snprintf(p, end-p, ",\"mach\":%.3f", a->mach); p = safe_snprintf(p, end, ",\"mach\":%.3f", a->mach);
if (trackDataValid(&a->track_valid))
p = safe_snprintf(p, end, ",\"track\":%.1f", a->track);
if (trackDataValid(&a->track_rate_valid))
p = safe_snprintf(p, end, ",\"track_rate\":%.2f", a->track_rate);
if (trackDataValid(&a->roll_valid)) if (trackDataValid(&a->roll_valid))
p += snprintf(p, end-p, ",\"roll\":%.1f", a->roll); p = safe_snprintf(p, end, ",\"roll\":%.1f", a->roll);
if (trackDataValid(&a->mag_heading_valid))
p = safe_snprintf(p, end, ",\"mag_heading\":%.1f", a->mag_heading);
if (trackDataValid(&a->true_heading_valid))
p = safe_snprintf(p, end, ",\"true_heading\":%.1f", a->true_heading);
if (trackDataValid(&a->baro_rate_valid))
p = safe_snprintf(p, end, ",\"baro_rate\":%d", a->baro_rate);
if (trackDataValid(&a->geom_rate_valid))
p = safe_snprintf(p, end, ",\"geom_rate\":%d", a->geom_rate);
if (trackDataValid(&a->squawk_valid))
p = safe_snprintf(p, end, ",\"squawk\":\"%04x\"", a->squawk);
if (trackDataValid(&a->emergency_valid))
p = safe_snprintf(p, end, ",\"emergency\":\"%s\"", emergency_enum_string(a->emergency));
if (a->category != 0) if (a->category != 0)
p += snprintf(p, end-p, ",\"category\":\"%02X\"", a->category); p = safe_snprintf(p, end, ",\"category\":\"%02X\"", a->category);
if (trackDataValid(&a->nav_altitude_valid))
p += snprintf(p, end-p, ",\"nav_alt\":%d", a->nav_altitude);
if (trackDataValid(&a->nav_heading_valid))
p += snprintf(p, end-p, ",\"nav_heading\":%.1f", a->nav_heading);
if (trackDataValid(&a->nav_modes_valid)) {
p += snprintf(p, end-p, ",\"nav_modes\":[");
p = append_nav_modes(p, end, a->nav_modes, "\"", ",");
p += snprintf(p, end-p, "]");
}
if (trackDataValid(&a->nav_qnh_valid)) if (trackDataValid(&a->nav_qnh_valid))
p += snprintf(p, end-p, ",\"nav_qnh\":%.1f", a->nav_qnh); p = safe_snprintf(p, end, ",\"nav_qnh\":%.1f", a->nav_qnh);
if (trackDataValid(&a->nav_altitude_valid))
p = safe_snprintf(p, end, ",\"nav_altitude\":%d", a->nav_altitude);
if (trackDataValid(&a->nav_heading_valid))
p = safe_snprintf(p, end, ",\"nav_heading\":%.1f", a->nav_heading);
if (trackDataValid(&a->nav_modes_valid)) {
p = safe_snprintf(p, end, ",\"nav_modes\":[");
p = append_nav_modes(p, end, a->nav_modes, "\"", ",");
p = safe_snprintf(p, end, "]");
}
if (trackDataValid(&a->position_valid))
p = safe_snprintf(p, end, ",\"lat\":%f,\"lon\":%f,\"nic\":%u,\"rc\":%u,\"seen_pos\":%.1f", a->lat, a->lon, a->pos_nic, a->pos_rc, (now - a->position_valid.updated)/1000.0);
if (a->adsb_version >= 0)
p = safe_snprintf(p, end, ",\"version\":%d", a->adsb_version);
if (trackDataValid(&a->nic_baro_valid))
p = safe_snprintf(p, end, ",\"nic_baro\":%u", a->nic_baro);
if (trackDataValid(&a->nac_p_valid))
p = safe_snprintf(p, end, ",\"nac_p\":%u", a->nac_p);
if (trackDataValid(&a->nac_v_valid))
p = safe_snprintf(p, end, ",\"nac_v\":%u", a->nac_v);
if (trackDataValid(&a->sil_valid))
p = safe_snprintf(p, end, ",\"sil\":%u", a->sil);
if (a->sil_type != SIL_INVALID)
p = safe_snprintf(p, end, ",\"sil_type\":\"%s\"", sil_type_enum_string(a->sil_type));
if (trackDataValid(&a->gva_valid))
p = safe_snprintf(p, end, ",\"gva\":%u", a->gva);
if (trackDataValid(&a->sda_valid))
p = safe_snprintf(p, end, ",\"sda\":%u", a->sda);
p += snprintf(p, end-p, ",\"mlat\":");
p = safe_snprintf(p, end, ",\"mlat\":");
p = append_flags(p, end, a, SOURCE_MLAT); p = append_flags(p, end, a, SOURCE_MLAT);
p += snprintf(p, end-p, ",\"tisb\":"); p = safe_snprintf(p, end, ",\"tisb\":");
p = append_flags(p, end, a, SOURCE_TISB); p = append_flags(p, end, a, SOURCE_TISB);
p += snprintf(p, end-p, ",\"messages\":%ld,\"seen\":%.1f,\"rssi\":%.1f}", p = safe_snprintf(p, end, ",\"messages\":%ld,\"seen\":%.1f,\"rssi\":%.1f}",
a->messages, (now - a->seen)/1000.0, a->messages, (now - a->seen)/1000.0,
10 * log10((a->signalLevel[0] + a->signalLevel[1] + a->signalLevel[2] + a->signalLevel[3] + 10 * log10((a->signalLevel[0] + a->signalLevel[1] + a->signalLevel[2] + a->signalLevel[3] +
a->signalLevel[4] + a->signalLevel[5] + a->signalLevel[6] + a->signalLevel[7] + 1e-5) / 8)); a->signalLevel[4] + a->signalLevel[5] + a->signalLevel[6] + a->signalLevel[7] + 1e-5) / 8));
// If we're getting near the end of the buffer, expand it. if (p >= end) {
if ((end - p) < 512) { // overran the buffer
int used = p - buf; int used = line_start - buf;
buflen *= 2; buflen *= 2;
buf = (char *) realloc(buf, buflen); buf = (char *) realloc(buf, buflen);
p = buf+used; p = buf+used;
end = buf + buflen; end = buf + buflen;
goto retry;
} }
} }
p += snprintf(p, end-p, "\n ]\n}\n"); p = safe_snprintf(p, end, "\n ]\n}\n");
*len = p-buf; *len = p-buf;
return buf; return buf;
} }
@ -1350,14 +1403,14 @@ static char * appendStatsJson(char *p,
{ {
int i; int i;
p += snprintf(p, end-p, p = safe_snprintf(p, end,
"\"%s\":{\"start\":%.1f,\"end\":%.1f", "\"%s\":{\"start\":%.1f,\"end\":%.1f",
key, key,
st->start / 1000.0, st->start / 1000.0,
st->end / 1000.0); st->end / 1000.0);
if (!Modes.net_only) { if (!Modes.net_only) {
p += snprintf(p, end-p, p = safe_snprintf(p, end,
",\"local\":{\"samples_processed\":%llu" ",\"local\":{\"samples_processed\":%llu"
",\"samples_dropped\":%llu" ",\"samples_dropped\":%llu"
",\"modeac\":%u" ",\"modeac\":%u"
@ -1372,24 +1425,24 @@ static char * appendStatsJson(char *p,
st->demod_rejected_unknown_icao); st->demod_rejected_unknown_icao);
for (i=0; i <= Modes.nfix_crc; ++i) { for (i=0; i <= Modes.nfix_crc; ++i) {
if (i == 0) p += snprintf(p, end-p, ",\"accepted\":[%u", st->demod_accepted[i]); if (i == 0) p = safe_snprintf(p, end, ",\"accepted\":[%u", st->demod_accepted[i]);
else p += snprintf(p, end-p, ",%u", st->demod_accepted[i]); else p = safe_snprintf(p, end, ",%u", st->demod_accepted[i]);
} }
p += snprintf(p, end-p, "]"); p = safe_snprintf(p, end, "]");
if (st->signal_power_sum > 0 && st->signal_power_count > 0) if (st->signal_power_sum > 0 && st->signal_power_count > 0)
p += snprintf(p, end-p,",\"signal\":%.1f", 10 * log10(st->signal_power_sum / st->signal_power_count)); p = safe_snprintf(p, end, ",\"signal\":%.1f", 10 * log10(st->signal_power_sum / st->signal_power_count));
if (st->noise_power_sum > 0 && st->noise_power_count > 0) if (st->noise_power_sum > 0 && st->noise_power_count > 0)
p += snprintf(p, end-p,",\"noise\":%.1f", 10 * log10(st->noise_power_sum / st->noise_power_count)); p = safe_snprintf(p, end, ",\"noise\":%.1f", 10 * log10(st->noise_power_sum / st->noise_power_count));
if (st->peak_signal_power > 0) if (st->peak_signal_power > 0)
p += snprintf(p, end-p,",\"peak_signal\":%.1f", 10 * log10(st->peak_signal_power)); p = safe_snprintf(p, end, ",\"peak_signal\":%.1f", 10 * log10(st->peak_signal_power));
p += snprintf(p, end-p,",\"strong_signals\":%d}", st->strong_signal_count); p = safe_snprintf(p, end, ",\"strong_signals\":%d}", st->strong_signal_count);
} }
if (Modes.net) { if (Modes.net) {
p += snprintf(p, end-p, p = safe_snprintf(p, end,
",\"remote\":{\"modeac\":%u" ",\"remote\":{\"modeac\":%u"
",\"modes\":%u" ",\"modes\":%u"
",\"bad\":%u" ",\"bad\":%u"
@ -1400,11 +1453,11 @@ static char * appendStatsJson(char *p,
st->remote_rejected_unknown_icao); st->remote_rejected_unknown_icao);
for (i=0; i <= Modes.nfix_crc; ++i) { for (i=0; i <= Modes.nfix_crc; ++i) {
if (i == 0) p += snprintf(p, end-p, ",\"accepted\":[%u", st->remote_accepted[i]); if (i == 0) p = safe_snprintf(p, end, ",\"accepted\":[%u", st->remote_accepted[i]);
else p += snprintf(p, end-p, ",%u", st->remote_accepted[i]); else p = safe_snprintf(p, end, ",%u", st->remote_accepted[i]);
} }
p += snprintf(p, end-p, "]}"); p = safe_snprintf(p, end, "]}");
} }
{ {
@ -1412,7 +1465,7 @@ static char * appendStatsJson(char *p,
uint64_t reader_cpu_millis = (uint64_t)st->reader_cpu.tv_sec*1000UL + st->reader_cpu.tv_nsec/1000000UL; uint64_t reader_cpu_millis = (uint64_t)st->reader_cpu.tv_sec*1000UL + st->reader_cpu.tv_nsec/1000000UL;
uint64_t background_cpu_millis = (uint64_t)st->background_cpu.tv_sec*1000UL + st->background_cpu.tv_nsec/1000000UL; uint64_t background_cpu_millis = (uint64_t)st->background_cpu.tv_sec*1000UL + st->background_cpu.tv_nsec/1000000UL;
p += snprintf(p, end-p, p = safe_snprintf(p, end,
",\"cpr\":{\"surface\":%u" ",\"cpr\":{\"surface\":%u"
",\"airborne\":%u" ",\"airborne\":%u"
",\"global_ok\":%u" ",\"global_ok\":%u"
@ -1464,22 +1517,22 @@ char *generateStatsJson(const char *url_path, int *len) {
MODES_NOTUSED(url_path); MODES_NOTUSED(url_path);
p += snprintf(p, end-p, "{\n"); p = safe_snprintf(p, end, "{\n");
p = appendStatsJson(p, end, &Modes.stats_current, "latest"); p = appendStatsJson(p, end, &Modes.stats_current, "latest");
p += snprintf(p, end-p, ",\n"); p = safe_snprintf(p, end, ",\n");
p = appendStatsJson(p, end, &Modes.stats_1min[Modes.stats_latest_1min], "last1min"); p = appendStatsJson(p, end, &Modes.stats_1min[Modes.stats_latest_1min], "last1min");
p += snprintf(p, end-p, ",\n"); p = safe_snprintf(p, end, ",\n");
p = appendStatsJson(p, end, &Modes.stats_5min, "last5min"); p = appendStatsJson(p, end, &Modes.stats_5min, "last5min");
p += snprintf(p, end-p, ",\n"); p = safe_snprintf(p, end, ",\n");
p = appendStatsJson(p, end, &Modes.stats_15min, "last15min"); p = appendStatsJson(p, end, &Modes.stats_15min, "last15min");
p += snprintf(p, end-p, ",\n"); p = safe_snprintf(p, end, ",\n");
add_stats(&Modes.stats_alltime, &Modes.stats_current, &add); add_stats(&Modes.stats_alltime, &Modes.stats_current, &add);
p = appendStatsJson(p, end, &add, "total"); p = appendStatsJson(p, end, &add, "total");
p += snprintf(p, end-p, "\n}\n"); p = safe_snprintf(p, end, "\n}\n");
assert(p <= end); assert(p <= end);