net_io.c
Go to the documentation of this file.
1 // dump1090, a Mode S messages decoder for RTLSDR devices.
2 //
3 // Copyright (C) 2012 by Salvatore Sanfilippo <antirez@gmail.com>
4 //
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are
9 // met:
10 //
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //
14 // * Redistributions in binary form must reproduce the above copyright
15 // notice, this list of conditions and the following disclaimer in the
16 // documentation and/or other materials provided with the distribution.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 
31 #include "dump1090.h"
32 //
33 // ============================= Networking =============================
34 //
35 // Note: here we disregard any kind of good coding practice in favor of
36 // extreme simplicity, that is:
37 //
38 // 1) We only rely on the kernel buffers for our I/O without any kind of
39 // user space buffering.
40 // 2) We don't register any kind of event handler, from time to time a
41 // function gets called and we accept new connections. All the rest is
42 // handled via non-blocking I/O and manually polling clients to see if
43 // they have something new to share with us when reading is needed.
44 //
45 //=========================================================================
46 //
47 // Networking "stack" initialization
48 //
49 void modesInitNet(void) {
50  struct {
51  char *descr;
52  int *socket;
53  int port;
54  } services[6] = {
55  {"Raw TCP output", &Modes.ros, Modes.net_output_raw_port},
56  {"Raw TCP input", &Modes.ris, Modes.net_input_raw_port},
57  {"Beast TCP output", &Modes.bos, Modes.net_output_beast_port},
58  {"Beast TCP input", &Modes.bis, Modes.net_input_beast_port},
59  {"HTTP server", &Modes.https, Modes.net_http_port},
60  {"Basestation TCP output", &Modes.sbsos, Modes.net_output_sbs_port}
61  };
62  int j;
63 
64  memset(Modes.clients,0,sizeof(Modes.clients));
65  Modes.maxfd = -1;
66 
67  for (j = 0; j < 6; j++) {
68  int s = anetTcpServer(Modes.aneterr, services[j].port, NULL);
69  if (s == -1) {
70  fprintf(stderr, "Error opening the listening port %d (%s): %s\n",
71  services[j].port, services[j].descr, strerror(errno));
72  exit(1);
73  }
74  anetNonBlock(Modes.aneterr, s);
75  *services[j].socket = s;
76  }
77 
78  signal(SIGPIPE, SIG_IGN);
79 }
80 //
81 //=========================================================================
82 //
83 // This function gets called from time to time when the decoding thread is
84 // awakened by new data arriving. This usually happens a few times every second
85 //
86 void modesAcceptClients(void) {
87  int fd, port;
88  unsigned int j;
89  struct client *c;
90  int services[6];
91 
92  services[0] = Modes.ros;
93  services[1] = Modes.ris;
94  services[2] = Modes.bos;
95  services[3] = Modes.bis;
96  services[4] = Modes.https;
97  services[5] = Modes.sbsos;
98 
99  for (j = 0; j < sizeof(services)/sizeof(int); j++) {
100  fd = anetTcpAccept(Modes.aneterr, services[j], NULL, &port);
101  if (fd == -1) continue;
102 
103  if (fd >= MODES_NET_MAX_FD) {
104  close(fd);
105  return; // Max number of clients reached
106  }
107 
108  anetNonBlock(Modes.aneterr, fd);
109  c = (struct client *) malloc(sizeof(*c));
110  c->service = services[j];
111  c->fd = fd;
112  c->buflen = 0;
113  Modes.clients[fd] = c;
115 
116  if (Modes.maxfd < fd) Modes.maxfd = fd;
117  if (services[j] == Modes.sbsos) Modes.stat_sbs_connections++;
118  if (services[j] == Modes.ros) Modes.stat_raw_connections++;
119  if (services[j] == Modes.bos) Modes.stat_beast_connections++;
120 
121  j--; // Try again with the same listening port
122 
123  if (Modes.debug & MODES_DEBUG_NET)
124  printf("Created new client %d\n", fd);
125  }
126 }
127 //
128 //=========================================================================
129 //
130 // On error free the client, collect the structure, adjust maxfd if needed.
131 //
132 void modesFreeClient(int fd) {
133  close(fd);
134  if (Modes.clients[fd]->service == Modes.sbsos) {
135  if (Modes.stat_sbs_connections) Modes.stat_sbs_connections--;
136  }
137  else if (Modes.clients[fd]->service == Modes.ros) {
138  if (Modes.stat_raw_connections) Modes.stat_raw_connections--;
139  }
140  else if (Modes.clients[fd]->service == Modes.bos) {
141  if (Modes.stat_beast_connections) Modes.stat_beast_connections--;
142  }
143  free(Modes.clients[fd]);
144  Modes.clients[fd] = NULL;
145 
146  if (Modes.debug & MODES_DEBUG_NET)
147  printf("Closing client %d\n", fd);
148 
149  // If this was our maxfd, rescan the full clients array to check what's
150  // the new max.
151  if (Modes.maxfd == fd) {
152  int j;
153 
154  Modes.maxfd = -1;
155  for (j = 0; j < MODES_NET_MAX_FD; j++) {
156  if (Modes.clients[j]) Modes.maxfd = j;
157  }
158  }
159 }
160 //
161 //=========================================================================
162 //
163 // Send the specified message to all clients listening for a given service
164 //
165 void modesSendAllClients(int service, void *msg, int len) {
166  int j;
167  struct client *c;
168 
169  for (j = 0; j <= Modes.maxfd; j++) {
170  c = Modes.clients[j];
171  if (c && c->service == service) {
172  int nwritten = write(j, msg, len);
173  if (nwritten != len) {
174  modesFreeClient(j);
175  }
176  }
177  }
178 }
179 //
180 //=========================================================================
181 //
182 // Write raw output in Beast Binary format with Timestamp to TCP clients
183 //
185  char *p = &Modes.beastOut[Modes.beastOutUsed];
186  int msgLen = mm->msgbits / 8;
187  char * pTimeStamp;
188  int j;
189 
190  *p++ = 0x1a;
191  if (msgLen == MODES_SHORT_MSG_BYTES)
192  {*p++ = '2';}
193  else if (msgLen == MODES_LONG_MSG_BYTES)
194  {*p++ = '3';}
195  else if (msgLen == MODEAC_MSG_BYTES)
196  {*p++ = '1';}
197  else
198  {return;}
199 
200  pTimeStamp = (char *) &mm->timestampMsg;
201  for (j = 5; j >= 0; j--) {
202  *p++ = pTimeStamp[j];
203  }
204 
205  *p++ = mm->signalLevel;
206 
207  memcpy(p, mm->msg, msgLen);
208 
209  Modes.beastOutUsed += (msgLen + 9);
210  if (Modes.beastOutUsed >= Modes.net_output_raw_size)
211  {
212  modesSendAllClients(Modes.bos, Modes.beastOut, Modes.beastOutUsed);
213  Modes.beastOutUsed = 0;
214  Modes.net_output_raw_rate_count = 0;
215  }
216 }
217 //
218 //=========================================================================
219 //
220 // Write raw output to TCP clients
221 //
223  char *p = &Modes.rawOut[Modes.rawOutUsed];
224  int msgLen = mm->msgbits / 8;
225  int j;
226  unsigned char * pTimeStamp;
227 
228  if (Modes.mlat && mm->timestampMsg) {
229  *p++ = '@';
230  pTimeStamp = (unsigned char *) &mm->timestampMsg;
231  for (j = 5; j >= 0; j--) {
232  sprintf(p, "%02X", pTimeStamp[j]);
233  p += 2;
234  }
235  Modes.rawOutUsed += 12; // additional 12 characters for timestamp
236  } else
237  *p++ = '*';
238 
239  for (j = 0; j < msgLen; j++) {
240  sprintf(p, "%02X", mm->msg[j]);
241  p += 2;
242  }
243 
244  *p++ = ';';
245  *p++ = '\n';
246 
247  Modes.rawOutUsed += ((msgLen*2) + 3);
248  if (Modes.rawOutUsed >= Modes.net_output_raw_size)
249  {
250  modesSendAllClients(Modes.ros, Modes.rawOut, Modes.rawOutUsed);
251  Modes.rawOutUsed = 0;
252  Modes.net_output_raw_rate_count = 0;
253  }
254 }
255 //
256 //=========================================================================
257 //
258 // Write SBS output to TCP clients
259 // The message structure mm->bFlags tells us what has been updated by this message
260 //
262  char msg[256], *p = msg;
263  uint32_t offset;
264  struct timeb epocTime;
265  struct tm stTime;
266  int msgType;
267 
268  //
269  // SBS BS style output checked against the following reference
270  // http://www.homepages.mcb.net/bones/SBS/Article/Barebones42_Socket_Data.htm - seems comprehensive
271  //
272 
273  // Decide on the basic SBS Message Type
274  if ((mm->msgtype == 4) || (mm->msgtype == 20)) {
275  msgType = 5;
276  } else if ((mm->msgtype == 5) || (mm->msgtype == 21)) {
277  msgType = 6;
278  } else if ((mm->msgtype == 0) || (mm->msgtype == 16)) {
279  msgType = 7;
280  } else if (mm->msgtype == 11) {
281  msgType = 8;
282  } else if ((mm->msgtype != 17) && (mm->msgtype != 18)) {
283  return;
284  } else if ((mm->metype >= 1) && (mm->metype <= 4)) {
285  msgType = 1;
286  } else if ((mm->metype >= 5) && (mm->metype <= 8)) {
288  {msgType = 2;}
289  else
290  {msgType = 7;}
291  } else if ((mm->metype >= 9) && (mm->metype <= 18)) {
293  {msgType = 3;}
294  else
295  {msgType = 7;}
296  } else if (mm->metype != 19) {
297  return;
298  } else if ((mm->mesub == 1) || (mm->mesub == 2)) {
299  msgType = 4;
300  } else {
301  return;
302  }
303 
304  // Fields 1 to 6 : SBS message type and ICAO address of the aircraft and some other stuff
305  p += sprintf(p, "MSG,%d,111,11111,%06X,111111,", msgType, mm->addr);
306 
307  // Fields 7 & 8 are the current time and date
308  if (mm->timestampMsg) { // Make sure the records' timestamp is valid before outputing it
309  epocTime = Modes.stSystemTimeBlk; // This is the time of the start of the Block we're processing
310  offset = (int) (mm->timestampMsg - Modes.timestampBlk); // This is the time (in 12Mhz ticks) into the Block
311  offset = offset / 12000; // convert to milliseconds
312  epocTime.millitm += offset; // add on the offset time to the Block start time
313  if (epocTime.millitm > 999) // if we've caused an overflow into the next second...
314  {epocTime.millitm -= 1000; epocTime.time ++;} // ..correct the overflow
315  stTime = *localtime(&epocTime.time); // convert the time to year, month day, hours, min, sec
316  p += sprintf(p, "%04d/%02d/%02d,", (stTime.tm_year+1900),(stTime.tm_mon+1), stTime.tm_mday);
317  p += sprintf(p, "%02d:%02d:%02d.%03d,", stTime.tm_hour, stTime.tm_min, stTime.tm_sec, epocTime.millitm);
318  } else {
319  p += sprintf(p, ",,");
320  }
321 
322  // Fields 9 & 10 are the current time and date
323  ftime(&epocTime); // get the current system time & date
324  stTime = *localtime(&epocTime.time); // convert the time to year, month day, hours, min, sec
325  p += sprintf(p, "%04d/%02d/%02d,", (stTime.tm_year+1900),(stTime.tm_mon+1), stTime.tm_mday);
326  p += sprintf(p, "%02d:%02d:%02d.%03d", stTime.tm_hour, stTime.tm_min, stTime.tm_sec, epocTime.millitm);
327 
328  // Field 11 is the callsign (if we have it)
329  if (mm->bFlags & MODES_ACFLAGS_CALLSIGN_VALID) {p += sprintf(p, ",%s", mm->flight);}
330  else {p += sprintf(p, ",");}
331 
332  // Field 12 is the altitude (if we have it) - force to zero if we're on the ground
334  p += sprintf(p, ",0");
335  } else if (mm->bFlags & MODES_ACFLAGS_ALTITUDE_VALID) {
336  p += sprintf(p, ",%d", mm->altitude);
337  } else {
338  p += sprintf(p, ",");
339  }
340 
341  // Field 13 and 14 are the ground Speed and Heading (if we have them)
342  if (mm->bFlags & MODES_ACFLAGS_NSEWSPD_VALID) {p += sprintf(p, ",%d,%d", mm->velocity, mm->heading);}
343  else {p += sprintf(p, ",,");}
344 
345  // Fields 15 and 16 are the Lat/Lon (if we have it)
346  if (mm->bFlags & MODES_ACFLAGS_LATLON_VALID) {p += sprintf(p, ",%1.5f,%1.5f", mm->fLat, mm->fLon);}
347  else {p += sprintf(p, ",,");}
348 
349  // Field 17 is the VerticalRate (if we have it)
350  if (mm->bFlags & MODES_ACFLAGS_VERTRATE_VALID) {p += sprintf(p, ",%d", mm->vert_rate);}
351  else {p += sprintf(p, ",");}
352 
353  // Field 18 is the Squawk (if we have it)
354  if (mm->bFlags & MODES_ACFLAGS_SQUAWK_VALID) {p += sprintf(p, ",%x", mm->modeA);}
355  else {p += sprintf(p, ",");}
356 
357  // Field 19 is the Squawk Changing Alert flag (if we have it)
358  if (mm->bFlags & MODES_ACFLAGS_FS_VALID) {
359  if ((mm->fs >= 2) && (mm->fs <= 4)) {
360  p += sprintf(p, ",-1");
361  } else {
362  p += sprintf(p, ",0");
363  }
364  } else {
365  p += sprintf(p, ",");
366  }
367 
368  // Field 20 is the Squawk Emergency flag (if we have it)
370  if ((mm->modeA == 0x7500) || (mm->modeA == 0x7600) || (mm->modeA == 0x7700)) {
371  p += sprintf(p, ",-1");
372  } else {
373  p += sprintf(p, ",0");
374  }
375  } else {
376  p += sprintf(p, ",");
377  }
378 
379  // Field 21 is the Squawk Ident flag (if we have it)
380  if (mm->bFlags & MODES_ACFLAGS_FS_VALID) {
381  if ((mm->fs >= 4) && (mm->fs <= 5)) {
382  p += sprintf(p, ",-1");
383  } else {
384  p += sprintf(p, ",0");
385  }
386  } else {
387  p += sprintf(p, ",");
388  }
389 
390  // Field 22 is the OnTheGround flag (if we have it)
391  if (mm->bFlags & MODES_ACFLAGS_AOG_VALID) {
392  if (mm->bFlags & MODES_ACFLAGS_AOG) {
393  p += sprintf(p, ",-1");
394  } else {
395  p += sprintf(p, ",0");
396  }
397  } else {
398  p += sprintf(p, ",");
399  }
400 
401  p += sprintf(p, "\r\n");
402  modesSendAllClients(Modes.sbsos, msg, p-msg);
403 }
404 //
405 //=========================================================================
406 //
408  if (Modes.stat_sbs_connections) {modesSendSBSOutput(mm);}
409  if (Modes.stat_beast_connections) {modesSendBeastOutput(mm);}
410  if (Modes.stat_raw_connections) {modesSendRawOutput(mm);}
411 }
412 //
413 //=========================================================================
414 //
415 // This function decodes a Beast binary format message
416 //
417 // The message is passed to the higher level layers, so it feeds
418 // the selected screen output, the network output and so forth.
419 //
420 // If the message looks invalid it is silently discarded.
421 //
422 // The function always returns 0 (success) to the caller as there is no
423 // case where we want broken messages here to close the client connection.
424 //
425 int decodeBinMessage(struct client *c, char *p) {
426  int msgLen = 0;
427  unsigned char msg[MODES_LONG_MSG_BYTES];
428  struct modesMessage mm;
429  MODES_NOTUSED(c);
430  memset(&mm, 0, sizeof(mm));
431 
432  if ((*p == '1') && (Modes.mode_ac)) { // skip ModeA/C unless user enables --modes-ac
433  msgLen = MODEAC_MSG_BYTES;
434  } else if (*p == '2') {
435  msgLen = MODES_SHORT_MSG_BYTES;
436  } else if (*p == '3') {
437  msgLen = MODES_LONG_MSG_BYTES;
438  }
439 
440  if (msgLen) {
441  // Mark messages received over the internet as remote so that we don't try to
442  // pass them off as being received by this instance when forwarding them
443  mm.remote = 1;
444  p += 7; // Skip the timestamp
445  mm.signalLevel = *p++; // Grab the signal level
446  memcpy(msg, p, msgLen); // and the data
447 
448  if (msgLen == MODEAC_MSG_BYTES) { // ModeA or ModeC
449  decodeModeAMessage(&mm, ((msg[0] << 8) | msg[1]));
450  } else {
451  decodeModesMessage(&mm, msg);
452  }
453 
454  useModesMessage(&mm);
455  }
456  return (0);
457 }
458 //
459 //=========================================================================
460 //
461 // Turn an hex digit into its 4 bit decimal value.
462 // Returns -1 if the digit is not in the 0-F range.
463 //
464 int hexDigitVal(int c) {
465  c = tolower(c);
466  if (c >= '0' && c <= '9') return c-'0';
467  else if (c >= 'a' && c <= 'f') return c-'a'+10;
468  else return -1;
469 }
470 //
471 //=========================================================================
472 //
473 // This function decodes a string representing message in raw hex format
474 // like: *8D4B969699155600E87406F5B69F; The string is null-terminated.
475 //
476 // The message is passed to the higher level layers, so it feeds
477 // the selected screen output, the network output and so forth.
478 //
479 // If the message looks invalid it is silently discarded.
480 //
481 // The function always returns 0 (success) to the caller as there is no
482 // case where we want broken messages here to close the client connection.
483 //
484 int decodeHexMessage(struct client *c, char *hex) {
485  int l = strlen(hex), j;
486  unsigned char msg[MODES_LONG_MSG_BYTES];
487  struct modesMessage mm;
488  MODES_NOTUSED(c);
489  memset(&mm, 0, sizeof(mm));
490 
491  // Mark messages received over the internet as remote so that we don't try to
492  // pass them off as being received by this instance when forwarding them
493  mm.remote = 1;
494  mm.signalLevel = 0xFF;
495 
496  // Remove spaces on the left and on the right
497  while(l && isspace(hex[l-1])) {
498  hex[l-1] = '\0'; l--;
499  }
500  while(isspace(*hex)) {
501  hex++; l--;
502  }
503 
504  // Turn the message into binary.
505  // Accept *-AVR raw @-AVR/BEAST timeS+raw %-AVR timeS+raw (CRC good) <-BEAST timeS+sigL+raw
506  // and some AVR records that we can understand
507  if (hex[l-1] != ';') {return (0);} // not complete - abort
508 
509  switch(hex[0]) {
510  case '<': {
511  mm.signalLevel = (hexDigitVal(hex[13])<<4) | hexDigitVal(hex[14]);
512  hex += 15; l -= 16; // Skip <, timestamp and siglevel, and ;
513  break;}
514 
515  case '@': // No CRC check
516  case '%': { // CRC is OK
517  hex += 13; l -= 14; // Skip @,%, and timestamp, and ;
518  break;}
519 
520  case '*':
521  case ':': {
522  hex++; l-=2; // Skip * and ;
523  break;}
524 
525  default: {
526  return (0); // We don't know what this is, so abort
527  break;}
528  }
529 
530  if ( (l != (MODEAC_MSG_BYTES * 2))
531  && (l != (MODES_SHORT_MSG_BYTES * 2))
532  && (l != (MODES_LONG_MSG_BYTES * 2)) )
533  {return (0);} // Too short or long message... broken
534 
535  if ( (0 == Modes.mode_ac)
536  && (l == (MODEAC_MSG_BYTES * 2)) )
537  {return (0);} // Right length for ModeA/C, but not enabled
538 
539  for (j = 0; j < l; j += 2) {
540  int high = hexDigitVal(hex[j]);
541  int low = hexDigitVal(hex[j+1]);
542 
543  if (high == -1 || low == -1) return 0;
544  msg[j/2] = (high << 4) | low;
545  }
546 
547  if (l == (MODEAC_MSG_BYTES * 2)) { // ModeA or ModeC
548  decodeModeAMessage(&mm, ((msg[0] << 8) | msg[1]));
549  } else { // Assume ModeS
550  decodeModesMessage(&mm, msg);
551  }
552 
553  useModesMessage(&mm);
554  return (0);
555 }
556 //
557 //=========================================================================
558 //
559 // Return a description of planes in json. No metric conversion
560 //
561 char *aircraftsToJson(int *len) {
562  time_t now = time(NULL);
563  struct aircraft *a = Modes.aircrafts;
564  int buflen = 1024; // The initial buffer is incremented as needed
565  char *buf = (char *) malloc(buflen), *p = buf;
566  int l;
567 
568  l = snprintf(p,buflen,"[\n");
569  p += l; buflen -= l;
570  while(a) {
571  int position = 0;
572  int track = 0;
573 
574  if (a->modeACflags & MODEAC_MSG_FLAG) { // skip any fudged ICAO records Mode A/C
575  a = a->next;
576  continue;
577  }
578 
580  position = 1;
581  }
582 
584  track = 1;
585  }
586 
587  // No metric conversion
588  l = snprintf(p,buflen,
589  "{\"hex\":\"%06x\", \"squawk\":\"%04x\", \"flight\":\"%s\", \"lat\":%f, "
590  "\"lon\":%f, \"validposition\":%d, \"altitude\":%d, \"vert_rate\":%d,\"track\":%d, \"validtrack\":%d,"
591  "\"speed\":%d, \"messages\":%ld, \"seen\":%d},\n",
592  a->addr, a->modeA, a->flight, a->lat, a->lon, position, a->altitude, a->vert_rate, a->track, track,
593  a->speed, a->messages, (int)(now - a->seen));
594  p += l; buflen -= l;
595 
596  //Resize if needed
597  if (buflen < 256) {
598  int used = p-buf;
599  buflen += 1024; // Our increment.
600  buf = (char *) realloc(buf,used+buflen);
601  p = buf+used;
602  }
603 
604  a = a->next;
605  }
606 
607  //Remove the final comma if any, and closes the json array.
608  if (*(p-2) == ',') {
609  *(p-2) = '\n';
610  p--;
611  buflen++;
612  }
613 
614  l = snprintf(p,buflen,"]\n");
615  p += l; buflen -= l;
616 
617  *len = p-buf;
618  return buf;
619 }
620 //
621 //=========================================================================
622 //
623 #define MODES_CONTENT_TYPE_HTML "text/html;charset=utf-8"
624 #define MODES_CONTENT_TYPE_CSS "text/css;charset=utf-8"
625 #define MODES_CONTENT_TYPE_JSON "application/json;charset=utf-8"
626 #define MODES_CONTENT_TYPE_JS "application/javascript;charset=utf-8"
627 //
628 // Get an HTTP request header and write the response to the client.
629 // gain here we assume that the socket buffer is enough without doing
630 // any kind of userspace buffering.
631 //
632 // Returns 1 on error to signal the caller the client connection should
633 // be closed.
634 //
635 int handleHTTPRequest(struct client *c, char *p) {
636  char hdr[512];
637  int clen, hdrlen;
638  int httpver, keepalive;
639  char *url, *content;
640  char ctype[48];
641  char getFile[1024];
642  char *ext;
643 
644  if (Modes.debug & MODES_DEBUG_NET)
645  printf("\nHTTP request: %s\n", c->buf);
646 
647  // Minimally parse the request.
648  httpver = (strstr(p, "HTTP/1.1") != NULL) ? 11 : 10;
649  if (httpver == 10) {
650  // HTTP 1.0 defaults to close, unless otherwise specified.
651  keepalive = strstr(p, "Connection: keep-alive") != NULL;
652  } else if (httpver == 11) {
653  // HTTP 1.1 defaults to keep-alive, unless close is specified.
654  keepalive = strstr(p, "Connection: close") == NULL;
655  }
656 
657  // Identify he URL.
658  p = strchr(p,' ');
659  if (!p) return 1; // There should be the method and a space
660  url = ++p; // Now this should point to the requested URL
661  p = strchr(p, ' ');
662  if (!p) return 1; // There should be a space before HTTP/
663  *p = '\0';
664 
665  if (Modes.debug & MODES_DEBUG_NET) {
666  printf("\nHTTP keep alive: %d\n", keepalive);
667  printf("HTTP requested URL: %s\n\n", url);
668  }
669 
670  if (strlen(url) < 2) {
671  snprintf(getFile, sizeof getFile, "%s/gmap.html", HTMLPATH); // Default file
672  } else {
673  snprintf(getFile, sizeof getFile, "%s/%s", HTMLPATH, url);
674  }
675 
676  // Select the content to send, we have just two so far:
677  // "/" -> Our google map application.
678  // "/data.json" -> Our ajax request to update planes.
679  if (strstr(url, "/data.json")) {
680  content = aircraftsToJson(&clen);
681  //snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_JSON);
682  } else {
683  struct stat sbuf;
684  int fd = -1;
685 
686  if (stat(getFile, &sbuf) != -1 && (fd = open(getFile, O_RDONLY)) != -1) {
687  content = (char *) malloc(sbuf.st_size);
688  if (read(fd, content, sbuf.st_size) == -1) {
689  snprintf(content, sbuf.st_size, "Error reading from file: %s", strerror(errno));
690  }
691  clen = sbuf.st_size;
692  } else {
693  char buf[128];
694  clen = snprintf(buf,sizeof(buf),"Error opening HTML file: %s", strerror(errno));
695  content = strdup(buf);
696  }
697 
698  if (fd != -1) {
699  close(fd);
700  }
701  }
702 
703  // Get file extension and content type
704  snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_HTML); // Default content type
705  ext = strrchr(getFile, '.');
706 
707  if (strlen(ext) > 0) {
708  if (strstr(ext, ".json")) {
709  snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_JSON);
710  } else if (strstr(ext, ".css")) {
711  snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_CSS);
712  } else if (strstr(ext, ".js")) {
713  snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_JS);
714  }
715  }
716 
717  // Create the header and send the reply
718  hdrlen = snprintf(hdr, sizeof(hdr),
719  "HTTP/1.1 200 OK\r\n"
720  "Server: Dump1090\r\n"
721  "Content-Type: %s\r\n"
722  "Connection: %s\r\n"
723  "Content-Length: %d\r\n"
724  "Cache-Control: no-cache, must-revalidate\r\n"
725  "Expires: Sat, 26 Jul 1997 05:00:00 GMT\r\n"
726  "\r\n",
727  ctype,
728  keepalive ? "keep-alive" : "close",
729  clen);
730 
731  if (Modes.debug & MODES_DEBUG_NET) {
732  printf("HTTP Reply header:\n%s", hdr);
733  }
734 
735  // Send header and content.
736  if (write(c->fd, hdr, hdrlen) == -1 || write(c->fd, content, clen) == -1) {
737  free(content);
738  return 1;
739  }
740  free(content);
741  Modes.stat_http_requests++;
742  return !keepalive;
743 }
744 //
745 //=========================================================================
746 //
747 // This function polls the clients using read() in order to receive new
748 // messages from the net.
749 //
750 // The message is supposed to be separated from the next message by the
751 // separator 'sep', which is a null-terminated C string.
752 //
753 // Every full message received is decoded and passed to the higher layers
754 // calling the function's 'handler'.
755 //
756 // The handler returns 0 on success, or 1 to signal this function we should
757 // close the connection with the client in case of non-recoverable errors.
758 //
759 void modesReadFromClient(struct client *c, char *sep,
760  int(*handler)(struct client *, char *)) {
761  int left;
762  int nread;
763  int fullmsg;
764  int bContinue = 1;
765  char *s, *e;
766 
767  while(bContinue) {
768 
769  fullmsg = 0;
770  left = MODES_CLIENT_BUF_SIZE - c->buflen;
771  // If our buffer is full discard it, this is some badly formatted shit
772  if (left <= 0) {
773  c->buflen = 0;
774  left = MODES_CLIENT_BUF_SIZE;
775  // If there is garbage, read more to discard it ASAP
776  }
777  nread = read(c->fd, c->buf+c->buflen, left);
778 
779  // If we didn't get all the data we asked for, then return once we've processed what we did get.
780  if (nread != left) {
781  bContinue = 0;
782  }
783  if ( (nread < 0) && (errno != EAGAIN)) { // Error, or end of file
784  modesFreeClient(c->fd);
785  }
786  if (nread <= 0) {
787  break; // Serve next client
788  }
789  c->buflen += nread;
790 
791  // Always null-term so we are free to use strstr() (it won't affect binary case)
792  c->buf[c->buflen] = '\0';
793 
794  e = s = c->buf; // Start with the start of buffer, first message
795 
796  if (c->service == Modes.bis) {
797  // This is the Beast Binary scanning case.
798  // If there is a complete message still in the buffer, there must be the separator 'sep'
799  // in the buffer, note that we full-scan the buffer at every read for simplicity.
800 
801  left = c->buflen; // Length of valid search for memchr()
802  while (left && ((s = memchr(e, (char) 0x1a, left)) != NULL)) { // The first byte of buffer 'should' be 0x1a
803  s++; // skip the 0x1a
804  if (*s == '1') {
805  e = s + MODEAC_MSG_BYTES + 8; // point past remainder of message
806  } else if (*s == '2') {
807  e = s + MODES_SHORT_MSG_BYTES + 8;
808  } else if (*s == '3') {
809  e = s + MODES_LONG_MSG_BYTES + 8;
810  } else {
811  e = s; // Not a valid beast message, skip
812  left = &(c->buf[c->buflen]) - e;
813  continue;
814  }
815  left = &(c->buf[c->buflen]) - e;
816  if (left < 0) { // Incomplete message in buffer
817  e = s - 1; // point back at last found 0x1a.
818  break;
819  }
820  // Have a 0x1a followed by 1, 2 or 3 - pass message less 0x1a to handler.
821  if (handler(c, s)) {
822  modesFreeClient(c->fd);
823  return;
824  }
825  fullmsg = 1;
826  }
827  s = e; // For the buffer remainder below
828 
829  } else {
830  //
831  // This is the ASCII scanning case, AVR RAW or HTTP at present
832  // If there is a complete message still in the buffer, there must be the separator 'sep'
833  // in the buffer, note that we full-scan the buffer at every read for simplicity.
834  //
835  while ((e = strstr(s, sep)) != NULL) { // end of first message if found
836  *e = '\0'; // The handler expects null terminated strings
837  if (handler(c, s)) { // Pass message to handler.
838  modesFreeClient(c->fd); // Handler returns 1 on error to signal we .
839  return; // should close the client connection
840  }
841  s = e + strlen(sep); // Move to start of next message
842  fullmsg = 1;
843  }
844  }
845 
846  if (fullmsg) { // We processed something - so
847  c->buflen = &(c->buf[c->buflen]) - s; // Update the unprocessed buffer length
848  memmove(c->buf, s, c->buflen); // Move what's remaining to the start of the buffer
849  } else { // If no message was decoded process the next client
850  break;
851  }
852  }
853 }
854 //
855 //=========================================================================
856 //
857 // Read data from clients. This function actually delegates a lower-level
858 // function that depends on the kind of service (raw, http, ...).
859 //
861  int j;
862  struct client *c;
863 
865 
866  for (j = 0; j <= Modes.maxfd; j++) {
867  if ((c = Modes.clients[j]) == NULL) continue;
868  if (c->service == Modes.ris)
870  else if (c->service == Modes.bis)
872  else if (c->service == Modes.https)
874  }
875 }
876 //
877 // =============================== Network IO ===========================
878 //
#define MODES_CONTENT_TYPE_HTML
Definition: net_io.c:623
long messages
Definition: dump1090.h:204
int anetTcpServer(char *err, int port, char *bindaddr)
Definition: anet.c:275
#define MODES_ACFLAGS_NSEWSPD_VALID
Definition: dump1090.h:141
int modeA
Definition: dump1090.h:205
#define MODES_DEBUG_NET
Definition: dump1090.h:153
constexpr double mm
Definition: AugerUnits.h:113
void decodeModesMessage(struct modesMessage *mm, unsigned char *msg)
Definition: mode_s.c:819
char buf[1024+1]
Definition: dump1090.h:188
#define MODES_ACFLAGS_ALTITUDE_VALID
Definition: dump1090.h:128
int track
Definition: dump1090.h:198
uint32_t addr
Definition: dump1090.h:193
int fd
Definition: dump1090.h:185
int altitude
Definition: dump1090.h:196
char flight[16]
Definition: dump1090.h:194
void modesQueueOutput(struct modesMessage *mm)
Definition: net_io.c:407
#define MODES_CONTENT_TYPE_JSON
Definition: net_io.c:625
uint32_t addr
Definition: dump1090.h:353
int decodeBinMessage(struct client *c, char *p)
Definition: net_io.c:425
#define MODES_CLIENT_BUF_SIZE
Definition: dump1090.h:172
int vert_rate
Definition: dump1090.h:374
#define MODES_ACFLAGS_FS_VALID
Definition: dump1090.h:140
void modesSendBeastOutput(struct modesMessage *mm)
Definition: net_io.c:184
char flight[16]
Definition: dump1090.h:371
void decodeModeAMessage(struct modesMessage *mm, int ModeA)
Definition: mode_ac.c:359
int exit
Definition: dump1090.h:237
uint64_t timestampMsg
Definition: dump1090.h:355
void modesReadFromClient(struct client *c, char *sep, int(*handler)(struct client *, char *))
Definition: net_io.c:759
int modeACflags
Definition: dump1090.h:209
int service
Definition: dump1090.h:186
#define MODES_ACFLAGS_AOG
Definition: dump1090.h:136
const double high[npar]
Definition: UnivRec.h:78
int decodeHexMessage(struct client *c, char *hex)
Definition: net_io.c:484
unsigned char signalLevel
Definition: dump1090.h:357
int fd
Definition: dump1090.h:233
void modesAcceptClients(void)
Definition: net_io.c:86
#define MODES_LONG_MSG_BYTES
Definition: dump1090.h:107
double fLon
Definition: dump1090.h:370
constexpr double s
Definition: AugerUnits.h:163
double fLat
Definition: dump1090.h:369
struct aircraft * next
Definition: dump1090.h:220
void modesReadFromClients(void)
Definition: net_io.c:860
int anetSetSendBuffer(char *err, int fd, int buffsize)
Definition: anet.c:87
#define MODES_ACFLAGS_SQUAWK_VALID
Definition: dump1090.h:132
struct @0 Modes
char * aircraftsToJson(int *len)
Definition: net_io.c:561
#define MODES_ACFLAGS_HEADING_VALID
Definition: dump1090.h:129
int anetNonBlock(char *err, int fd)
Definition: anet.c:58
void modesFreeClient(int fd)
Definition: net_io.c:132
int hexDigitVal(int c)
Definition: net_io.c:464
#define MODES_CONTENT_TYPE_CSS
Definition: net_io.c:624
int vert_rate
Definition: dump1090.h:199
void useModesMessage(struct modesMessage *mm)
Definition: mode_s.c:1838
#define MODES_ACFLAGS_LATLON_VALID
Definition: dump1090.h:127
void modesSendAllClients(int service, void *msg, int len)
Definition: net_io.c:165
void modesInitNet(void)
Definition: net_io.c:49
void modesSendRawOutput(struct modesMessage *mm)
Definition: net_io.c:222
#define MODES_NET_MAX_FD
Definition: dump1090.h:165
#define HTMLPATH
Definition: dump1090.h:176
int bFlags
Definition: dump1090.h:219
const double low[npar]
Definition: UnivRec.h:77
double lon
Definition: dump1090.h:218
#define MODEAC_MSG_BYTES
Definition: dump1090.h:95
int velocity
Definition: dump1090.h:375
unsigned char msg[14]
Definition: dump1090.h:346
double lat
Definition: dump1090.h:218
#define MODES_ACFLAGS_VERTRATE_VALID
Definition: dump1090.h:131
#define MODEAC_MSG_FLAG
Definition: dump1090.h:97
#define MODES_NET_SNDBUF_SIZE
Definition: dump1090.h:173
time_t seen
Definition: dump1090.h:200
#define MODES_ACFLAGS_AOG_VALID
Definition: dump1090.h:139
void modesSendSBSOutput(struct modesMessage *mm)
Definition: net_io.c:261
int altitude
Definition: dump1090.h:382
#define MODES_ACFLAGS_CALLSIGN_VALID
Definition: dump1090.h:133
int anetTcpAccept(char *err, int s, char *ip, int *port)
Definition: anet.c:332
int buflen
Definition: dump1090.h:187
#define MODES_NOTUSED(V)
Definition: dump1090.h:179
#define MODES_SHORT_MSG_BYTES
Definition: dump1090.h:108
int speed
Definition: dump1090.h:197
int handleHTTPRequest(struct client *c, char *p)
Definition: net_io.c:635
#define MODES_ACFLAGS_AOG_GROUND
Definition: dump1090.h:146
#define MODES_CONTENT_TYPE_JS
Definition: net_io.c:626

, generated on Tue Sep 26 2023.