// //========================================================================= // // This function is called a few times every second by main in order to // perform tasks we need to do continuously, like accepting new clients // from the net, refreshing the screen in interactive mode, and so forth // void backgroundTasks(void) { static time_t next_stats; if (Modes.net) { modesReadFromClients(); } // If Modes.aircrafts is not NULL, remove any stale aircraft if (Modes.aircrafts) { interactiveRemoveStaleAircrafts(); } // Refresh screen when in interactive mode if (Modes.interactive) { interactiveShowData(); } if (Modes.stats > 0) { time_t now = time(NULL); if (now > next_stats) { if (next_stats != 0) display_stats(); next_stats = now + Modes.stats; } } }
// //========================================================================= // // This function is called a few times every second by main in order to // perform tasks we need to do continuously, like accepting new clients // from the net, refreshing the screen in interactive mode, and so forth // void backgroundTasks(void) { if (Modes.net) { modesReadFromClients(); } // If Modes.aircrafts is not NULL, remove any stale aircraft if (Modes.aircrafts) { interactiveRemoveStaleAircrafts(); } // Refresh screen when in interactive mode if (Modes.interactive) { interactiveShowData(); } }
// Handle resizing terminal void sigWinchCallback() { signal(SIGWINCH, SIG_IGN); Modes.interactive_rows = getTermRows(); interactiveShowData(); signal(SIGWINCH, sigWinchCallback); }
// //========================================================================= // int main(int argc, char **argv) { int j; // Set sane defaults modesInitConfig(); signal(SIGINT, sigintHandler); // Define Ctrl/C handler (exit program) // Parse the command line options for (j = 1; j < argc; j++) { int more = j+1 < argc; // There are more arguments if (!strcmp(argv[j],"--device-index") && more) { Modes.dev_index = atoi(argv[++j]); } else if (!strcmp(argv[j],"--gain") && more) { Modes.gain = (int) atof(argv[++j])*10; // Gain is in tens of DBs } else if (!strcmp(argv[j],"--enable-agc")) { Modes.enable_agc++; } else if (!strcmp(argv[j],"--freq") && more) { Modes.freq = (int) strtoll(argv[++j],NULL,10); } else if (!strcmp(argv[j],"--ifile") && more) { Modes.filename = strdup(argv[++j]); } else if (!strcmp(argv[j],"--fix")) { Modes.nfix_crc = 1; } else if (!strcmp(argv[j],"--no-fix")) { Modes.nfix_crc = 0; } else if (!strcmp(argv[j],"--no-crc-check")) { Modes.check_crc = 0; } else if (!strcmp(argv[j],"--phase-enhance")) { Modes.phase_enhance = 1; } else if (!strcmp(argv[j],"--raw")) { Modes.raw = 1; } else if (!strcmp(argv[j],"--net")) { Modes.net = 1; } else if (!strcmp(argv[j],"--modeac")) { Modes.mode_ac = 1; } else if (!strcmp(argv[j],"--net-beast")) { Modes.beast = 1; } else if (!strcmp(argv[j],"--net-only")) { Modes.net = 1; Modes.net_only = 1; } else if (!strcmp(argv[j],"--net-heartbeat") && more) { Modes.net_heartbeat_rate = atoi(argv[++j]) * 15; } else if (!strcmp(argv[j],"--net-ro-size") && more) { Modes.net_output_raw_size = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-ro-rate") && more) { Modes.net_output_raw_rate = atoi(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]);} } else if (!strcmp(argv[j],"--net-ri-port") && more) { Modes.net_input_raw_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-bo-port") && more) { Modes.net_output_beast_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-bi-port") && more) { Modes.net_input_beast_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-http-port") && more) { Modes.net_http_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-sbs-port") && more) { Modes.net_output_sbs_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--onlyaddr")) { Modes.onlyaddr = 1; } else if (!strcmp(argv[j],"--metric")) { Modes.metric = 1; } else if (!strcmp(argv[j],"--aggressive")) { Modes.nfix_crc = MODES_MAX_BITERRORS; } else if (!strcmp(argv[j],"--interactive")) { Modes.interactive = 1; } else if (!strcmp(argv[j],"--interactive-rows") && more) { Modes.interactive_rows = atoi(argv[++j]); } else if (!strcmp(argv[j],"--interactive-ttl") && more) { Modes.interactive_display_ttl = atoi(argv[++j]); } else if (!strcmp(argv[j],"--lat") && more) { Modes.fUserLat = atof(argv[++j]); } else if (!strcmp(argv[j],"--lon") && more) { Modes.fUserLon = atof(argv[++j]); } else if (!strcmp(argv[j],"--debug") && more) { char *f = argv[++j]; while(*f) { switch(*f) { case 'D': Modes.debug |= MODES_DEBUG_DEMOD; break; case 'd': Modes.debug |= MODES_DEBUG_DEMODERR; break; case 'C': Modes.debug |= MODES_DEBUG_GOODCRC; break; case 'c': Modes.debug |= MODES_DEBUG_BADCRC; break; case 'p': Modes.debug |= MODES_DEBUG_NOPREAMBLE; break; case 'n': Modes.debug |= MODES_DEBUG_NET; break; case 'j': Modes.debug |= MODES_DEBUG_JS; break; default: fprintf(stderr, "Unknown debugging flag: %c\n", *f); exit(1); break; } f++; } } else if (!strcmp(argv[j],"--stats")) { Modes.stats = 1; } else if (!strcmp(argv[j],"--snip") && more) { snipMode(atoi(argv[++j])); exit(0); } else if (!strcmp(argv[j],"--help")) { showHelp(); exit(0); } else if (!strcmp(argv[j],"--ppm") && more) { Modes.ppm_error = atoi(argv[++j]); } else if (!strcmp(argv[j],"--quiet")) { Modes.quiet = 1; } else if (!strcmp(argv[j],"--mlat")) { Modes.mlat = 1; } else if (!strcmp(argv[j],"--interactive-rtl1090")) { Modes.interactive = 1; Modes.interactive_rtl1090 = 1; } else { fprintf(stderr, "Unknown or not enough arguments for option '%s'.\n\n", argv[j]); showHelp(); exit(1); } } #ifndef _WIN32 // Setup for SIGWINCH for handling lines if (Modes.interactive) {signal(SIGWINCH, sigWinchCallback);} #endif // Initialization modesInit(); if (Modes.net_only) { fprintf(stderr,"Net-only mode, no RTL device or file open.\n"); } else if (Modes.filename == NULL) { modesInitRTLSDR(); } else { if (Modes.filename[0] == '-' && Modes.filename[1] == '\0') { Modes.fd = STDIN_FILENO; } else if ((Modes.fd = open(Modes.filename,O_RDONLY)) == -1) { perror("Opening data file"); exit(1); } } if (Modes.net) modesInitNet(); // If the user specifies --net-only, just run in order to serve network // clients without reading data from the RTL device while (Modes.net_only) { if (Modes.exit) exit(0); // If we exit net_only nothing further in main() backgroundTasks(); usleep(100000); } // Create the thread that will read the data from the device. pthread_create(&Modes.reader_thread, NULL, readerThreadEntryPoint, NULL); pthread_mutex_lock(&Modes.data_mutex); while (Modes.exit == 0) { if (Modes.iDataReady == 0) { pthread_cond_wait(&Modes.data_cond,&Modes.data_mutex); // This unlocks Modes.data_mutex, and waits for Modes.data_cond continue; // Once (Modes.data_cond) occurs, it locks Modes.data_mutex } // Modes.data_mutex is Locked, and (Modes.iDataReady != 0) if (Modes.iDataReady) { // Check we have new data, just in case!! Modes.iDataOut &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase // Translate the next lot of I/Q samples into Modes.magnitude computeMagnitudeVector(Modes.pData[Modes.iDataOut]); Modes.stSystemTimeBlk = Modes.stSystemTimeRTL[Modes.iDataOut]; // Update the input buffer pointer queue Modes.iDataOut = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataOut + 1); Modes.iDataReady = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn - Modes.iDataOut); // If we lost some blocks, correct the timestamp if (Modes.iDataLost) { Modes.timestampBlk += (MODES_ASYNC_BUF_SAMPLES * 6 * Modes.iDataLost); Modes.iDataLost = 0; } // It's safe to release the lock now pthread_cond_signal (&Modes.data_cond); pthread_mutex_unlock(&Modes.data_mutex); // Process data after releasing the lock, so that the capturing // thread can read data while we perform computationally expensive // stuff at the same time. detectModeS(Modes.magnitude, MODES_ASYNC_BUF_SAMPLES); // Update the timestamp ready for the next block Modes.timestampBlk += (MODES_ASYNC_BUF_SAMPLES*6); } else { pthread_cond_signal (&Modes.data_cond); pthread_mutex_unlock(&Modes.data_mutex); } backgroundTasks(); pthread_mutex_lock(&Modes.data_mutex); } // If --stats were given, print statistics if (Modes.stats) { printf("\n\n"); if (Modes.interactive) interactiveShowData(); printf("%d ModeA/C detected\n", Modes.stat_ModeAC); printf("%d valid Mode-S preambles\n", Modes.stat_valid_preamble); printf("%d DF-?? fields corrected for length\n", Modes.stat_DF_Len_Corrected); printf("%d DF-?? fields corrected for type\n", Modes.stat_DF_Type_Corrected); printf("%d demodulated with 0 errors\n", Modes.stat_demodulated0); printf("%d demodulated with 1 error\n", Modes.stat_demodulated1); printf("%d demodulated with 2 errors\n", Modes.stat_demodulated2); printf("%d demodulated with > 2 errors\n", Modes.stat_demodulated3); printf("%d with good crc\n", Modes.stat_goodcrc); printf("%d with bad crc\n", Modes.stat_badcrc); printf("%d errors corrected\n", Modes.stat_fixed); for (j = 0; j < MODES_MAX_BITERRORS; j++) { printf(" %d with %d bit %s\n", Modes.stat_bit_fix[j], j+1, (j==0)?"error":"errors"); } if (Modes.phase_enhance) { printf("%d phase enhancement attempts\n", Modes.stat_out_of_phase); printf("%d phase enhanced demodulated with 0 errors\n", Modes.stat_ph_demodulated0); printf("%d phase enhanced demodulated with 1 error\n", Modes.stat_ph_demodulated1); printf("%d phase enhanced demodulated with 2 errors\n", Modes.stat_ph_demodulated2); printf("%d phase enhanced demodulated with > 2 errors\n", Modes.stat_ph_demodulated3); printf("%d phase enhanced with good crc\n", Modes.stat_ph_goodcrc); printf("%d phase enhanced with bad crc\n", Modes.stat_ph_badcrc); printf("%d phase enhanced errors corrected\n", Modes.stat_ph_fixed); for (j = 0; j < MODES_MAX_BITERRORS; j++) { printf(" %d with %d bit %s\n", Modes.stat_ph_bit_fix[j], j+1, (j==0)?"error":"errors"); } } printf("%d total usable messages\n", Modes.stat_goodcrc + Modes.stat_ph_goodcrc + Modes.stat_fixed + Modes.stat_ph_fixed); } if (Modes.filename == NULL) { rtlsdr_cancel_async(Modes.dev); // Cancel rtlsdr_read_async will cause data input thread to terminate cleanly rtlsdr_close(Modes.dev); } pthread_cond_destroy(&Modes.data_cond); // Thread cleanup pthread_mutex_destroy(&Modes.data_mutex); pthread_join(Modes.reader_thread,NULL); // Wait on reader thread exit #ifndef _WIN32 pthread_exit(0); #else return (0); #endif }
static void display_stats(void) { int j; time_t now = time(NULL); printf("\n\n"); if (Modes.interactive) interactiveShowData(); printf("Statistics as at %s", ctime(&now)); printf("%d sample blocks processed\n", Modes.stat_blocks_processed); printf("%d sample blocks dropped\n", Modes.stat_blocks_dropped); printf("%d ModeA/C detected\n", Modes.stat_ModeAC); printf("%d valid Mode-S preambles\n", Modes.stat_valid_preamble); printf("%d DF-?? fields corrected for length\n", Modes.stat_DF_Len_Corrected); printf("%d DF-?? fields corrected for type\n", Modes.stat_DF_Type_Corrected); printf("%d demodulated with 0 errors\n", Modes.stat_demodulated0); printf("%d demodulated with 1 error\n", Modes.stat_demodulated1); printf("%d demodulated with 2 errors\n", Modes.stat_demodulated2); printf("%d demodulated with > 2 errors\n", Modes.stat_demodulated3); printf("%d with good crc\n", Modes.stat_goodcrc); printf("%d with bad crc\n", Modes.stat_badcrc); printf("%d errors corrected\n", Modes.stat_fixed); for (j = 0; j < MODES_MAX_BITERRORS; j++) { printf(" %d with %d bit %s\n", Modes.stat_bit_fix[j], j+1, (j==0)?"error":"errors"); } if (Modes.phase_enhance) { printf("%d phase enhancement attempts\n", Modes.stat_out_of_phase); printf("%d phase enhanced demodulated with 0 errors\n", Modes.stat_ph_demodulated0); printf("%d phase enhanced demodulated with 1 error\n", Modes.stat_ph_demodulated1); printf("%d phase enhanced demodulated with 2 errors\n", Modes.stat_ph_demodulated2); printf("%d phase enhanced demodulated with > 2 errors\n", Modes.stat_ph_demodulated3); printf("%d phase enhanced with good crc\n", Modes.stat_ph_goodcrc); printf("%d phase enhanced with bad crc\n", Modes.stat_ph_badcrc); printf("%d phase enhanced errors corrected\n", Modes.stat_ph_fixed); for (j = 0; j < MODES_MAX_BITERRORS; j++) { printf(" %d with %d bit %s\n", Modes.stat_ph_bit_fix[j], j+1, (j==0)?"error":"errors"); } } printf("%d total usable messages\n", Modes.stat_goodcrc + Modes.stat_ph_goodcrc + Modes.stat_fixed + Modes.stat_ph_fixed); fflush(stdout); Modes.stat_blocks_processed = Modes.stat_blocks_dropped = 0; Modes.stat_ModeAC = Modes.stat_valid_preamble = Modes.stat_DF_Len_Corrected = Modes.stat_DF_Type_Corrected = Modes.stat_demodulated0 = Modes.stat_demodulated1 = Modes.stat_demodulated2 = Modes.stat_demodulated3 = Modes.stat_goodcrc = Modes.stat_badcrc = Modes.stat_fixed = 0; Modes.stat_out_of_phase = Modes.stat_ph_demodulated0 = Modes.stat_ph_demodulated1 = Modes.stat_ph_demodulated2 = Modes.stat_ph_demodulated3 = Modes.stat_ph_goodcrc = Modes.stat_ph_badcrc = Modes.stat_ph_fixed = 0; for (j = 0; j < MODES_MAX_BITERRORS; j++) { Modes.stat_ph_bit_fix[j] = 0; Modes.stat_bit_fix[j] = 0; } }
// //========================================================================= // // This function is called a few times every second by main in order to // perform tasks we need to do continuously, like accepting new clients // from the net, refreshing the screen in interactive mode, and so forth // void backgroundTasks(void) { static uint64_t next_stats_display; static uint64_t next_stats_update; static uint64_t next_json, next_history; uint64_t now = mstime(); icaoFilterExpire(); trackPeriodicUpdate(); if (Modes.net) { modesNetPeriodicWork(); } // Refresh screen when in interactive mode if (Modes.interactive) { interactiveShowData(); } // always update end time so it is current when requests arrive Modes.stats_current.end = now; if (now >= next_stats_update) { int i; if (next_stats_update == 0) { next_stats_update = now + 60000; } else { Modes.stats_latest_1min = (Modes.stats_latest_1min + 1) % 15; Modes.stats_1min[Modes.stats_latest_1min] = Modes.stats_current; add_stats(&Modes.stats_current, &Modes.stats_alltime, &Modes.stats_alltime); add_stats(&Modes.stats_current, &Modes.stats_periodic, &Modes.stats_periodic); reset_stats(&Modes.stats_5min); for (i = 0; i < 5; ++i) add_stats(&Modes.stats_1min[(Modes.stats_latest_1min - i + 15) % 15], &Modes.stats_5min, &Modes.stats_5min); reset_stats(&Modes.stats_15min); for (i = 0; i < 15; ++i) add_stats(&Modes.stats_1min[i], &Modes.stats_15min, &Modes.stats_15min); reset_stats(&Modes.stats_current); Modes.stats_current.start = Modes.stats_current.end = now; if (Modes.json_dir) writeJsonToFile("stats.json", generateStatsJson); next_stats_update += 60000; } } if (Modes.stats && now >= next_stats_display) { if (next_stats_display == 0) { next_stats_display = now + Modes.stats; } else { add_stats(&Modes.stats_periodic, &Modes.stats_current, &Modes.stats_periodic); display_stats(&Modes.stats_periodic); reset_stats(&Modes.stats_periodic); next_stats_display += Modes.stats; } } if (Modes.json_dir && now >= next_json) { writeJsonToFile("aircraft.json", generateAircraftJson); 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); 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 = generateAircraftJson("/data/aircraft.json", &Modes.json_aircraft_history[Modes.json_aircraft_history_next].clen); if (Modes.json_dir) { char filebuf[PATH_MAX]; snprintf(filebuf, PATH_MAX, "history_%d.json", Modes.json_aircraft_history_next); writeJsonToFile(filebuf, generateHistoryJson); } Modes.json_aircraft_history_next = (Modes.json_aircraft_history_next+1) % HISTORY_SIZE; if (rewrite_receiver_json) writeJsonToFile("receiver.json", generateReceiverJson); // number of history entries changed next_history = now + HISTORY_INTERVAL; } }
// //========================================================================= // int main(int argc, char **argv) { int j, fd; struct client *c; // Set sane defaults view1090InitConfig(); signal(SIGINT, sigintHandler); // Define Ctrl/C handler (exit program) // Parse the command line options for (j = 1; j < argc; j++) { int more = ((j + 1) < argc); // There are more arguments if (!strcmp(argv[j],"--net-bo-port") && more) { Modes.net_input_beast_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-bo-ipaddr") && more) { strcpy(View1090.net_input_beast_ipaddr, argv[++j]); } else if (!strcmp(argv[j],"--modeac")) { Modes.mode_ac = 1; } else if (!strcmp(argv[j],"--interactive-rows") && more) { Modes.interactive_rows = atoi(argv[++j]); } else if (!strcmp(argv[j],"--interactive")) { Modes.interactive = 1; } else if (!strcmp(argv[j],"--interactive-ttl") && more) { Modes.interactive_display_ttl = atoi(argv[++j]); } else if (!strcmp(argv[j],"--interactive-rtl1090")) { Modes.interactive = 1; Modes.interactive_rtl1090 = 1; } else if (!strcmp(argv[j],"--lat") && more) { Modes.fUserLat = atof(argv[++j]); } else if (!strcmp(argv[j],"--lon") && more) { Modes.fUserLon = atof(argv[++j]); } else if (!strcmp(argv[j],"--metric")) { Modes.metric = 1; } else if (!strcmp(argv[j],"--no-crc-check")) { Modes.check_crc = 0; } else if (!strcmp(argv[j],"--fix")) { Modes.nfix_crc = 1; } else if (!strcmp(argv[j],"--no-fix")) { Modes.nfix_crc = 0; } else if (!strcmp(argv[j],"--aggressive")) { Modes.nfix_crc = MODES_MAX_BITERRORS; } else if (!strcmp(argv[j],"--help")) { showHelp(); exit(0); } else { fprintf(stderr, "Unknown or not enough arguments for option '%s'.\n\n", argv[j]); showHelp(); exit(1); } } // Initialization view1090Init(); // Try to connect to the selected ip address and port. We only support *ONE* input connection which we initiate.here. if ((fd = anetTcpConnect(Modes.aneterr, View1090.net_input_beast_ipaddr, Modes.net_input_beast_port)) == ANET_ERR) { fprintf(stderr, "Failed to connect to %s:%d\n", View1090.net_input_beast_ipaddr, Modes.net_input_beast_port); exit(1); } // // Setup a service callback client structure for a beast binary input (from dump1090) // This is a bit dodgy under Windows. The fd parameter is a handle to the internet // socket on which we are receiving data. Under Linux, these seem to start at 0 and // count upwards. However, Windows uses "HANDLES" and these don't nececeriy start at 0. // dump1090 limits fd to values less than 1024, and then uses the fd parameter to // index into an array of clients. This is ok-ish if handles are allocated up from 0. // However, there is no gaurantee that Windows will behave like this, and if Windows // allocates a handle greater than 1024, then dump1090 won't like it. On my test machine, // the first Windows handle is usually in the 0x54 (84 decimal) region. if (fd >= MODES_NET_MAX_FD) { // Max number of clients reached fprintf(stderr, "Max number of clients exceeded : fd = 0x%X\n", fd); close(fd); exit(1); } c = (struct client *) malloc(sizeof(*c)); c->buflen = 0; c->fd = c->service = Modes.bis = fd; Modes.clients[fd] = c; if (Modes.maxfd < fd) { Modes.maxfd = fd; } // Keep going till the user does something that stops us while (!Modes.exit) { modesReadFromClient(c,"",decodeBinMessage); interactiveRemoveStaleAircrafts(); interactiveShowData(); } // The user has stopped us, so close any socket we opened if (fd != ANET_ERR) {close(fd);} pthread_exit(0); return (0); }
// //========================================================================= // int main(int argc, char **argv) { int j; struct client *c; struct net_service *s; char *bo_connect_ipaddr = "127.0.0.1"; int bo_connect_port = 30005; // Set sane defaults view1090InitConfig(); signal(SIGINT, sigintHandler); // Define Ctrl/C handler (exit program) // Parse the command line options for (j = 1; j < argc; j++) { int more = ((j + 1) < argc); // There are more arguments if (!strcmp(argv[j],"--net-bo-port") && more) { bo_connect_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-bo-ipaddr") && more) { bo_connect_ipaddr = argv[++j]; } else if (!strcmp(argv[j],"--modeac")) { Modes.mode_ac = 1; } else if (!strcmp(argv[j],"--interactive-rows") && more) { Modes.interactive_rows = atoi(argv[++j]); } else if (!strcmp(argv[j],"--no-interactive")) { Modes.interactive = 0; } else if (!strcmp(argv[j],"--show-only") && more) { Modes.show_only = (uint32_t) strtoul(argv[++j], NULL, 16); Modes.interactive = 0; } else if (!strcmp(argv[j],"--interactive-ttl") && more) { Modes.interactive_display_ttl = (uint64_t)(1000 * atof(argv[++j])); } else if (!strcmp(argv[j],"--interactive-rtl1090")) { Modes.interactive = 1; Modes.interactive_rtl1090 = 1; } else if (!strcmp(argv[j],"--lat") && more) { Modes.fUserLat = atof(argv[++j]); } else if (!strcmp(argv[j],"--lon") && more) { Modes.fUserLon = atof(argv[++j]); } else if (!strcmp(argv[j],"--metric")) { Modes.metric = 1; } else if (!strcmp(argv[j],"--no-crc-check")) { Modes.check_crc = 0; } else if (!strcmp(argv[j],"--fix")) { Modes.nfix_crc = 1; } else if (!strcmp(argv[j],"--no-fix")) { Modes.nfix_crc = 0; } else if (!strcmp(argv[j],"--aggressive")) { Modes.nfix_crc = MODES_MAX_BITERRORS; } else if (!strcmp(argv[j],"--max-range") && more) { Modes.maxRange = atof(argv[++j]) * 1852.0; // convert to metres } else if (!strcmp(argv[j],"--help")) { showHelp(); exit(0); } else { fprintf(stderr, "Unknown or not enough arguments for option '%s'.\n\n", argv[j]); showHelp(); exit(1); } } #ifdef _WIN32 // Try to comply with the Copyright license conditions for binary distribution if (!Modes.quiet) {showCopyright();} #define MSG_DONTWAIT 0 #endif #ifndef _WIN32 // Setup for SIGWINCH for handling lines if (Modes.interactive) {signal(SIGWINCH, sigWinchCallback);} #endif // Initialization view1090Init(); modesInitNet(); // Try to connect to the selected ip address and port. We only support *ONE* input connection which we initiate.here. s = makeBeastInputService(); c = serviceConnect(s, bo_connect_ipaddr, bo_connect_port); if (!c) { fprintf(stderr, "Failed to connect to %s:%d: %s\n", bo_connect_ipaddr, bo_connect_port, Modes.aneterr); exit(1); } // Keep going till the user does something that stops us while (!Modes.exit) { icaoFilterExpire(); trackPeriodicUpdate(); modesNetPeriodicWork(); if (Modes.interactive) interactiveShowData(); if (s->connections == 0) { // lost input connection, try to reconnect usleep(1000000); c = serviceConnect(s, bo_connect_ipaddr, bo_connect_port); continue; } usleep(100000); } return (0); }