Harden the stratux output a bit: use safe_snprintf, jsonEscapeString

This commit is contained in:
Oliver Jowett 2020-09-08 23:22:53 +08:00
parent ec90edcd8d
commit da3e9766de
1 changed files with 46 additions and 43 deletions

View File

@ -86,6 +86,11 @@ static void writeFATSVPositionUpdate(float lat, float lon, float alt);
static void autoset_modeac(); static void autoset_modeac();
__attribute__ ((format (printf,3,0))) static char *safe_vsnprintf(char *p, char *end, const char *format, va_list ap);
__attribute__ ((format (printf,3,4))) static char *safe_snprintf(char *p, char *end, const char *format, ...);
static const char *jsonEscapeString(const char *str);
// //
//========================================================================= //=========================================================================
// //
@ -785,6 +790,8 @@ static void send_sbs_heartbeat(struct net_service *service)
// //
// Write Stratux output to TCP clients // Write Stratux output to TCP clients
// //
#define STRATUX_MAX_PACKET_SIZE 1000
static void modesSendStratuxOutput(struct modesMessage *mm, struct aircraft *a) { static void modesSendStratuxOutput(struct modesMessage *mm, struct aircraft *a) {
char *p; char *p;
struct timespec now; struct timespec now;
@ -806,14 +813,12 @@ static void modesSendStratuxOutput(struct modesMessage *mm, struct aircraft *a)
if (!mm->reliable && !a->reliable) if (!mm->reliable && !a->reliable)
return; return;
//// For now, suppress non-ICAO addresses p = prepareWrite(&Modes.stratux_out, STRATUX_MAX_PACKET_SIZE); // larger buffer size needed vs SBS
//if (mm->addr & MODES_NON_ICAO_ADDRESS)
// return;
p = prepareWrite(&Modes.stratux_out, 1000); // larger buffer size needed vs SBS
if (!p) if (!p)
return; return;
char *end = p + STRATUX_MAX_PACKET_SIZE;
// Begin populating the traffic.go fields. // Begin populating the traffic.go fields.
// ICAO address, Mode S message types, and signal level // ICAO address, Mode S message types, and signal level
@ -824,7 +829,7 @@ static void modesSendStratuxOutput(struct modesMessage *mm, struct aircraft *a)
cacf = mm->CF; cacf = mm->CF;
} }
p += sprintf(p, p = safe_snprintf(p, end,
"{\"Icao_addr\":%d," "{\"Icao_addr\":%d,"
"\"DF\":%d,\"CA\":%d," "\"DF\":%d,\"CA\":%d,"
"\"TypeCode\":%d," "\"TypeCode\":%d,"
@ -846,68 +851,68 @@ static void modesSendStratuxOutput(struct modesMessage *mm, struct aircraft *a)
//// callsign //// callsign
if (mm->callsign_valid) if (mm->callsign_valid)
p += sprintf(p, "\"Tail\":\"%s\",", mm->callsign); p = safe_snprintf(p, end, "\"Tail\":\"%s\",", jsonEscapeString(mm->callsign));
else else
p += sprintf(p, "\"Tail\":null,"); p = safe_snprintf(p, end, "\"Tail\":null,");
//// altitude & gnss //// altitude & gnss
bool alt_is_geom; bool alt_is_geom;
if (mm->altitude_baro_valid) { if (mm->altitude_baro_valid) {
p += sprintf(p, "\"Alt\":%d,",mm->altitude_baro); p = safe_snprintf(p, end, "\"Alt\":%d,",mm->altitude_baro);
alt_is_geom = false; alt_is_geom = false;
} else if (mm->altitude_geom_valid) { } else if (mm->altitude_geom_valid) {
p += sprintf(p, "\"Alt\":%d,",mm->altitude_geom); p = safe_snprintf(p, end, "\"Alt\":%d,",mm->altitude_geom);
alt_is_geom = true; alt_is_geom = true;
} else { } else {
p += sprintf(p, "\"Alt\":null,"); p = safe_snprintf(p, end, "\"Alt\":null,");
alt_is_geom = false; alt_is_geom = false;
} }
// altitude source // altitude source
if (alt_is_geom) if (alt_is_geom)
p += sprintf(p, "\"AltIsGNSS\":true,"); p = safe_snprintf(p, end, "\"AltIsGNSS\":true,");
else else
p += sprintf(p, "\"AltIsGNSS\":false,"); p = safe_snprintf(p, end, "\"AltIsGNSS\":false,");
// GNSS alt. delta From baro alt. // GNSS alt. delta From baro alt.
if (trackDataValid(&a->geom_delta_valid)) if (trackDataValid(&a->geom_delta_valid))
p += sprintf(p, "\"GnssDiffFromBaroAlt\":%d,",a->geom_delta); p = safe_snprintf(p, end, "\"GnssDiffFromBaroAlt\":%d,",a->geom_delta);
else else
p += sprintf(p, "\"GnssDiffFromBaroAlt\":null,"); p = safe_snprintf(p, end, "\"GnssDiffFromBaroAlt\":null,");
//// ////
//// ground speed and track //// ground speed and track
if (mm->gs_valid) if (mm->gs_valid)
p += sprintf(p, "\"Speed_valid\":true,\"Speed\":%.0f,", mm->gs.selected); p = safe_snprintf(p, end, "\"Speed_valid\":true,\"Speed\":%.0f,", mm->gs.selected);
else else
p += sprintf(p, "\"Speed_valid\":false,\"Speed\":null,"); p = safe_snprintf(p, end, "\"Speed_valid\":false,\"Speed\":null,");
//// ground heading //// ground heading
if (mm->heading_valid && mm->heading_type == HEADING_GROUND_TRACK) if (mm->heading_valid && mm->heading_type == HEADING_GROUND_TRACK)
p += sprintf(p, "\"Track\":%.0f,", mm->heading); p = safe_snprintf(p, end, "\"Track\":%.0f,", mm->heading);
else else
p += sprintf(p, "\"Track\":null,"); p = safe_snprintf(p, end, "\"Track\":null,");
//// position //// position
if (mm->cpr_decoded) if (mm->cpr_decoded)
p += sprintf(p, "\"Lat\":%.6f,\"Lng\":%.6f,\"Position_valid\":true,", p = safe_snprintf(p, end, "\"Lat\":%.6f,\"Lng\":%.6f,\"Position_valid\":true,",
mm->decoded_lat, mm->decoded_lon); mm->decoded_lat, mm->decoded_lon);
else else
p += sprintf(p, "\"Lat\":null,\"Lng\":null,\"Position_valid\":false,"); p = safe_snprintf(p, end, "\"Lat\":null,\"Lng\":null,\"Position_valid\":false,");
//// vrate (use barometric if possible) //// vrate (use barometric if possible)
if (mm->baro_rate_valid) if (mm->baro_rate_valid)
p += sprintf(p, "\"Vvel\":%d,", mm->baro_rate); p = safe_snprintf(p, end, "\"Vvel\":%d,", mm->baro_rate);
else if (mm->geom_rate_valid) else if (mm->geom_rate_valid)
p += sprintf(p, "\"Vvel\":%d,", mm->geom_rate); p = safe_snprintf(p, end, "\"Vvel\":%d,", mm->geom_rate);
else else
p += sprintf(p, "\"Vvel\":null,"); p = safe_snprintf(p, end, "\"Vvel\":null,");
//// squawk //// squawk
if (mm->squawk_valid) if (mm->squawk_valid)
p += sprintf(p, "\"Squawk\":%x,", mm->squawk); p = safe_snprintf(p, end, "\"Squawk\":%x,", mm->squawk);
else else
p += sprintf(p, "\"Squawk\":null,"); p = safe_snprintf(p, end, "\"Squawk\":null,");
// TODO: squawk changing alert support in stratux? // TODO: squawk changing alert support in stratux?
// TODO: squawk emergency flag? // TODO: squawk emergency flag?
@ -916,61 +921,59 @@ static void modesSendStratuxOutput(struct modesMessage *mm, struct aircraft *a)
// airground // airground
switch (mm->airground) { switch (mm->airground) {
case AG_GROUND: case AG_GROUND:
p += sprintf(p, "\"OnGround\":true,"); p = safe_snprintf(p, end, "\"OnGround\":true,");
break; break;
case AG_AIRBORNE: case AG_AIRBORNE:
p += sprintf(p, "\"OnGround\":false,"); p = safe_snprintf(p, end, "\"OnGround\":false,");
break; break;
default: default:
p += sprintf(p, "\"OnGround\":null,"); p = safe_snprintf(p, end, "\"OnGround\":null,");
} }
// navigation accuracy category - position // navigation accuracy category - position
if (mm->accuracy.nac_p_valid) { if (mm->accuracy.nac_p_valid) {
p += sprintf(p, "\"NACp\":%d,", mm->accuracy.nac_p); p = safe_snprintf(p, end, "\"NACp\":%d,", mm->accuracy.nac_p);
} else { } else {
p += sprintf(p, "\"NACp\":null,"); p = safe_snprintf(p, end, "\"NACp\":null,");
} }
// emitter type // emitter type
int emitter = 0; int emitter = -1;
int setEmitter = 0;
if ((mm->msgtype == 17) || (mm->msgtype == 18)) { if ((mm->msgtype == 17) || (mm->msgtype == 18)) {
switch (mm->metype) { switch (mm->metype) {
case 1: case 1:
emitter = ((mm->mesub) | 0x18); emitter = ((mm->mesub) | 0x18);
setEmitter = 1;
break; break;
case 2: case 2:
emitter = ((mm->mesub) | 0x10); emitter = ((mm->mesub) | 0x10);
setEmitter = 1;
break; break;
case 3: case 3:
emitter = ((mm->mesub) | 0x08); emitter = ((mm->mesub) | 0x08);
setEmitter = 1;
break; break;
case 4: case 4:
emitter = (mm->mesub); emitter = (mm->mesub);
setEmitter = 1;
break; break;
} }
} }
if (setEmitter) if (emitter >= 0)
p += sprintf(p, "\"Emitter_category\":%d,", emitter); p = safe_snprintf(p, end, "\"Emitter_category\":%d,", emitter);
else else
p += sprintf(p, "\"Emitter_category\":null,"); p = safe_snprintf(p, end, "\"Emitter_category\":null,");
// Time message received (based on system clock). Format is 2016-02-20T06:35:43.155Z // Time message received (based on system clock). Format is 2016-02-20T06:35:43.155Z
p += sprintf(p, "\"Timestamp\":\"%04d-%02d-%02dT%02d:%02d:%02d.%03dZ\"", p = safe_snprintf(p, end, "\"Timestamp\":\"%04d-%02d-%02dT%02d:%02d:%02d.%03dZ\"",
(stTime_receive.tm_year+1900),(stTime_receive.tm_mon+1), (stTime_receive.tm_year+1900),(stTime_receive.tm_mon+1),
stTime_receive.tm_mday, stTime_receive.tm_hour, stTime_receive.tm_mday, stTime_receive.tm_hour,
stTime_receive.tm_min, stTime_receive.tm_sec, stTime_receive.tm_min, stTime_receive.tm_sec,
(unsigned)(mm->sysTimestampMsg % 1000)); (unsigned)(mm->sysTimestampMsg % 1000));
p += sprintf(p, "}\r\n"); p = safe_snprintf(p, end, "}\r\n");
if (p < end)
completeWrite(&Modes.stratux_out, p); completeWrite(&Modes.stratux_out, p);
else
fprintf(stderr, "stratux: output too large (max %d, overran by %d)\n", STRATUX_MAX_PACKET_SIZE, (int) (p - end));
} }
static void send_stratux_heartbeat(struct net_service *service) static void send_stratux_heartbeat(struct net_service *service)