diff --git a/dump1090.c b/dump1090.c index 7b7ba4b..f90cf98 100644 --- a/dump1090.c +++ b/dump1090.c @@ -145,13 +145,12 @@ void modesInitConfig(void) { Modes.ppm_error = MODES_DEFAULT_PPM; Modes.check_crc = 1; Modes.net_heartbeat_interval = MODES_NET_HEARTBEAT_INTERVAL; - Modes.net_output_sbs_port = MODES_NET_OUTPUT_SBS_PORT; - Modes.net_output_raw_port = MODES_NET_OUTPUT_RAW_PORT; - Modes.net_input_raw_port = MODES_NET_INPUT_RAW_PORT; - Modes.net_output_beast_port = MODES_NET_OUTPUT_BEAST_PORT; - Modes.net_input_beast_port = MODES_NET_INPUT_BEAST_PORT; - Modes.net_http_port = MODES_NET_HTTP_PORT; - Modes.net_fatsv_port = MODES_NET_OUTPUT_FA_TSV_PORT; + Modes.net_output_raw_ports = strdup("30001"); + Modes.net_input_raw_ports = strdup("30002"); + Modes.net_output_sbs_ports = strdup("30003"); + Modes.net_input_beast_ports = strdup("30004,30104"); + Modes.net_output_beast_ports = strdup("30005"); + Modes.net_http_ports = strdup("8080"); Modes.interactive_rows = getTermRows(); Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL; Modes.html_dir = HTMLPATH; @@ -682,13 +681,12 @@ void showHelp(void) { "--modeac Enable decoding of SSR Modes 3/A & 3/C\n" "--net-only Enable just networking, no RTL device or file used\n" "--net-bind-address IP address to bind to (default: Any; Use 127.0.0.1 for private)\n" -"--net-http-port HTTP server port (default: 8080)\n" -"--net-ri-port TCP raw input listen port (default: 30001)\n" -"--net-ro-port TCP raw output listen port (default: 30002)\n" -"--net-sbs-port TCP BaseStation output listen port (default: 30003)\n" -"--net-bi-port TCP Beast input listen port (default: 30004)\n" -"--net-bo-port TCP Beast output listen port (default: 30005)\n" -"--net-fatsv-port FlightAware TSV output port (default: 10001)\n" +"--net-http-port HTTP server ports (default: 8080)\n" +"--net-ri-port TCP raw input listen ports (default: 30001)\n" +"--net-ro-port TCP raw output listen ports (default: 30002)\n" +"--net-sbs-port TCP BaseStation output listen ports (default: 30003)\n" +"--net-bi-port TCP Beast input listen ports (default: 30004,30104)\n" +"--net-bo-port TCP Beast output listen ports (default: 30005)\n" "--net-ro-size TCP output minimum size (default: 0)\n" "--net-ro-interval TCP output memory flush rate in seconds (default: 0)\n" "--net-heartbeat TCP heartbeat rate in seconds (default: 60 sec; 0 to disable)\n" @@ -825,8 +823,8 @@ void backgroundTasks(void) { next_json = now + Modes.json_interval; } - if ((Modes.json_dir || Modes.net_http_port) && now >= next_history) { - int rewrite_receiver_json = (Modes.json_aircraft_history[HISTORY_SIZE-1].content == NULL); + if (now >= next_history) { + int rewrite_receiver_json = (Modes.json_dir && Modes.json_aircraft_history[HISTORY_SIZE-1].content == NULL); free(Modes.json_aircraft_history[Modes.json_aircraft_history_next].content); // might be NULL, that's OK. Modes.json_aircraft_history[Modes.json_aircraft_history_next].content = @@ -968,7 +966,7 @@ int main(int argc, char **argv) { } else if (!strcmp(argv[j],"--modeac")) { Modes.mode_ac = 1; } else if (!strcmp(argv[j],"--net-beast")) { - Modes.beast = 1; + fprintf(stderr, "--net-beast ignored, use --net-bo-port to control where Beast output is generated\n"); } else if (!strcmp(argv[j],"--net-only")) { Modes.net = 1; Modes.net_only = 1; @@ -981,24 +979,26 @@ int main(int argc, char **argv) { } else if (!strcmp(argv[j],"--net-ro-interval") && more) { Modes.net_output_flush_interval = (uint64_t)(1000 * atof(argv[++j])); } else if (!strcmp(argv[j],"--net-ro-port") && more) { - if (Modes.beast) // Required for legacy backward compatibility - {Modes.net_output_beast_port = atoi(argv[++j]);;} - else - {Modes.net_output_raw_port = atoi(argv[++j]);} + free(Modes.net_output_raw_ports); + Modes.net_output_raw_ports = strdup(argv[++j]); } else if (!strcmp(argv[j],"--net-ri-port") && more) { - Modes.net_input_raw_port = atoi(argv[++j]); + free(Modes.net_input_raw_ports); + Modes.net_input_raw_ports = strdup(argv[++j]); } else if (!strcmp(argv[j],"--net-bo-port") && more) { - Modes.net_output_beast_port = atoi(argv[++j]); + free(Modes.net_output_beast_ports); + Modes.net_output_beast_ports = strdup(argv[++j]); } else if (!strcmp(argv[j],"--net-bi-port") && more) { - Modes.net_input_beast_port = atoi(argv[++j]); + free(Modes.net_input_beast_ports); + Modes.net_input_beast_ports = strdup(argv[++j]); } else if (!strcmp(argv[j],"--net-bind-address") && more) { + free(Modes.net_bind_address); Modes.net_bind_address = strdup(argv[++j]); } else if (!strcmp(argv[j],"--net-http-port") && more) { - Modes.net_http_port = atoi(argv[++j]); - } else if (!strcmp(argv[j],"--net-fatsv-port") && more) { - Modes.net_fatsv_port = atoi(argv[++j]); + free(Modes.net_http_ports); + Modes.net_http_ports = strdup(argv[++j]); } else if (!strcmp(argv[j],"--net-sbs-port") && more) { - Modes.net_output_sbs_port = atoi(argv[++j]); + free(Modes.net_output_sbs_ports); + Modes.net_output_sbs_ports = strdup(argv[++j]); } else if (!strcmp(argv[j],"--net-buffer") && more) { Modes.net_sndbuf_size = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-verbatim")) { diff --git a/dump1090.h b/dump1090.h index 7ab45d1..f35d775 100644 --- a/dump1090.h +++ b/dump1090.h @@ -191,14 +191,6 @@ typedef struct rtlsdr_dev rtlsdr_dev_t; #define MODES_NET_HEARTBEAT_INTERVAL 60000 // milliseconds -#define MODES_NET_SERVICES_NUM 7 -#define MODES_NET_INPUT_RAW_PORT 30001 -#define MODES_NET_OUTPUT_RAW_PORT 30002 -#define MODES_NET_OUTPUT_SBS_PORT 30003 -#define MODES_NET_INPUT_BEAST_PORT 30004 -#define MODES_NET_OUTPUT_BEAST_PORT 30005 -#define MODES_NET_HTTP_PORT 8080 -#define MODES_NET_OUTPUT_FA_TSV_PORT 10001 #define MODES_CLIENT_BUF_SIZE 1024 #define MODES_NET_SNDBUF_SIZE (1024*64) #define MODES_NET_SNDBUF_MAX (7) @@ -296,22 +288,20 @@ struct { // Internal state int nfix_crc; // Number of crc bit error(s) to correct int check_crc; // Only display messages with good CRC int raw; // Raw output format - int beast; // Beast binary format output int mode_ac; // Enable decoding of SSR Modes A & C int debug; // Debugging mode int net; // Enable networking int net_only; // Enable just networking uint64_t net_heartbeat_interval; // TCP heartbeat interval (milliseconds) - int net_output_sbs_port; // SBS output TCP port int net_output_flush_size; // Minimum Size of output data uint64_t net_output_flush_interval; // Maximum interval (in milliseconds) between outputwrites - int net_output_raw_port; // Raw output TCP port - int net_input_raw_port; // Raw input TCP port - int net_output_beast_port; // Beast output TCP port - int net_input_beast_port; // Beast input TCP port - char *net_bind_address; // Bind address - int net_http_port; // HTTP port - int net_fatsv_port; // FlightAware TSV port + char *net_output_raw_ports; // List of raw output TCP ports + char *net_input_raw_ports; // List of raw input TCP ports + char *net_output_sbs_ports; // List of SBS output TCP ports + char *net_input_beast_ports; // List of Beast input TCP ports + char *net_output_beast_ports; // List of Beast output TCP ports + char *net_http_ports; // List of HTTP ports + char *net_bind_address; // Bind address int net_sndbuf_size; // TCP output buffer size (64Kb * 2^n) int net_verbatim; // if true, send the original message, not the CRC-corrected one int forward_mlat; // allow forwarding of mlat messages to output ports diff --git a/faup1090.c b/faup1090.c index ae30e5e..4503d08 100644 --- a/faup1090.c +++ b/faup1090.c @@ -139,7 +139,7 @@ int main(int argc, char **argv) { int j; int stdout_option = 0; char *bo_connect_ipaddr = "127.0.0.1"; - int bo_connect_port = MODES_NET_OUTPUT_BEAST_PORT; + int bo_connect_port = 30005; struct client *c; struct net_service *beast_input, *fatsv_output; diff --git a/mode_s.c b/mode_s.c index b487a01..c2493d1 100644 --- a/mode_s.c +++ b/mode_s.c @@ -714,32 +714,36 @@ static void decodeExtendedSquitter(struct modesMessage *mm) // Check CF on DF18 to work out the format of the ES and whether we need to look for an IMF bit if (mm->msgtype == 18) { - /* we just globally tag any DF18 as TIS-B, - * which is not strictly true but close enough - */ - mm->bFlags |= MODES_ACFLAGS_FROM_TISB; - switch (mm->cf) { case 0: // ADS-B ES/NT devices that report the ICAO 24-bit address in the AA field break; case 1: // Reserved for ADS-B for ES/NT devices that use other addressing techniques in the AA field - case 5: // TIS-B messages that relay ADS-B Messages using anonymous 24-bit addresses (format not explicitly defined, but it seems to follow DF17) mm->addr |= MODES_NON_ICAO_ADDRESS; break; case 2: // Fine TIS-B message (formats are close enough to DF17 for our purposes) - case 6: // ADS-B rebroadcast using the same type codes and message formats as defined for DF = 17 ADS-B messages + mm->bFlags |= MODES_ACFLAGS_FROM_TISB; check_imf = 1; break; case 3: // Coarse TIS-B airborne position and velocity. // TODO: decode me. // For now we only look at the IMF bit. + mm->bFlags |= MODES_ACFLAGS_FROM_TISB; if (msg[4] & 0x80) mm->addr |= MODES_NON_ICAO_ADDRESS; return; + case 5: // TIS-B messages that relay ADS-B Messages using anonymous 24-bit addresses (format not explicitly defined, but it seems to follow DF17) + mm->bFlags |= MODES_ACFLAGS_FROM_TISB; + mm->addr |= MODES_NON_ICAO_ADDRESS; + break; + + case 6: // ADS-B rebroadcast using the same type codes and message formats as defined for DF = 17 ADS-B messages + check_imf = 1; + break; + default: // All others, we don't know the format. mm->addr |= MODES_NON_ICAO_ADDRESS; // assume non-ICAO return; @@ -1035,9 +1039,9 @@ static void displayExtendedSquitter(struct modesMessage *mm) { } if (mm->bFlags & MODES_ACFLAGS_HAE_DELTA_VALID) { - printf(" HAE - Barometric : %d ft\n", mm->hae_delta); + printf(" HAE/Baro offset : %d ft\n", mm->hae_delta); } else { - printf(" HAE - Barometric : not valid\n"); + printf(" HAE/Baro offset : not valid\n"); } } else if (mm->metype >= 5 && mm->metype <= 22) { // Airborne position Baro printf(" F flag : %s\n", (mm->msg[6] & 0x04) ? "odd" : "even"); @@ -1200,12 +1204,12 @@ void displayModesMessage(struct modesMessage *mm) { } else if (mm->msgtype == 18) { // DF 18 printf("DF 18: Extended Squitter.\n"); printf(" Control Field : %d (%s)\n", mm->cf, cf_str[mm->cf]); - if ((mm->cf == 0) || (mm->cf == 1) || (mm->cf == 5) || (mm->cf == 6)) { - if (mm->cf == 1 || mm->cf == 5) { - printf(" Other Address : %06x\n", mm->addr); - } else { - printf(" ICAO Address : %06x\n", mm->addr); - } + if (mm->addr & MODES_NON_ICAO_ADDRESS) { + printf(" Other Address : %06x\n", mm->addr); + } else { + printf(" ICAO Address : %06x\n", mm->addr); + } + if ((mm->cf == 0) || (mm->cf == 1) || (mm->cf == 2) || (mm->cf == 5) || (mm->cf == 6)) { displayExtendedSquitter(mm); } diff --git a/net_io.c b/net_io.c index 3d12a6b..ab9d656 100644 --- a/net_io.c +++ b/net_io.c @@ -96,7 +96,7 @@ struct net_service *serviceInit(const char *descr, struct net_writer *writer, he Modes.services = service; service->descr = descr; - service->listen_fd = -1; + service->listener_count = 0; service->connections = 0; service->writer = writer; service->read_sep = sep; @@ -163,24 +163,57 @@ struct client *serviceConnect(struct net_service *service, char *addr, int port) // Set up the given service to listen on an address/port. // _exits_ on failure! -void serviceListen(struct net_service *service, char *bind_addr, int bind_port) +void serviceListen(struct net_service *service, char *bind_addr, char *bind_ports) { - int s; + int *fds = NULL; + int n = 0; + char *p, *end; - if (service->listen_fd >= 0) { + if (service->listener_count > 0) { fprintf(stderr, "Tried to set up the service %s twice!\n", service->descr); exit(1); } - s = anetTcpServer(Modes.aneterr, bind_port, bind_addr); - if (s == ANET_ERR) { - fprintf(stderr, "Error opening the listening port %d (%s): %s\n", - bind_port, service->descr, Modes.aneterr); - exit(1); + if (!bind_ports || !strcmp(bind_ports, "") || !strcmp(bind_ports, "0")) + return; + + p = bind_ports; + while (*p) { + int s; + unsigned long port = strtoul(p, &end, 10); + if (p == end) { + fprintf(stderr, + "Couldn't parse port list: %s\n" + " %*s^\n", + bind_ports, (int)(p - bind_ports), ""); + exit(1); + } + + s = anetTcpServer(Modes.aneterr, port, bind_addr); + if (s == ANET_ERR) { + fprintf(stderr, "Error opening the listening port %lu (%s): %s\n", + port, service->descr, Modes.aneterr); + exit(1); + } + + anetNonBlock(Modes.aneterr, s); + + fds = realloc(fds, (n+1) * sizeof(int)); + if (!fds) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + fds[n] = s; + ++n; + + p = end; + if (*p == ',') + ++p; } - anetNonBlock(Modes.aneterr, s); - service->listen_fd = s; + service->listener_count = n; + service->listener_fds = fds; } struct net_service *makeBeastInputService(void) @@ -201,41 +234,23 @@ void modesInitNet(void) { Modes.services = NULL; // set up listeners + s = serviceInit("Raw TCP output", &Modes.raw_out, send_raw_heartbeat, NULL, NULL); + serviceListen(s, Modes.net_bind_address, Modes.net_output_raw_ports); - if (Modes.net_output_raw_port) { - s = serviceInit("Raw TCP output", &Modes.raw_out, send_raw_heartbeat, NULL, NULL); - serviceListen(s, Modes.net_bind_address, Modes.net_output_raw_port); - } + s = serviceInit("Beast TCP output", &Modes.beast_out, send_beast_heartbeat, NULL, NULL); + serviceListen(s, Modes.net_bind_address, Modes.net_output_beast_ports); - if (Modes.net_output_beast_port) { - s = serviceInit("Beast TCP output", &Modes.beast_out, send_beast_heartbeat, NULL, NULL); - serviceListen(s, Modes.net_bind_address, Modes.net_output_beast_port); - } + s = serviceInit("Basestation TCP output", &Modes.sbs_out, send_sbs_heartbeat, NULL, NULL); + serviceListen(s, Modes.net_bind_address, Modes.net_output_sbs_ports); - if (Modes.net_output_sbs_port) { - s = serviceInit("Basestation TCP output", &Modes.sbs_out, send_sbs_heartbeat, NULL, NULL); - serviceListen(s, Modes.net_bind_address, Modes.net_output_sbs_port); - } + s = serviceInit("Raw TCP input", NULL, NULL, "\n", decodeHexMessage); + serviceListen(s, Modes.net_bind_address, Modes.net_input_raw_ports); - if (Modes.net_fatsv_port) { - s = makeFatsvOutputService(); - serviceListen(s, Modes.net_bind_address, Modes.net_fatsv_port); - } + s = makeBeastInputService(); + serviceListen(s, Modes.net_bind_address, Modes.net_input_beast_ports); - if (Modes.net_input_raw_port) { - s = serviceInit("Raw TCP input", NULL, NULL, "\n", decodeHexMessage); - serviceListen(s, Modes.net_bind_address, Modes.net_input_raw_port); - } - - if (Modes.net_input_beast_port) { - s = makeBeastInputService(); - serviceListen(s, Modes.net_bind_address, Modes.net_input_beast_port); - } - - if (Modes.net_http_port) { - s = serviceInit("HTTP server", NULL, NULL, "\r\n\r\n", handleHTTPRequest); - serviceListen(s, Modes.net_bind_address, Modes.net_http_port); - } + s = serviceInit("HTTP server", NULL, NULL, "\r\n\r\n", handleHTTPRequest); + serviceListen(s, Modes.net_bind_address, Modes.net_http_ports); } // //========================================================================= @@ -248,8 +263,9 @@ static struct client * modesAcceptClients(void) { struct net_service *s; for (s = Modes.services; s; s = s->next) { - if (s->listen_fd >= 0) { - while ((fd = anetTcpAccept(Modes.aneterr, s->listen_fd, NULL, &port)) >= 0) { + int i; + for (i = 0; i < s->listener_count; ++i) { + while ((fd = anetTcpAccept(Modes.aneterr, s->listener_fds[i], NULL, &port)) >= 0) { createSocketClient(s, fd); } } diff --git a/net_io.h b/net_io.h index 34632bc..4610ee6 100644 --- a/net_io.h +++ b/net_io.h @@ -33,7 +33,8 @@ typedef void (*heartbeat_fn)(struct net_service *); struct net_service { struct net_service* next; const char *descr; - int listen_fd; + int listener_count; // number of listeners + int *listener_fds; // listening FDs int connections; // number of active clients @@ -63,7 +64,7 @@ struct net_writer { struct net_service *serviceInit(const char *descr, struct net_writer *writer, heartbeat_fn hb_handler, const char *sep, read_fn read_handler); struct client *serviceConnect(struct net_service *service, char *addr, int port); -void serviceListen(struct net_service *service, char *bind_addr, int bind_port); +void serviceListen(struct net_service *service, char *bind_addr, char *bind_ports); struct client *createSocketClient(struct net_service *service, int fd); struct client *createGenericClient(struct net_service *service, int fd); diff --git a/stats.c b/stats.c index 68e7f5f..1b97043 100644 --- a/stats.c +++ b/stats.c @@ -155,7 +155,7 @@ void display_stats(struct stats *st) { printf("%u unique aircraft tracks\n", st->unique_aircraft); printf("%u aircraft tracks where only one message was seen\n", st->single_message_aircraft); - if (Modes.net && Modes.net_http_port) + if (Modes.net) printf("%d HTTP requests\n", st->http_requests); { diff --git a/view1090.c b/view1090.c index 63d6bca..432fc32 100644 --- a/view1090.c +++ b/view1090.c @@ -149,7 +149,7 @@ int main(int argc, char **argv) { struct client *c; struct net_service *s; char *bo_connect_ipaddr = "127.0.0.1"; - int bo_connect_port = MODES_NET_OUTPUT_BEAST_PORT; + int bo_connect_port = 30005; // Set sane defaults