123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471 |
- /****************************************************************************
- NAME
- ais_json.c - deserialize AIS JSON
- DESCRIPTION
- This module uses the generic JSON parser to get data from AIS
- representations to libgps structures.
- This file is Copyright (c)2010-2018 by the GPSD project
- SPDX-License-Identifier: BSD-2-clause
- ***************************************************************************/
- #include "gpsd_config.h" /* must be before all includes */
- #include <stdio.h>
- #include <string.h>
- #include <stdbool.h>
- #include <stdlib.h>
- #include <stddef.h>
- #include <time.h>
- #include "gps.h"
- #include "json.h"
- #ifdef SOCKET_EXPORT_ENABLE
- #include "libgps.h"
- /* kluge because we don't want to include gpsd.h here */
- extern int gpsd_hexpack(const char *, char *, size_t);
- static void lenhex_unpack(const char *from,
- size_t * plen, char *to, size_t maxlen)
- {
- char *colon = strchr(from, ':');
- *plen = (size_t) atoi(from);
- if (colon != NULL)
- (void)gpsd_hexpack(colon + 1, to, maxlen);
- }
- int json_ais_read(const char *buf,
- char *path, size_t pathlen, struct ais_t *ais,
- const char **endptr)
- {
- /* collected but not actually used yet */
- bool scaled;
- #define AIS_HEADER \
- {"class", t_check, .dflt.check = "AIS"}, \
- {"type", t_uinteger, .addr.uinteger = &ais->type}, \
- {"device", t_string, .addr.string = path, \
- .len = pathlen}, \
- {"repeat", t_uinteger, .addr.uinteger = &ais->repeat}, \
- {"scaled", t_boolean, .addr.boolean = &scaled, \
- .dflt.boolean = false}, \
- {"mmsi", t_uinteger, .addr.uinteger = &ais->mmsi},
- #define AIS_TYPE6 \
- {"seqno", t_uinteger, .addr.uinteger = &ais->type6.seqno,\
- .dflt.uinteger = 0},\
- {"dest_mmsi", t_uinteger, .addr.uinteger = &ais->type6.dest_mmsi,\
- .dflt.uinteger = 0},\
- {"retransmit", t_boolean, .addr.boolean = &ais->type6.retransmit,\
- .dflt.boolean = false},\
- {"dac", t_uinteger, .addr.uinteger = &ais->type6.dac,\
- .dflt.uinteger = 0},\
- {"fid", t_uinteger, .addr.uinteger = &ais->type6.fid,\
- .dflt.uinteger = 0},
- #define AIS_TYPE8 \
- {"dac", t_uinteger, .addr.uinteger = &ais->type8.dac,\
- .dflt.uinteger = 0},\
- {"fid", t_uinteger, .addr.uinteger = &ais->type8.fid,\
- .dflt.uinteger = 0},
- int status;
- #include "ais_json.i" /* JSON parser template structures */
- #undef AIS_HEADER
- memset(ais, '\0', sizeof(struct ais_t));
- if (strstr(buf, "\"type\":1,") != NULL
- || strstr(buf, "\"type\":2,") != NULL
- || strstr(buf, "\"type\":3,") != NULL) {
- status = json_read_object(buf, json_ais1, endptr);
- } else if (strstr(buf, "\"type\":4,") != NULL
- || strstr(buf, "\"type\":11,") != NULL) {
- status = json_read_object(buf, json_ais4, endptr);
- if (status == 0) {
- ais->type4.year = AIS_YEAR_NOT_AVAILABLE;
- ais->type4.month = AIS_MONTH_NOT_AVAILABLE;
- ais->type4.day = AIS_DAY_NOT_AVAILABLE;
- ais->type4.hour = AIS_HOUR_NOT_AVAILABLE;
- ais->type4.minute = AIS_MINUTE_NOT_AVAILABLE;
- ais->type4.second = AIS_SECOND_NOT_AVAILABLE;
- // We use %09u for the date to allow for dodgy years (>9999) to go through
- // cppcheck-suppress uninitvar
- (void)sscanf(timestamp, "%09u-%02u-%02uT%02u:%02u:%02uZ",
- &ais->type4.year,
- &ais->type4.month,
- &ais->type4.day,
- &ais->type4.hour,
- &ais->type4.minute,
- &ais->type4.second);
- }
- } else if (strstr(buf, "\"type\":5,") != NULL) {
- status = json_read_object(buf, json_ais5, endptr);
- if (status == 0) {
- ais->type5.month = AIS_MONTH_NOT_AVAILABLE;
- ais->type5.day = AIS_DAY_NOT_AVAILABLE;
- ais->type5.hour = AIS_HOUR_NOT_AVAILABLE;
- ais->type5.minute = AIS_MINUTE_NOT_AVAILABLE;
- // cppcheck-suppress uninitvar
- (void)sscanf(eta, "%02u-%02uT%02u:%02uZ",
- &ais->type5.month,
- &ais->type5.day,
- &ais->type5.hour,
- &ais->type5.minute);
- }
- } else if (strstr(buf, "\"type\":6,") != NULL) {
- bool structured = false;
- if (strstr(buf, "\"dac\":1,") != NULL) {
- if (strstr(buf, "\"fid\":12,") != NULL) {
- status = json_read_object(buf, json_ais6_fid12, endptr);
- if (status == 0) {
- ais->type6.dac1fid12.lmonth = AIS_MONTH_NOT_AVAILABLE;
- ais->type6.dac1fid12.lday = AIS_DAY_NOT_AVAILABLE;
- ais->type6.dac1fid12.lhour = AIS_HOUR_NOT_AVAILABLE;
- ais->type6.dac1fid12.lminute = AIS_MINUTE_NOT_AVAILABLE;
- // cppcheck-suppress uninitvar
- (void)sscanf(departure, "%02u-%02uT%02u:%02uZ",
- &ais->type6.dac1fid12.lmonth,
- &ais->type6.dac1fid12.lday,
- &ais->type6.dac1fid12.lhour,
- &ais->type6.dac1fid12.lminute);
- ais->type6.dac1fid12.nmonth = AIS_MONTH_NOT_AVAILABLE;
- ais->type6.dac1fid12.nday = AIS_DAY_NOT_AVAILABLE;
- ais->type6.dac1fid12.nhour = AIS_HOUR_NOT_AVAILABLE;
- ais->type6.dac1fid12.nminute = AIS_MINUTE_NOT_AVAILABLE;
- // cppcheck-suppress uninitvar
- (void)sscanf(eta, "%02u-%02uT%02u:%02uZ",
- &ais->type6.dac1fid12.nmonth,
- &ais->type6.dac1fid12.nday,
- &ais->type6.dac1fid12.nhour,
- &ais->type6.dac1fid12.nminute);
- }
- structured = true;
- }
- else if (strstr(buf, "\"fid\":15,") != NULL) {
- status = json_read_object(buf, json_ais6_fid15, endptr);
- structured = true;
- }
- else if (strstr(buf, "\"fid\":16,") != NULL) {
- status = json_read_object(buf, json_ais6_fid16, endptr);
- structured = true;
- }
- else if (strstr(buf, "\"fid\":18,") != NULL) {
- status = json_read_object(buf, json_ais6_fid18, endptr);
- if (status == 0) {
- ais->type6.dac1fid18.day = AIS_DAY_NOT_AVAILABLE;
- ais->type6.dac1fid18.hour = AIS_HOUR_NOT_AVAILABLE;
- ais->type6.dac1fid18.minute = AIS_MINUTE_NOT_AVAILABLE;
- // cppcheck-suppress uninitvar
- (void)sscanf(arrival, "%02u-%02uT%02u:%02uZ",
- &ais->type6.dac1fid18.month,
- &ais->type6.dac1fid18.day,
- &ais->type6.dac1fid18.hour,
- &ais->type6.dac1fid18.minute);
- }
- structured = true;
- }
- else if (strstr(buf, "\"fid\":20,") != NULL) {
- status = json_read_object(buf, json_ais6_fid20, endptr);
- if (status == 0) {
- ais->type6.dac1fid20.month = AIS_MONTH_NOT_AVAILABLE;
- ais->type6.dac1fid20.day = AIS_DAY_NOT_AVAILABLE;
- ais->type6.dac1fid20.hour = AIS_HOUR_NOT_AVAILABLE;
- ais->type6.dac1fid20.minute = AIS_MINUTE_NOT_AVAILABLE;
- // cppcheck-suppress uninitvar
- (void)sscanf(arrival, "%02u-%02uT%02u:%02uZ",
- &ais->type6.dac1fid20.month,
- &ais->type6.dac1fid20.day,
- &ais->type6.dac1fid20.hour,
- &ais->type6.dac1fid20.minute);
- }
- structured = true;
- }
- else if (strstr(buf, "\"fid\":25,") != NULL) {
- status = json_read_object(buf, json_ais6_fid25, endptr);
- structured = true;
- }
- else if (strstr(buf, "\"fid\":28,") != NULL) {
- status = json_read_object(buf, json_ais6_fid28, endptr);
- if (status == 0) {
- ais->type6.dac1fid28.month = AIS_MONTH_NOT_AVAILABLE;
- ais->type6.dac1fid28.day = AIS_DAY_NOT_AVAILABLE;
- ais->type6.dac1fid28.hour = AIS_HOUR_NOT_AVAILABLE;
- ais->type6.dac1fid28.minute = AIS_MINUTE_NOT_AVAILABLE;
- // cppcheck-suppress uninitvar
- (void)sscanf(start, "%02u-%02uT%02u:%02uZ",
- &ais->type6.dac1fid28.month,
- &ais->type6.dac1fid28.day,
- &ais->type6.dac1fid28.hour,
- &ais->type6.dac1fid28.minute);
- }
- structured = true;
- }
- else if (strstr(buf, "\"fid\":30,") != NULL) {
- status = json_read_object(buf, json_ais6_fid30, endptr);
- structured = true;
- }
- else if (strstr(buf, "\"fid\":32,") != NULL || strstr(buf, "\"fid\":14,") != NULL) {
- status = json_read_object(buf, json_ais6_fid32, endptr);
- structured = true;
- }
- }
- else if (strstr(buf, "\"dac\":235,") != NULL || strstr(buf, "\"dac\":250,") != NULL) {
- if (strstr(buf, "\"fid\":10,") != NULL) {
- status = json_read_object(buf, json_ais6_fid10, endptr);
- structured = true;
- }
- }
- else if (strstr(buf, "\"dac\":200,") != NULL) {
- if (strstr(buf, "\"fid\":21,") != NULL) {
- status = json_read_object(buf, json_ais6_fid21, endptr);
- structured = true;
- if (status == 0) {
- ais->type6.dac200fid21.month = AIS_MONTH_NOT_AVAILABLE;
- ais->type6.dac200fid21.day = AIS_DAY_NOT_AVAILABLE;
- ais->type6.dac200fid21.hour = AIS_HOUR_NOT_AVAILABLE;
- ais->type6.dac200fid21.minute = AIS_MINUTE_NOT_AVAILABLE;
- // cppcheck-suppress uninitvar
- (void)sscanf(eta, "%02u-%02uT%02u:%02u",
- &ais->type6.dac200fid21.month,
- &ais->type6.dac200fid21.day,
- &ais->type6.dac200fid21.hour,
- &ais->type6.dac200fid21.minute);
- }
- }
- else if (strstr(buf, "\"fid\":22,") != NULL) {
- status = json_read_object(buf, json_ais6_fid22, endptr);
- structured = true;
- if (status == 0) {
- ais->type6.dac200fid22.month = AIS_MONTH_NOT_AVAILABLE;
- ais->type6.dac200fid22.day = AIS_DAY_NOT_AVAILABLE;
- ais->type6.dac200fid22.hour = AIS_HOUR_NOT_AVAILABLE;
- ais->type6.dac200fid22.minute = AIS_MINUTE_NOT_AVAILABLE;
- // cppcheck-suppress uninitvar
- (void)sscanf(rta, "%02u-%02uT%02u:%02u",
- &ais->type6.dac200fid22.month,
- &ais->type6.dac200fid22.day,
- &ais->type6.dac200fid22.hour,
- &ais->type6.dac200fid22.minute);
- }
- }
- else if (strstr(buf, "\"fid\":55,") != NULL) {
- status = json_read_object(buf, json_ais6_fid55, endptr);
- structured = true;
- }
- }
- if (!structured) {
- status = json_read_object(buf, json_ais6, endptr);
- if (status == 0)
- lenhex_unpack(data, &ais->type6.bitcount,
- ais->type6.bitdata, sizeof(ais->type6.bitdata));
- }
- ais->type6.structured = structured;
- } else if (strstr(buf, "\"type\":7,") != NULL
- || strstr(buf, "\"type\":13,") != NULL) {
- status = json_read_object(buf, json_ais7, endptr);
- } else if (strstr(buf, "\"type\":8,") != NULL) {
- bool structured = false;
- if (strstr(buf, "\"dac\":1,") != NULL) {
- if (strstr(buf, "\"fid\":11,") != NULL) {
- status = json_read_object(buf, json_ais8_fid11, endptr);
- if (status == 0) {
- ais->type8.dac1fid11.day = AIS_DAY_NOT_AVAILABLE;
- ais->type8.dac1fid11.hour = AIS_HOUR_NOT_AVAILABLE;
- ais->type8.dac1fid11.minute = AIS_MINUTE_NOT_AVAILABLE;
- // cppcheck-suppress uninitvar
- (void)sscanf(timestamp, "%02uT%02u:%02uZ",
- &ais->type8.dac1fid11.day,
- &ais->type8.dac1fid11.hour,
- &ais->type8.dac1fid11.minute);
- }
- structured = true;
- }
- else if (strstr(buf, "\"fid\":13,") != NULL) {
- status = json_read_object(buf, json_ais8_fid13, endptr);
- if (status == 0) {
- ais->type8.dac1fid13.fmonth = AIS_MONTH_NOT_AVAILABLE;
- ais->type8.dac1fid13.fday = AIS_DAY_NOT_AVAILABLE;
- ais->type8.dac1fid13.fhour = AIS_HOUR_NOT_AVAILABLE;
- ais->type8.dac1fid13.fminute = AIS_MINUTE_NOT_AVAILABLE;
- // cppcheck-suppress uninitvar
- (void)sscanf(departure, "%02u-%02uT%02u:%02uZ",
- &ais->type8.dac1fid13.fmonth,
- &ais->type8.dac1fid13.fday,
- &ais->type8.dac1fid13.fhour,
- &ais->type8.dac1fid13.fminute);
- ais->type8.dac1fid13.tmonth = AIS_MONTH_NOT_AVAILABLE;
- ais->type8.dac1fid13.tday = AIS_DAY_NOT_AVAILABLE;
- ais->type8.dac1fid13.thour = AIS_HOUR_NOT_AVAILABLE;
- ais->type8.dac1fid13.tminute = AIS_MINUTE_NOT_AVAILABLE;
- // cppcheck-suppress uninitvar
- (void)sscanf(eta, "%02u-%02uT%02u:%02uZ",
- &ais->type8.dac1fid13.tmonth,
- &ais->type8.dac1fid13.tday,
- &ais->type8.dac1fid13.thour,
- &ais->type8.dac1fid13.tminute);
- }
- structured = true;
- }
- else if (strstr(buf, "\"fid\":15,") != NULL) {
- status = json_read_object(buf, json_ais8_fid15, endptr);
- structured = true;
- }
- else if (strstr(buf, "\"fid\":16,") != NULL) {
- status = json_read_object(buf, json_ais8_fid16, endptr);
- if (status == 0) {
- structured = true;
- }
- }
- else if (strstr(buf, "\"fid\":17,") != NULL) {
- status = json_read_object(buf, json_ais8_fid17, endptr);
- structured = true;
- }
- else if (strstr(buf, "\"fid\":19,") != NULL) {
- status = json_read_object(buf, json_ais8_fid19, endptr);
- structured = true;
- }
- else if (strstr(buf, "\"fid\":23,") != NULL) {
- status = json_read_object(buf, json_ais8_fid23, endptr);
- ais->type8.dac200fid23.start_year = AIS_YEAR_NOT_AVAILABLE;
- ais->type8.dac200fid23.start_month = AIS_MONTH_NOT_AVAILABLE;
- ais->type8.dac200fid23.start_day = AIS_DAY_NOT_AVAILABLE;
- ais->type8.dac200fid23.start_hour = AIS_HOUR_NOT_AVAILABLE;
- ais->type8.dac200fid23.start_minute = AIS_MINUTE_NOT_AVAILABLE;
- ais->type8.dac200fid23.end_year = AIS_YEAR_NOT_AVAILABLE;
- ais->type8.dac200fid23.end_month = AIS_MONTH_NOT_AVAILABLE;
- ais->type8.dac200fid23.end_day = AIS_DAY_NOT_AVAILABLE;
- ais->type8.dac200fid23.end_hour = AIS_HOUR_NOT_AVAILABLE;
- ais->type8.dac200fid23.end_minute = AIS_MINUTE_NOT_AVAILABLE;
- // cppcheck-suppress uninitvar
- (void)sscanf(start, "%09u-%02u-%02uT%02u:%02u",
- &ais->type8.dac200fid23.start_year,
- &ais->type8.dac200fid23.start_month,
- &ais->type8.dac200fid23.start_day,
- &ais->type8.dac200fid23.start_hour,
- &ais->type8.dac200fid23.start_minute);
- // cppcheck-suppress uninitvar
- (void)sscanf(end, "%09u-%02u-%02uT%02u:%02u",
- &ais->type8.dac200fid23.end_year,
- &ais->type8.dac200fid23.end_month,
- &ais->type8.dac200fid23.end_day,
- &ais->type8.dac200fid23.end_hour,
- &ais->type8.dac200fid23.end_minute);
- structured = true;
- }
- else if (strstr(buf, "\"fid\":24,") != NULL) {
- status = json_read_object(buf, json_ais8_fid24, endptr);
- structured = true;
- }
- else if (strstr(buf, "\"fid\":27,") != NULL) {
- status = json_read_object(buf, json_ais8_fid27, endptr);
- if (status == 0) {
- ais->type8.dac1fid27.month = AIS_MONTH_NOT_AVAILABLE;
- ais->type8.dac1fid27.day = AIS_DAY_NOT_AVAILABLE;
- ais->type8.dac1fid27.hour = AIS_HOUR_NOT_AVAILABLE;
- ais->type8.dac1fid27.minute = AIS_MINUTE_NOT_AVAILABLE;
- // cppcheck-suppress uninitvar
- (void)sscanf(start, "%02u-%02uT%02u:%02uZ",
- &ais->type8.dac1fid27.month,
- &ais->type8.dac1fid27.day,
- &ais->type8.dac1fid27.hour,
- &ais->type8.dac1fid27.minute);
- }
- structured = true;
- }
- else if (strstr(buf, "\"fid\":29,") != NULL) {
- status = json_read_object(buf, json_ais8_fid29, endptr);
- structured = true;
- }
- else if (strstr(buf, "\"fid\":31,") != NULL) {
- status = json_read_object(buf, json_ais8_fid31, endptr);
- if (status == 0) {
- ais->type8.dac1fid31.day = AIS_DAY_NOT_AVAILABLE;
- ais->type8.dac1fid31.hour = AIS_HOUR_NOT_AVAILABLE;
- ais->type8.dac1fid31.minute = AIS_MINUTE_NOT_AVAILABLE;
- // cppcheck-suppress uninitvar
- (void)sscanf(timestamp, "%02uT%02u:%02uZ",
- &ais->type8.dac1fid31.day,
- &ais->type8.dac1fid31.hour,
- &ais->type8.dac1fid31.minute);
- }
- structured = true;
- }
- }
- else if (strstr(buf, "\"dac\":200,") != NULL && strstr(buf,"data")==NULL) {
- if (strstr(buf, "\"fid\":10,") != NULL) {
- status = json_read_object(buf, json_ais8_fid10, endptr);
- structured = true;
- }
- if (strstr(buf, "\"fid\":40,") != NULL) {
- status = json_read_object(buf, json_ais8_fid40, endptr);
- structured = true;
- }
- }
- if (!structured) {
- status = json_read_object(buf, json_ais8, endptr);
- if (status == 0)
- lenhex_unpack(data, &ais->type8.bitcount,
- ais->type8.bitdata, sizeof(ais->type8.bitdata));
- }
- ais->type8.structured = structured;
- } else if (strstr(buf, "\"type\":9,") != NULL) {
- status = json_read_object(buf, json_ais9, endptr);
- } else if (strstr(buf, "\"type\":10,") != NULL) {
- status = json_read_object(buf, json_ais10, endptr);
- } else if (strstr(buf, "\"type\":12,") != NULL) {
- status = json_read_object(buf, json_ais12, endptr);
- } else if (strstr(buf, "\"type\":14,") != NULL) {
- status = json_read_object(buf, json_ais14, endptr);
- } else if (strstr(buf, "\"type\":15,") != NULL) {
- status = json_read_object(buf, json_ais15, endptr);
- } else if (strstr(buf, "\"type\":16,") != NULL) {
- status = json_read_object(buf, json_ais16, endptr);
- } else if (strstr(buf, "\"type\":17,") != NULL) {
- status = json_read_object(buf, json_ais17, endptr);
- if (status == 0)
- lenhex_unpack(data, &ais->type17.bitcount,
- ais->type17.bitdata, sizeof(ais->type17.bitdata));
- } else if (strstr(buf, "\"type\":18,") != NULL) {
- status = json_read_object(buf, json_ais18, endptr);
- } else if (strstr(buf, "\"type\":19,") != NULL) {
- status = json_read_object(buf, json_ais19, endptr);
- } else if (strstr(buf, "\"type\":20,") != NULL) {
- status = json_read_object(buf, json_ais20, endptr);
- } else if (strstr(buf, "\"type\":21,") != NULL) {
- status = json_read_object(buf, json_ais21, endptr);
- } else if (strstr(buf, "\"type\":22,") != NULL) {
- status = json_read_object(buf, json_ais22, endptr);
- } else if (strstr(buf, "\"type\":23,") != NULL) {
- status = json_read_object(buf, json_ais23, endptr);
- } else if (strstr(buf, "\"type\":24,") != NULL) {
- status = json_read_object(buf, json_ais24, endptr);
- } else if (strstr(buf, "\"type\":25,") != NULL) {
- status = json_read_object(buf, json_ais25, endptr);
- if (status == 0)
- lenhex_unpack(data, &ais->type25.bitcount,
- ais->type25.bitdata, sizeof(ais->type25.bitdata));
- } else if (strstr(buf, "\"type\":26,") != NULL) {
- status = json_read_object(buf, json_ais26, endptr);
- if (status == 0)
- lenhex_unpack(data, &ais->type26.bitcount,
- ais->type26.bitdata, sizeof(ais->type26.bitdata));
- } else if (strstr(buf, "\"type\":27,") != NULL) {
- status = json_read_object(buf, json_ais27, endptr);
- } else {
- if (endptr != NULL)
- *endptr = NULL;
- return JSON_ERR_MISC;
- }
- return status;
- }
- #endif /* SOCKET_EXPORT_ENABLE */
- /* ais_json.c ends here */
|