Rationalization of JSON output. Pass actual URL path to URL handler.

(cherry picked from commit becce8d69a6e6cee38d4fdb78b5a4e25d570baea)
This commit is contained in:
Oliver Jowett 2015-01-15 20:54:22 +00:00
parent 63fb121d1c
commit b1bfb4d520
3 changed files with 33 additions and 31 deletions

View file

@ -681,6 +681,7 @@ static void display_stats(void) {
void backgroundTasks(void) { void backgroundTasks(void) {
static time_t next_stats; static time_t next_stats;
static time_t next_json; static time_t next_json;
time_t now = time(NULL);
if (Modes.net) { if (Modes.net) {
modesNetPeriodicWork(); modesNetPeriodicWork();
@ -697,7 +698,6 @@ void backgroundTasks(void) {
} }
if (Modes.stats > 0) { if (Modes.stats > 0) {
time_t now = time(NULL);
if (now > next_stats) { if (now > next_stats) {
if (next_stats != 0) if (next_stats != 0)
display_stats(); display_stats();
@ -705,14 +705,11 @@ void backgroundTasks(void) {
} }
} }
if (Modes.json_aircraft_path) { if ((Modes.json_dir || Modes.net_http_port) && now >= next_json) {
time_t now = time(NULL); writeJsonToFile("aircraft.json", generateAircraftJson);
if (now >= next_json) {
writeJsonToFile(Modes.json_aircraft_path, generateAircraftJson);
next_json = now + Modes.json_interval; next_json = now + Modes.json_interval;
} }
} }
}
// //
//========================================================================= //=========================================================================
@ -907,14 +904,7 @@ int main(int argc, char **argv) {
Modes.oversample = 1; Modes.oversample = 1;
#ifndef _WIN32 #ifndef _WIN32
} else if (!strcmp(argv[j], "--write-json") && more) { } else if (!strcmp(argv[j], "--write-json") && more) {
++j; Modes.json_dir = strdup(argv[++j]);
Modes.json_aircraft_path = malloc(strlen(argv[j]) + 15);
strcpy(Modes.json_aircraft_path, argv[j]);
strcat(Modes.json_aircraft_path, "/aircraft.json");
Modes.json_metadata_path = malloc(strlen(argv[j]) + 15);
strcpy(Modes.json_metadata_path, argv[j]);
strcat(Modes.json_metadata_path, "/receiver.json");
} else if (!strcmp(argv[j], "--write-json-every") && more) { } else if (!strcmp(argv[j], "--write-json-every") && more) {
Modes.json_interval = atoi(argv[++j]); Modes.json_interval = atoi(argv[++j]);
if (Modes.json_interval < 1) if (Modes.json_interval < 1)
@ -972,9 +962,7 @@ int main(int argc, char **argv) {
} }
if (Modes.net) modesInitNet(); if (Modes.net) modesInitNet();
if (Modes.json_metadata_path) { writeJsonToFile("receiver.json", generateReceiverJson); // once only on startup
writeJsonToFile(Modes.json_metadata_path, generateReceiverJson); // once only on startup
}
// If the user specifies --net-only, just run in order to serve network // If the user specifies --net-only, just run in order to serve network
// clients without reading data from the RTL device // clients without reading data from the RTL device

View file

@ -358,8 +358,7 @@ struct { // Internal state
int metric; // Use metric units int metric; // Use metric units
int mlat; // Use Beast ascii format for raw data output, i.e. @...; iso *...; int mlat; // Use Beast ascii format for raw data output, i.e. @...; iso *...;
int interactive_rtl1090; // flight table in interactive mode is formatted like RTL1090 int interactive_rtl1090; // flight table in interactive mode is formatted like RTL1090
char *json_aircraft_path; // Path to json aircraft file to write, or NULL not to. char *json_dir; // Path to json base directory, or NULL not to write json.
char *json_metadata_path; // Path to json metadata file to write, or NULL not to.
int json_interval; // Interval between rewriting the json aircraft file int json_interval; // Interval between rewriting the json aircraft file
int json_location_accuracy; // Accuracy of location metadata: 0=none, 1=approx, 2=exact int json_location_accuracy; // Accuracy of location metadata: 0=none, 1=approx, 2=exact
@ -485,9 +484,9 @@ void modesQueueOutput (struct modesMessage *mm);
void modesReadFromClient(struct client *c, char *sep, int(*handler)(struct client *, char *)); void modesReadFromClient(struct client *c, char *sep, int(*handler)(struct client *, char *));
void modesNetPeriodicWork (void); void modesNetPeriodicWork (void);
void writeJsonToFile(const char *path, char * (*generator) (int*)); void writeJsonToFile(const char *file, char * (*generator) (const char*,int*));
char *generateAircraftJson(int *len); char *generateAircraftJson(const char *url_path, int *len);
char *generateReceiverJson(int *len); char *generateReceiverJson(const char *url_path, int *len);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -667,13 +667,15 @@ int decodeHexMessage(struct client *c, char *hex) {
// //
// Return a description of planes in json. No metric conversion // Return a description of planes in json. No metric conversion
// //
char *generateAircraftJson(int *len) { char *generateAircraftJson(const char *url_path, int *len) {
time_t now = time(NULL); time_t now = time(NULL);
struct aircraft *a = Modes.aircrafts; struct aircraft *a = Modes.aircrafts;
int buflen = 1024; // The initial buffer is incremented as needed int buflen = 1024; // The initial buffer is incremented as needed
char *buf = (char *) malloc(buflen), *p = buf, *end = buf+buflen; char *buf = (char *) malloc(buflen), *p = buf, *end = buf+buflen;
int first = 1; int first = 1;
(void) url_path; // unused
p += snprintf(p, end-p, p += snprintf(p, end-p,
"{ \"now\" : %d,\n" "{ \"now\" : %d,\n"
" \"messages\" : %u,\n" " \"messages\" : %u,\n"
@ -732,10 +734,12 @@ char *generateAircraftJson(int *len) {
// //
// Return a description of the receiver in json. // Return a description of the receiver in json.
// //
char *generateReceiverJson(int *len) char *generateReceiverJson(const char *url_path, int *len)
{ {
char *buf = (char *) malloc(1024), *p = buf; char *buf = (char *) malloc(1024), *p = buf;
(void)url_path; // unused
p += sprintf(p, "{ " \ p += sprintf(p, "{ " \
"\"version\" : \"%s\", " "\"version\" : \"%s\", "
"\"refresh\" : %d", "\"refresh\" : %d",
@ -762,16 +766,20 @@ char *generateReceiverJson(int *len)
} }
// Write JSON to file // Write JSON to file
void writeJsonToFile(const char *path, char * (*generator) (int*)) void writeJsonToFile(const char *file, char * (*generator) (const char *,int*))
{ {
#ifndef _WIN32 #ifndef _WIN32
char pathbuf[PATH_MAX];
char tmppath[PATH_MAX]; char tmppath[PATH_MAX];
int fd; int fd;
int len = 0; int len = 0;
mode_t mask; mode_t mask;
char *content; char *content;
snprintf(tmppath, PATH_MAX, "%s.XXXXXX", path); if (!Modes.json_dir)
return;
snprintf(tmppath, PATH_MAX, "%s/%s.XXXXXX", Modes.json_dir, file);
tmppath[PATH_MAX-1] = 0; tmppath[PATH_MAX-1] = 0;
fd = mkstemp(tmppath); fd = mkstemp(tmppath);
if (fd < 0) if (fd < 0)
@ -781,7 +789,9 @@ void writeJsonToFile(const char *path, char * (*generator) (int*))
umask(mask); umask(mask);
fchmod(fd, 0644 & ~mask); fchmod(fd, 0644 & ~mask);
content = generator(&len); snprintf(pathbuf, PATH_MAX, "/data/%s", file);
pathbuf[PATH_MAX-1] = 0;
content = generator(pathbuf, &len);
if (write(fd, content, len) != len) if (write(fd, content, len) != len)
goto error_1; goto error_1;
@ -789,7 +799,9 @@ void writeJsonToFile(const char *path, char * (*generator) (int*))
if (close(fd) < 0) if (close(fd) < 0)
goto error_2; goto error_2;
rename(tmppath, path); snprintf(pathbuf, PATH_MAX, "%s/%s", Modes.json_dir, file);
pathbuf[PATH_MAX-1] = 0;
rename(tmppath, pathbuf);
free(content); free(content);
return; return;
@ -814,7 +826,7 @@ void writeJsonToFile(const char *path, char * (*generator) (int*))
static struct { static struct {
char *path; char *path;
char * (*handler)(int*); char * (*handler)(const char*,int*);
char *content_type; char *content_type;
} url_handlers[] = { } url_handlers[] = {
{ "/data/aircraft.json", generateAircraftJson, MODES_CONTENT_TYPE_JSON }, { "/data/aircraft.json", generateAircraftJson, MODES_CONTENT_TYPE_JSON },
@ -877,7 +889,10 @@ int handleHTTPRequest(struct client *c, char *p) {
for (i = 0; url_handlers[i].path; ++i) { for (i = 0; url_handlers[i].path; ++i) {
if (!strcmp(url, url_handlers[i].path)) { if (!strcmp(url, url_handlers[i].path)) {
content_type = url_handlers[i].content_type; content_type = url_handlers[i].content_type;
content = url_handlers[i].handler(&clen); content = url_handlers[i].handler(url, &clen);
if (!content)
continue;
statuscode = 200; statuscode = 200;
statusmsg = "OK"; statusmsg = "OK";
if (Modes.debug & MODES_DEBUG_NET) { if (Modes.debug & MODES_DEBUG_NET) {