forked from wiedehopf/readsb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
readsb.h
1302 lines (1137 loc) · 40.4 KB
/
readsb.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Part of readsb, a Mode-S/ADSB/TIS message decoder.
//
// readsb.h: main program header
//
// Copyright (c) 2019 Michael Wolf <[email protected]>
//
// This code is based on a detached fork of dump1090-fa.
//
// Copyright (c) 2014-2016 Oliver Jowett <[email protected]>
//
// This file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// This file incorporates work covered by the following copyright and
// license:
//
// Copyright (C) 2012 by Salvatore Sanfilippo <[email protected]>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef __DUMP1090_H
#define __DUMP1090_H
#ifndef ALL_JSON
#define ALL_JSON 0
#endif
// Default version number, if not overriden by the Makefile
#ifndef MODES_READSB_VERSION
#define MODES_READSB_VERSION "Unknown"
#endif
#ifndef MODES_READSB_VARIANT
#define MODES_READSB_VARIANT "readsb"
#endif
#define VERSION_STRING MODES_READSB_VARIANT " version: " MODES_READSB_VERSION
// ============================= Include files ==========================
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <time.h>
#include <limits.h>
#include <sys/types.h>
#include <dirent.h>
#include <zlib.h>
#include <inttypes.h>
#include <sched.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include "minilzo/minilzo.h"
#include "threadpool.h"
#include <stdatomic.h>
#include <zstd.h>
#include <sys/mman.h>
#include "compat/compat.h"
// ============================= #defines ===============================
#define MODES_DEFAULT_FREQ 1090000000
#define MODES_RTL_BUFFERS 16 // Number of RTL buffers
#define MODES_MAG_BUFFERS 12 // Number of magnitude buffers (should be smaller than RTL_BUFFERS for flowcontrol to work)
#define MODES_AUTO_GAIN -100 // Use automatic gain
#define MODES_MAX_GAIN 999999 // Use max available gain
#define MODEAC_MSG_BYTES 2
#define MODES_PREAMBLE_US 8 // microseconds = bits
#define MODES_PREAMBLE_SAMPLES (MODES_PREAMBLE_US * 2)
#define MODES_PREAMBLE_SIZE (MODES_PREAMBLE_SAMPLES * sizeof(uint16_t))
#define MODES_LONG_MSG_BYTES 14
#define MODES_SHORT_MSG_BYTES 7
#define MODES_LONG_MSG_BITS (MODES_LONG_MSG_BYTES * 8)
#define MODES_SHORT_MSG_BITS (MODES_SHORT_MSG_BYTES * 8)
#define MODES_LONG_MSG_SAMPLES (MODES_LONG_MSG_BITS * 2)
#define MODES_SHORT_MSG_SAMPLES (MODES_SHORT_MSG_BITS * 2)
#define MODES_LONG_MSG_SIZE (MODES_LONG_MSG_SAMPLES * sizeof(uint16_t))
#define MODES_SHORT_MSG_SIZE (MODES_SHORT_MSG_SAMPLES * sizeof(uint16_t))
#define MODES_OS_PREAMBLE_SAMPLES (20)
#define MODES_OS_PREAMBLE_SIZE (MODES_OS_PREAMBLE_SAMPLES * sizeof(uint16_t))
#define MODES_OS_LONG_MSG_SAMPLES (268)
#define MODES_OS_SHORT_MSG_SAMPLES (135)
#define MODES_OS_LONG_MSG_SIZE (MODES_LONG_MSG_SAMPLES * sizeof(uint16_t))
#define MODES_OS_SHORT_MSG_SIZE (MODES_SHORT_MSG_SAMPLES * sizeof(uint16_t))
#define MODES_OUT_BUF_SIZE (48*1024)
#define MODES_OUT_FLUSH_INTERVAL (500) // max flush interval
// needs to be larger than OUT_BUF_SIZE above
#define MODES_NET_SNDBUF_SIZE (64*1024)
#define MODES_NET_SNDBUF_MAX (7)
#define HEX_UNKNOWN (0xDEADBEEF)
#define DFTYPE_MODEAC 77
#define INVALID_ALTITUDE (-9999)
#define CANARY (0x665225ca79e653a3)
#define MESSAGE_RATE_CALC_POINTS (2)
// size of various on stack buffers used across the code, let's just be conservative and assume 1 MB of stack
// without heavy recursion 3 of those stack buffers can be in use at the same time, at most we expect to to be in use
#define QUARTER_STACK (256 * 1024)
/* Where did a bit of data arrive from? In order of increasing priority */
typedef enum
{
SOURCE_INVALID, /* data is not valid */
SOURCE_INDIRECT, /* data is of unknown quality */
SOURCE_MODE_AC, /* A/C message */
SOURCE_SBS, /* data is of unknown quality */
SOURCE_MLAT, /* derived from mlat */
SOURCE_MODE_S, /* data from a Mode S message, no full CRC */
SOURCE_JAERO, /* data is from satellite ADS-C */
SOURCE_MODE_S_CHECKED, /* data from a Mode S message with full CRC */
SOURCE_TISB, /* data from a TIS-B extended squitter message */
SOURCE_ADSR, /* data from a ADS-R extended squitter message */
SOURCE_ADSB, /* data from a ADS-B extended squitter message */
SOURCE_PRIO, /* priority input */
} datasource_t;
/* What sort of address is this and who sent it?
* (Earlier values are higher priority)
*/
typedef enum
{
ADDR_ADSB_ICAO = 0, /* ADS-B, ICAO address, transponder sourced */
ADDR_ADSB_ICAO_NT = 1, /* ADS-B, ICAO address, non-transponder */
ADDR_ADSR_ICAO = 2, /* ADS-R, ICAO address */
ADDR_TISB_ICAO = 3, /* TIS-B, ICAO address */
ADDR_JAERO = 4,
ADDR_MLAT = 5,
ADDR_OTHER = 6,
ADDR_MODE_S = 7,
ADDR_ADSB_OTHER = 8, /* ADS-B, other address format */
ADDR_ADSR_OTHER = 9, /* ADS-R, other address format */
ADDR_TISB_TRACKFILE = 10, /* TIS-B, Mode A code + track file number */
ADDR_TISB_OTHER = 11, /* TIS-B, other address format */
ADDR_MODE_A = 12, /* Mode A */
ADDR_UNKNOWN = 15/* unknown address format */
} addrtype_t;
// number of types as defined above
#define NUM_TYPES 14
typedef enum
{
UNIT_FEET,
UNIT_METERS
} altitude_unit_t;
typedef enum
{
ALTITUDE_BARO,
ALTITUDE_GEOM
} altitude_source_t;
typedef enum
{
AG_INVALID = 0,
AG_GROUND = 1,
AG_AIRBORNE = 2,
AG_UNCERTAIN = 3
} airground_t;
typedef enum
{
SIL_INVALID, SIL_UNKNOWN, SIL_PER_SAMPLE, SIL_PER_HOUR
} sil_type_t;
typedef enum
{
CPR_INVALID, CPR_SURFACE, CPR_AIRBORNE, CPR_COARSE
} cpr_type_t;
typedef enum
{
CPR_NONE, CPR_LOCAL, CPR_GLOBAL
} cpr_local_t;
typedef enum
{
HEADING_INVALID, // Not set
HEADING_GROUND_TRACK, // Direction of track over ground, degrees clockwise from true north
HEADING_TRUE, // Heading, degrees clockwise from true north
HEADING_MAGNETIC, // Heading, degrees clockwise from magnetic north
HEADING_MAGNETIC_OR_TRUE, // HEADING_MAGNETIC or HEADING_TRUE depending on the HRD bit in opstatus
HEADING_TRACK_OR_HEADING // GROUND_TRACK / MAGNETIC / TRUE depending on the TAH bit in opstatus
} heading_type_t;
typedef enum {
COMMB_UNKNOWN,
COMMB_AMBIGUOUS,
COMMB_EMPTY_RESPONSE,
COMMB_DATALINK_CAPS,
COMMB_GICB_CAPS,
COMMB_AIRCRAFT_IDENT,
COMMB_ACAS_RA,
COMMB_VERTICAL_INTENT,
COMMB_TRACK_TURN,
COMMB_HEADING_SPEED,
COMMB_METEOROLOGICAL_ROUTINE
} commb_format_t;
typedef enum
{
NAV_MODE_AUTOPILOT = 1,
NAV_MODE_VNAV = 2,
NAV_MODE_ALT_HOLD = 4,
NAV_MODE_APPROACH = 8,
NAV_MODE_LNAV = 16,
NAV_MODE_TCAS = 32
} nav_modes_t;
// Matches encoding of the ES type 28/1 emergency/priority status subfield
typedef enum
{
EMERGENCY_NONE = 0,
EMERGENCY_GENERAL = 1,
EMERGENCY_LIFEGUARD = 2,
EMERGENCY_MINFUEL = 3,
EMERGENCY_NORDO = 4,
EMERGENCY_UNLAWFUL = 5,
EMERGENCY_DOWNED = 6,
EMERGENCY_RESERVED = 7
} emergency_t;
typedef enum {
NAV_ALT_INVALID,
NAV_ALT_UNKNOWN,
NAV_ALT_AIRCRAFT,
NAV_ALT_MCP,
NAV_ALT_FMS
} nav_altitude_source_t;
#define MODES_NON_ICAO_ADDRESS (1<<24) // Set on addresses to indicate they are not ICAO addresses
#define BADDR (0xff123456) // invalid address used to set stuff like cpr_focus and show_only default value
#define MODES_INTERACTIVE_REFRESH_TIME 250 // Milliseconds
#define MODES_INTERACTIVE_DISPLAY_TTL 60000 // Delete from display after 60 seconds
#define MODES_NET_HEARTBEAT_INTERVAL 60000 // milliseconds
//#define ENABLE_DF24
#define HISTORY_SIZE 120
#define HISTORY_INTERVAL 30000
#define MODES_NOTUSED(V) ((void) V)
#ifndef AIRCRAFT_HASH_BITS
#define AIRCRAFT_HASH_BITS 20
#endif
#define AIRCRAFT_BUCKETS (1 << AIRCRAFT_HASH_BITS) // this is critical for hashing purposes
#define MODES_ICAO_FILTER_TTL 60000
#define DB_HASH_BITS 20
#define DB_BUCKETS (1 << DB_HASH_BITS) // this is critical for hashing purposes
#define STATE_BLOBS 256 // change naming scheme if increasing this
#define LOCK_THREADS_MAX 64
#define PERIODIC_UPDATE (1 * SECONDS)
#define REMOVE_STALE_INTERVAL (1 * SECONDS)
#define STAT_BUCKETS 90 // 90 * 10 seconds = 15 min (max interval in stats.json)
#define RANGEDIRS_BUCKETS 360
#define RANGEDIRS_IVALS 64
#define PING_REJECT (3 * SECONDS)
#define PING_DISCONNECT (15 * SECONDS)
#define PING_BUCKETS 20 // statistics on round trip time
#define PING_BUCKETBASE (24) // milliseconds of first bucket
#define PING_BUCKETMULT (1.2) // each bucket will grow by that factor
#define PING_REDUCE (1500) // 1.5 seconds
#define PING_REDUCE_DURATION (15 * SECONDS)
#define GARBAGE_THRESHOLD (512)
/* A timestamp that indicates the data is synthetic, created from a
* multilateration result
*/
#define MAGIC_MLAT_TIMESTAMP 0xFF004D4C4154LL
#define MAGIC_UAT_TIMESTAMP 0xFF004D4C4155LL
#define MAGIC_NOFORWARD_TIMESTAMP 0xFF004D4C4160LL
#define MAGIC_ANY_TIMESTAMP 0xFFFFFFFFFFFFULL
#define likely(x) __builtin_expect((x),1)
#define unlikely(x) __builtin_expect((x),0)
#if defined(__llvm__)
#define _unroll_8 _Pragma ("unroll 8")
#define _unroll_16 _Pragma ("unroll 16")
#define _unroll_32 _Pragma ("unroll 32")
#elif defined(__GNUC__)
#if __GNUC__ >= 8
#define _unroll_8 _Pragma ("GCC unroll 8")
#define _unroll_16 _Pragma ("GCC unroll 16")
#define _unroll_32 _Pragma ("GCC unroll 32")
#else
#define _unroll_8
#define _unroll_16
#define _unroll_32
#endif
#else
#define _unroll_8
#define _unroll_16
#define _unroll_32
#endif
void setExit(int arg);
int priorityTasksPending();
void priorityTasksRun();
#define MemoryAlignment 32
#define ALIGNED __attribute__((aligned(MemoryAlignment)))
static inline void *malloc_or_exit(size_t alignment, size_t size, const char *file, int line) {
void *buf = NULL;
if (alignment && 0) {
// disabled for the moment
size_t mod = size % alignment;
if (mod != 0) {
size += (alignment - mod);
}
buf = aligned_alloc(alignment, size);
if (0) {
mod = size % alignment;
if (mod != 0) {
fprintf(stderr, "aligned_alloc bad alignment: %ld\n", (long) mod);
}
}
} else {
buf = malloc(size);
}
if (unlikely(!buf)) {
setExit(2); // irregular exit ... soon
fprintf(stderr, "FATAL: malloc_or_exit() of size %lld failed: %s:%d (insufficient memory?)\n", (long long) size, file, line);
}
return buf;
}
// disable this ... maybe it test in the future if it makes a diff if i'm bored
#if 0
#define cmalloc(size) malloc_or_exit(MemoryAlignment, size, __FILE__, __LINE__)
#else
#define cmalloc(size) malloc_or_exit(0, size, __FILE__, __LINE__)
#endif
// Include subheaders after all the #defines are in place
#include "toString.h"
#include "util.h"
#include "fasthash.h"
#include "anet.h"
#include "net_io.h"
#include "crc.h"
#include "demod_2400.h"
#include "stats.h"
#include "cpr.h"
#include "icao_filter.h"
#include "convert.h"
#include "sdr.h"
#include "aircraft.h"
#include "globe_index.h"
#include "receiver.h"
#include "geomag.h"
#include "json_out.h"
#include "api.h"
//======================== structure declarations =========================
typedef enum
{
SDR_NONE = 0, SDR_IFILE, SDR_RTLSDR, SDR_BLADERF, SDR_MICROBLADERF, SDR_HACKRF, SDR_MODESBEAST, SDR_PLUTOSDR, SDR_SOAPYSDR, SDR_GNS
} sdr_type_t;
// Structure representing one magnitude buffer
struct mag_buf
{
int64_t sampleTimestamp; // Clock timestamp of the start of this block, 12MHz clock
double mean_level; // Mean of normalized (0..1) signal level
double mean_power; // Mean of normalized (0..1) power level
uint32_t dropped; // Number of dropped samples preceding this buffer
unsigned length; // Number of valid samples _after_ overlap. Total buffer length is buf->length + Modes.trailing_samples.
int64_t sysTimestamp; // Estimated system time at start of block
int64_t sysMicroseconds; // sysTimestamp in microseconds
uint16_t *data; // Magnitude data. Starts with Modes.trailing_samples worth of overlap from the previous block
#if defined(__arm__)
/*padding 4 bytes*/
uint32_t padding;
#endif
};
// Program global state
struct _Threads {
threadT upkeep; // runs priorityTasksUpdate, locks most other threads when doing its thing
threadT decode; // thread doing demodulation, decoding and networking
threadT reader;
threadT json; // thread writing json
threadT globeJson; // thread writing json
threadT globeBin; // thread writing binCraft
threadT misc;
threadT apiUpdate;
};
extern struct _Threads Threads;
struct modeMessage;
struct messageBuffer {
struct modesMessage *msg;
int len;
int alloc;
int id;
struct client *activeClient;
};
struct _Modes
{ // Internal state
pthread_mutex_t traceDebugMutex;
int num_procs;
int allPoolSize;
threadpool_t *allPool;
task_group_t *allTasks;
uint32_t sdr_buf_size;
uint32_t sdr_buf_samples;
int64_t traceWriteTimelimit;
int tracePoolSize;
threadpool_t *tracePool;
task_group_t *traceTasks;
int triggerPastDayTraceWrite;
int lockThreadsCount;
threadT *lockThreads[LOCK_THREADS_MAX];
struct timespec hungTimer1;
struct timespec hungTimer2;
pthread_mutex_t hungTimerMutex;
char *currentTask;
int64_t joinTimeout;
unsigned first_free_buffer; // Entry in mag_buffers that will next be filled with input.
unsigned first_filled_buffer; // Entry in mag_buffers that has valid data and will be demodulated next. If equal to next_free_buffer, there is no unprocessed data.
unsigned trailing_samples; // extra trailing samples in magnitude buffers
int volatile exit; // Exit from the main loop when true
int volatile exitSoon;
int fd; // --ifile option file descriptor
input_format_t input_format; // --iformat option
iq_convert_fn converter_function;
char * dev_name;
int gain;
int dc_filter; // should we apply a DC filter?
int enable_agc;
sdr_type_t sdr_type; // where are we getting data from?
int freq;
int ppm_error;
char aneterr[ANET_ERR_LEN];
struct net_service_group services_in; // Active services which primarily receive data
struct net_service_group services_out; // Active services which primarily send data
int exitNowEventfd;
int exitSoonEventfd;
int net_epfd; // epoll fd used for most network stuff
int net_event_count;
int net_maxEvents;
struct epoll_event *net_events;
struct messageBuffer *netMessageBuffer;
int decodeThreads;
threadpool_t *decodePool;
task_group_t *decodeTasks;
pthread_mutex_t decodeLock;
pthread_mutex_t trackLock;
pthread_mutex_t outputLock;
int max_fds;
int max_fds_api;
int max_fds_net;
int modesClientCount;
int api_fds_per_thread;
int total_aircraft_count;
float estimated_ppm;
uint64_t trace_chunk_size;
uint64_t trace_cache_size;
uint64_t trace_current_size;
ssize_t volatile state_chunk_size;
ssize_t volatile state_chunk_size_read;
ALIGNED struct aircraft * aircraft[AIRCRAFT_BUCKETS];
ALIGNED struct craftArray globeLists[GLOBE_MAX_INDEX+1];
int receiver_table_hash_bits;
int receiver_table_size;
struct receiver **receiverTable;
struct craftArray aircraftActive;
dbEntry *db;
dbEntry **dbIndex;
dbEntry *db2;
dbEntry **db2Index;
int64_t dbModificationTime;
int64_t receiverCount;
struct net_writer raw_out; // Raw output
struct net_writer beast_out; // Beast-format output
struct net_writer beast_reduce_out; // Reduced data Beast-format output
struct net_writer beast_in; // for sending pings to clients sending us beast data
struct net_writer garbage_out; // Beast-format output
struct net_writer sbs_out; // SBS-format output
struct net_writer sbs_out_replay; // SBS-format output
struct net_writer sbs_out_mlat; // SBS-format output
struct net_writer sbs_out_jaero; // SBS-format output
struct net_writer sbs_out_prio; // SBS-format output
struct net_writer json_out; // SBS-format output
struct net_writer asterix_out; // Asterix output
struct net_writer feedmap_out; // SBS-format output
struct net_writer vrs_out; // SBS-format output
struct net_writer fatsv_out; // FATSV-format output
struct net_writer gpsd_in; // for sending 1 line to gpsd
struct net_writer uat_replay_out; // UAT replay output
struct net_service *beast_in_service;
struct net_service *uat_in_service;
struct hexInterval* deleteTrace;
int write_state_blob;
int writeInternalState;
char *replace_state_blob;
int64_t replace_state_inhibit_traces_until;
int64_t network_time_limit;
uint32_t currentPing;
int8_t apiUpdate; // creates json snippets also by non api stuff
int8_t api; // enable api output
int8_t apiBufferInitDone;
int apiThreadCount;
atomic_int apiWorkerCpuMicro;
atomic_uint apiRequestCounter;
atomic_int recentTraceWrites;
atomic_int fullTraceWrites;
atomic_int permTraceWrites;
struct net_service apiService;
struct apiCon **apiListeners;
struct apiBuffer apiBuffer[2];
atomic_int *apiFlip;
struct apiThread *apiThread;
pthread_mutex_t apiFlipMutex; // mutex to read apiFlip
float messageRate;
uint32_t messageRateAcc[MESSAGE_RATE_CALC_POINTS];
int64_t nextMessageRateCalc;
// Configuration
int8_t nfix_crc; // Number of crc bit error(s) to correct
int8_t fixDF; // fix message type single bit errors that become DF17
int8_t check_crc; // Only display messages with good CRC
int8_t raw; // Raw output format
int8_t mode_ac; // Enable decoding of SSR Modes A & C
int8_t mode_ac_auto; // allow toggling of A/C by Beast commands
int8_t debug_net;
int8_t debug_no_discard;
int8_t debug_nextra;
int8_t debug_cpr;
int8_t debug_speed_check;
int8_t debug_garbage;
int8_t debug_receiver;
int8_t debug_rough_receiver_location;
int8_t debug_traceCount;
int8_t debug_traceAlloc;
int8_t debug_sampleCounter;
int8_t debug_dbJson;
int8_t debug_ACAS;
int8_t debug_api;
int8_t debug_recent;
int8_t debug_squawk;
int8_t debug_ping;
int8_t debug_callsign;
int8_t debug_nogps;
int8_t debug_uuid;
int8_t debug_bogus;
int8_t decode_all;
int8_t debug_maxRange;
int8_t debug_removeStaleDuration;
int8_t debug_receiverRangeLimit;
int8_t debug_yeet;
int8_t debug_7700;
int8_t debug_send_uuid;
int8_t debug_provoke_segfault;
int8_t debug_position_timing;
int8_t debug_lastStatus;
int8_t debug_gps;
int8_t debug_planefinder;
int8_t incrementId;
int8_t omitGlobeFiles;
int8_t enableAcasCsv;
int8_t enableAcasJson;
int8_t dump_accept_synthetic_now;
int8_t syntethic_now_suppress_errors;
int8_t tar1090_use_api;
int8_t verbose;
int8_t net_verbatim; // if true, send the original message, not the CRC-corrected one
int8_t netReceiverId;
int8_t ping;
int8_t netReceiverIdPrint;
int8_t netReceiverIdJson;
int8_t netIngest;
int8_t forward_mlat; // forward beast mlat messages to beast output ports
int8_t forward_mlat_sbs; // forward mlat messages to sbs output ports
int8_t beast_forward_noforward;
int8_t beast_set_noforward_timestamp;
int8_t quiet; // Suppress stdout
int8_t interactive; // Interactive mode
int8_t stats_range_histo; // Collect/show a range histogram?
int8_t outline_json; // write a range outline json file
int8_t onlyaddr; // Print only ICAO addresses
int8_t metric; // Use metric units
int8_t use_gnss; // Use GNSS altitudes with H suffix ("HAE", though it isn't always) when available
int8_t mlat; // Use Beast ascii format for raw data output, i.e. @...; iso *...;
int8_t json_location_accuracy; // Accuracy of location metadata: 0=none, 1=approx, 2=exact
int8_t net; // Enable networking
int8_t net_only; // Enable just networking
int8_t jsonLongtype;
int8_t viewadsb;
int8_t sbsReduce; // apply beast reduce logic to SBS messages
int8_t asterixReduce; // apply beast reduce logic to SBS messages
int position_persistence; // Maximum number of consecutive implausible positions from global CPR to invalidate a known position
int json_reliable;
uint32_t filterDF; // Only show messages with certain DF types
uint32_t filterDFbitset; // Bitset, Only show messages with these DF types
int64_t trackExpireJaero;
int64_t trackExpireMax;
uint32_t cpr_focus;
uint32_t trace_focus;
uint32_t leg_focus;
uint32_t show_only; // Only show messages from this ICAO
uint64_t receiver_focus;
uint32_t preambleThreshold;
int net_output_flush_size; // Minimum Size of output data
int32_t net_output_beast_reduce_interval; // Position update interval for data reduction
int32_t ping_reduce;
int32_t ping_reject;
int32_t log_usb_jitter;
int32_t devel_log_ppm;
int64_t doubleBeastReduceIntervalUntil;
float beast_reduce_filter_distance;
float beast_reduce_filter_altitude;
int64_t net_connector_delay;
int64_t net_connector_delay_min;
int64_t next_reconnect_callback;
int64_t last_connector_fail;
int32_t net_heartbeat_interval; // TCP heartbeat interval (milliseconds)
int32_t net_output_flush_interval; // Maximum interval (in milliseconds) between outputwrites
int32_t net_output_flush_interval_beast_reduce; // Maximum interval (in milliseconds) between outputwrites
double fUserLat; // Users receiver/antenna lat/lon needed for initial surface location
double fUserLon; // Users receiver/antenna lat/lon needed for initial surface location
double maxRange; // Absolute maximum decoding range, in *metres*
char *latString;
char *lonString;
double sample_rate; // actual sample rate in use (in hz)
int64_t interactive_display_ttl; // Interactive mode: TTL display
int64_t json_interval; // Interval between rewriting the json aircraft file, in milliseconds; also the advertised map refresh interval
int64_t stats_display_interval; // Interval (millis) between stats dumps,
int64_t range_outline_duration;
int64_t writeTracesActualDuration; // how long the trace writing cycle took
int64_t auto_exit;
char *db_file;
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_uat_replay_ports; // List of UAT replay output TCP ports
char *net_input_uat_ports; // List of UAT input TCP ports
char *net_input_planefinder_ports; // List of planefinder input TCP ports
char *net_output_sbs_ports; // List of SBS output TCP ports
char *net_input_sbs_ports; // List of SBS input TCP ports
char *net_output_jaero_ports; // jaero SBS output ports
char *net_input_jaero_ports; // jaero SBS input 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_output_beast_reduce_ports; // List of Beast output TCP ports
char *net_output_asterix_ports; // List of Asterix output TCP ports
char *net_input_asterix_ports; // List of Asterix input TCP ports
char *net_output_json_ports;
char *net_output_api_ports;
char *garbage_ports;
char *net_output_vrs_ports; // List of VRS output TCP ports
int64_t net_output_vrs_interval;
int64_t net_output_json_interval;
int net_output_json_include_nopos;
struct net_connector *net_connectors; // client connectors
int net_connectors_count;
int net_connectors_size;
int64_t synthetic_now;
char *uuidFile;
char *filename; // Input form file, --ifile option
char *net_bind_address; // Bind address
char *json_dir; // Path to json base directory, or NULL not to write json.
char *globe_history_dir;
char *state_dir;
char *state_parent_dir;
char *dump_beast_dir; // write raw beast with a timestamp every millisecond for low level replay
zstd_fw_t *dump_fw;
int64_t dump_next_ts; // last timestamp sent
int32_t dump_interval;
int32_t dump_beast_index;
uint64_t dump_lastReceiverId;
int8_t dump_reduce; // only dump beast that would be sent out according to reduce_interval
int8_t state_only_on_exit;
int8_t free_aircraft;
int64_t state_write_interval;
char *prom_file;
int64_t heatmap_current_interval;
int64_t heatmap_interval; // don't change data type
int heatmap;
char *heatmap_dir;
int64_t keep_traces; // how long traces are saved in internal memory
int64_t json_trace_interval; // max time ignoring new positions for trace
int32_t traceMax; // max trace length
int32_t traceReserve; // grow trace allocation if we have less than traceReserve free spots
int32_t traceRecentPoints;
int32_t traceCachePoints;
int32_t traceChunkPoints;
int32_t traceChunkMaxBytes;
int json_globe_index; // Enable extra globe indexed json files.
int acasFD1; // file descriptor to write acasFDs to
int acasFD2;
struct tile *json_globe_special_tiles;
int32_t *json_globe_indexes;
int32_t json_globe_indexes_len;
int specialTileCount;
int json_gzip; // Enable extra globe indexed json files.
int beast_fd; // Local Modes-S Beast handler
int beast_baudrate; // Mode-S beast and similar baud rate
char *beast_serial; // Modes-S Beast device path
struct client *serial_client;
int net_sndbuf_size; // TCP output buffer size (64Kb * 2^n)
int json_aircraft_history_next;
int json_aircraft_history_full;
int trace_hist_only;
int sbsOverrideSquawk;
float messageRateMult;
uint32_t binCraftVersion; // never change the type for this variable
int8_t userLocationValid;
int8_t biastee;
int8_t triggerPermWriteDay;
int8_t acasDay;
int8_t traceDay;
int8_t onlyBin; // only write binCraft for globe (1) and also aircraft.json (2)
int8_t enableBinGz;
int8_t updateStats;
int8_t staleStop;
struct timespec reader_cpu_accumulator; // CPU time used by the reader thread, copied out and reset by the main thread under the mutex
ALIGNED struct mag_buf mag_buffers[MODES_MAG_BUFFERS]; // Converted magnitude buffers from RTL or file input
int64_t startup_time;
int64_t next_stats_update;
int64_t next_stats_display;
int64_t next_api_update;
int64_t next_remove_stale;
int stats_bucket; // index that has just been writte to
ALIGNED struct stats stats_10[STAT_BUCKETS];
struct stats stats_current;
struct stats stats_alltime;
struct stats stats_periodic;
struct stats stats_1min;
struct stats stats_5min;
struct stats stats_15min;
struct statsCount globalStatsCount;
// array for thread numbers
ALIGNED int threadNumber[256];
int lastRangeDirHour;
ALIGNED struct distCoords rangeDirs[RANGEDIRS_IVALS][RANGEDIRS_BUCKETS];
int64_t apiShutdownDelay;
};
extern struct _Modes Modes;
// The struct we use to store information about a decoded message.
struct modesMessage
{
// Generic fields
unsigned char msg[MODES_LONG_MSG_BYTES]; // Binary message.
unsigned char verbatim[MODES_LONG_MSG_BYTES]; // Binary message, as originally received before correction
double signalLevel; // RSSI, in the range [0..1], as a fraction of full-scale power
struct client *client; // network client this message came from, NULL otherwise
struct aircraft *aircraft; // tracked aircraft associated with this message or NULL
struct messageBuffer *messageBuffer;
int64_t timestamp; // Timestamp of the message (12MHz clock)
int64_t sysTimestamp; // Timestamp of the message (system time)
uint64_t receiverId; // zero if not transmitted
int msgtype; // Downlink format #
int msgbits; // Number of bits in message
int score; // Scoring from scoreModesMessage, if used
int receiverCountMlat; // number of receivers for MLAT messages
int mlatEPU; // estimated position uncertainty
int correctedbits; // No. of bits corrected
int decodeResult;
uint32_t crc; // Message CRC
uint32_t addr; // Address Announced
uint32_t maybe_addr; // probably the address, good chance to be wrong
addrtype_t addrtype; // address format / source
int8_t remote; // If set this message is from a remote station
int8_t sbs_in; // Signifies this message is coming from basestation input
int8_t address_reliable;
int8_t sbsMsgType; // SBS message type
int8_t reduce_forward; // forward this message for reduced beast output
int8_t garbage; // from garbage receiver
int8_t duplicate; // associated position is a duplicate
int8_t duplicate_checked; // duplicate check done
int8_t pos_bad; // speed_check failed
int8_t pos_ignore; // associated position is old / delayed / misc error
int8_t pos_old; // associated position is old / delayed / misc error
int8_t pos_receiver_range_exceeded;
int8_t trackUnreliable;
int8_t speedUnreliable;
int8_t in_disc_cache;
int8_t jsonPositionOutputEmit;
datasource_t source; // Characterizes the overall message source
// Raw data, just extracted directly from the message
// The names reflect the field names in Annex 4
unsigned IID; // extracted from CRC of DF11s
unsigned AA;
unsigned AC;
unsigned CA;
unsigned CC;
unsigned CF;
unsigned DR;
unsigned FS;
unsigned ID;
unsigned KE;
unsigned ND;
unsigned RI;
unsigned SL;
unsigned UM;
unsigned VS;
unsigned metype; // DF17/18 ME type
unsigned mesub; // DF17/18 ME subtype
unsigned char MB[7];
unsigned char MD[10];
unsigned char ME[7];
unsigned char MV[7];
// Decoded data
bool baro_alt_valid;
bool geom_alt_valid;
bool track_valid;
bool track_rate_valid;
bool heading_valid;
bool roll_valid;
bool gs_valid;
bool ias_valid;
bool tas_valid;
bool mach_valid;
bool baro_rate_valid;
bool geom_rate_valid;
bool squawk_valid;
bool callsign_valid;
bool cpr_valid;
bool cpr_odd;
bool cpr_decoded;
bool cpr_relative;
bool category_valid;
bool geom_delta_valid;
bool from_mlat;
bool from_tisb;
bool spi_valid;
bool spi;
bool alert_valid;
bool alert;
bool emergency_valid;
bool sbs_pos_valid;
bool alt_q_bit;
bool acas_ra_valid;
bool geom_alt_derived;
bool wind_valid;
bool oat_valid;
bool static_pressure_valid;
bool turbulence_valid;
bool humidity_valid;
bool met_source_valid;
bool squawk_emergency_valid;
bool squawk_emergency;
// valid if baro_alt_valid:
int baro_alt; // Altitude in either feet or meters
altitude_unit_t baro_alt_unit; // the unit used for altitude
// valid if geom_alt_valid:
int geom_alt; // Altitude in either feet or meters
altitude_unit_t geom_alt_unit; // the unit used for altitude
// following fields are valid if the corresponding _valid field is set:
int geom_delta; // Difference between geometric and baro alt
float heading; // ground track or heading, degrees (0-359). Reported directly or computed from from EW and NS velocity
heading_type_t heading_type; // how to interpret 'track_or_heading'
float track_rate; // Rate of change of track, degrees/second
float roll; // Roll, degrees, negative is left roll
struct
{
// Groundspeed, kts, reported directly or computed from from EW and NS velocity
// For surface movement, this has different interpretations for v0 and v2; both
// fields are populated. The tracking layer will update "gs.selected".
float v0;
float v2;