[hamradio-commits] [dump1090] 217/373: VK1ET : Numerous changes to Port handling

Matthew Ernisse mernisse-guest at moszumanska.debian.org
Thu Oct 23 14:58:21 UTC 2014


This is an automated email from the git hooks/post-receive script.

mernisse-guest pushed a commit to branch backport
in repository dump1090.

commit e86eb3921e135f62a35cc852fcd375f3d0fff7ce
Author: Malcolm Robb <Support at ATTAvionics.com>
Date:   Fri May 24 22:29:00 2013 +0100

    VK1ET : Numerous changes to Port handling
    
    Changes based on ideas from John VK1ET. His commit notes are as follows
    :
    
    1. Change input socket handling to avoid unnecessary memmove (use
    pointers instead)
    
    2. Add ability to read and decode binary beast format TCP.
    
    3. Change output socket handling same as sbs_output - only call output
    handler if there is a current client connected use separate ports for
    beast in and out - no need for --net-beast flag. Will input/output
    format defined by socket connected to. avr raw, beast binary and sbs can
    be handled simultaneously.
    
    4. Some comments changes, filtering of ModeAC to json,.
---
 dump1090.c | 397 ++++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 260 insertions(+), 137 deletions(-)

diff --git a/dump1090.c b/dump1090.c
index 30b87f0..d758cef 100644
--- a/dump1090.c
+++ b/dump1090.c
@@ -56,7 +56,7 @@
 // MinorVer changes when additional features are added, but not for bug fixes (range 00-99)
 // DayDate & Year changes for all changes, including for bug fixes. It represent the release date of the update
 //
-#define MODES_DUMP1090_VERSION     "1.06.2305.13"
+#define MODES_DUMP1090_VERSION     "1.07.2305.13"
 #define MODES_USER_LATITUDE_DFLT   (0.0)
 #define MODES_USER_LONGITUDE_DFLT  (0.0)
 
@@ -146,11 +146,13 @@
 #define MODES_INTERACTIVE_TTL 60                /* TTL before being removed */
 
 #define MODES_NET_MAX_FD 1024
-#define MODES_NET_OUTPUT_SBS_PORT 30003
-#define MODES_NET_OUTPUT_RAW_PORT 30002
-#define MODES_NET_INPUT_RAW_PORT 30001
-#define MODES_NET_HTTP_PORT 8080
-#define MODES_CLIENT_BUF_SIZE 1024
+#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_CLIENT_BUF_SIZE  1024
 #define MODES_NET_SNDBUF_SIZE (1024*64)
 
 #ifndef HTMLPATH
@@ -229,9 +231,13 @@ struct {
     int sbsos;                      /* SBS output listening socket. */
     int ros;                        /* Raw output listening socket. */
     int ris;                        /* Raw input listening socket. */
+    int bos;                        /* Beast output listening socket */
+    int bis;                        /* Beast input listening socket */
     int https;                      /* HTTP listening socket. */
     char * rawOut;                  /* Buffer for building raw output data */
     int rawOutUsed;                 /* How much if the buffer is currently used */
+    char *beastOut;                 /* Buffer for building beast output data */
+    int beastOutUsed;               /* How much if the buffer is currently used */
 
     /* Configuration */
     char *filename;                 /* Input form file, --ifile option. */
@@ -250,6 +256,8 @@ struct {
     int net_output_raw_rate_count;  /* Rate (in 64mS increments) of output raw data */     
     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 */
     int net_http_port;              /* HTTP port. */
     int quiet;                      /* Suppress stdout */
     int interactive;                /* Interactive mode */
@@ -286,6 +294,8 @@ struct {
 							
     unsigned int stat_http_requests;
     unsigned int stat_sbs_connections;
+    unsigned int stat_raw_connections;
+    unsigned int stat_beast_connections;
     unsigned int stat_out_of_phase;
     unsigned int stat_ph_demodulated0;
     unsigned int stat_ph_demodulated1;
@@ -316,6 +326,7 @@ struct modesMessage {
     uint32_t      addr;                           // ICAO Address from bytes 1 2 and 3
     int           phase_corrected;                // True if phase correction was applied
     uint64_t      timestampMsg;                   // Timestamp of the message
+    int           remote;                         // If set this message is from a remote station
     unsigned char signalLevel;                    // Signal Amplitude
 
     // DF 11
@@ -353,7 +364,7 @@ void modesSendRawOutput(struct modesMessage *mm);
 void modesSendBeastOutput(struct modesMessage *mm);
 void modesSendSBSOutput(struct modesMessage *mm);
 void useModesMessage(struct modesMessage *mm);
-int fixBitErrors(unsigned char *msg, int bits, int maxfixable, int *bitpos);
+int fixBitErrors(unsigned char *msg, int bits, int maxfix, char *fixedbits);
 int fixSingleBitErrors(unsigned char *msg, int bits);
 int fixTwoBitsErrors(unsigned char *msg, int bits);
 void modesInitErrorInfo();
@@ -384,17 +395,19 @@ void modesInitConfig(void) {
     memset(&Modes, 0, sizeof(Modes));
 
     // Now initialise things that should not be 0/NULL to their defaults
-    Modes.gain                = MODES_MAX_GAIN;
-    Modes.freq                = MODES_DEFAULT_FREQ;
-    Modes.check_crc           = 1;
-    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_http_port       = MODES_NET_HTTP_PORT;
-    Modes.interactive_rows    = MODES_INTERACTIVE_ROWS;
-    Modes.interactive_ttl     = MODES_INTERACTIVE_TTL;
-    Modes.fUserLat            = MODES_USER_LATITUDE_DFLT;
-    Modes.fUserLon            = MODES_USER_LONGITUDE_DFLT;
+    Modes.gain                  = MODES_MAX_GAIN;
+    Modes.freq                  = MODES_DEFAULT_FREQ;
+    Modes.check_crc             = 1;
+    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.interactive_rows      = MODES_INTERACTIVE_ROWS;
+    Modes.interactive_ttl       = MODES_INTERACTIVE_TTL;
+    Modes.fUserLat              = MODES_USER_LATITUDE_DFLT;
+    Modes.fUserLon              = MODES_USER_LONGITUDE_DFLT;
 }
 
 void modesInit(void) {
@@ -408,6 +421,7 @@ void modesInit(void) {
          ((Modes.data       = (uint16_t *) malloc(MODES_ASYNC_BUF_SIZE)                                         ) == NULL) ||
          ((Modes.magnitude  = (uint16_t *) malloc(MODES_ASYNC_BUF_SIZE+MODES_PREAMBLE_SIZE+MODES_LONG_MSG_SIZE) ) == NULL) ||
          ((Modes.maglut     = (uint16_t *) malloc(sizeof(uint16_t) * 256 * 256)                                 ) == NULL) ||
+         ((Modes.beastOut   = (char     *) malloc(MODES_RAWOUT_BUF_SIZE)                                        ) == NULL) ||
          ((Modes.rawOut     = (char     *) malloc(MODES_RAWOUT_BUF_SIZE)                                        ) == NULL) ) 
     {
         fprintf(stderr, "Out of memory allocating data buffer.\n");
@@ -2649,13 +2663,19 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
     }
 
     //Send any remaining partial raw buffers now
-    if (Modes.rawOutUsed)
+    if (Modes.rawOutUsed || Modes.beastOutUsed)
       {
       Modes.net_output_raw_rate_count++;
       if (Modes.net_output_raw_rate_count > Modes.net_output_raw_rate)
         {
-        modesSendAllClients(Modes.ros, Modes.rawOut, Modes.rawOutUsed);
-        Modes.rawOutUsed = 0;
+        if (Modes.rawOutUsed) {
+            modesSendAllClients(Modes.ros, Modes.rawOut, Modes.rawOutUsed);
+            Modes.rawOutUsed = 0;
+        }
+        if (Modes.beastOutUsed) {
+            modesSendAllClients(Modes.bos, Modes.beastOut, Modes.beastOutUsed);
+            Modes.beastOutUsed = 0;
+        }
         Modes.net_output_raw_rate_count = 0;
         }
       }
@@ -2684,19 +2704,10 @@ void useModesMessage(struct modesMessage *mm) {
             displayModesMessage(mm);
         }
 
-        // Feed SBS output clients
-        if (Modes.stat_sbs_connections) {
-            modesSendSBSOutput(mm);
-        }
-
-        // Send data to connected network clients
-        if (Modes.net) {
-            if (Modes.beast) {
-                modesSendBeastOutput(mm);
-            } else {
-                modesSendRawOutput(mm);
-            }
-        }
+        // Feed output clients
+        if (Modes.stat_sbs_connections)   {modesSendSBSOutput(mm);}
+        if (Modes.stat_beast_connections) {modesSendBeastOutput(mm);}
+        if (Modes.stat_raw_connections)   {modesSendRawOutput(mm);}
     }
 }
 
@@ -3346,9 +3357,11 @@ void modesInitNet(void) {
         char *descr;
         int *socket;
         int port;
-    } services[4] = {
+    } services[6] = {
         {"Raw TCP output", &Modes.ros, Modes.net_output_raw_port},
         {"Raw TCP input", &Modes.ris, Modes.net_input_raw_port},
+        {"Beast TCP output", &Modes.bos, Modes.net_output_beast_port},
+        {"Beast TCP input", &Modes.bis, Modes.net_input_beast_port},
         {"HTTP server", &Modes.https, Modes.net_http_port},
         {"Basestation TCP output", &Modes.sbsos, Modes.net_output_sbs_port}
     };
@@ -3357,7 +3370,7 @@ void modesInitNet(void) {
     memset(Modes.clients,0,sizeof(Modes.clients));
     Modes.maxfd = -1;
 
-    for (j = 0; j < 4; j++) {
+    for (j = 0; j < 6; j++) {
         int s = anetTcpServer(Modes.aneterr, services[j].port, NULL);
         if (s == -1) {
             fprintf(stderr, "Error opening the listening port %d (%s): %s\n",
@@ -3378,12 +3391,14 @@ void modesAcceptClients(void) {
     int fd, port;
     unsigned int j;
     struct client *c;
-    int services[4];
+    int services[6];
 
     services[0] = Modes.ros;
     services[1] = Modes.ris;
-    services[2] = Modes.https;
-    services[3] = Modes.sbsos;
+    services[2] = Modes.bos;
+    services[3] = Modes.bis;
+    services[4] = Modes.https;
+    services[5] = Modes.sbsos;
 
     for (j = 0; j < sizeof(services)/sizeof(int); j++) {
         fd = anetTcpAccept(Modes.aneterr, services[j], NULL, &port);
@@ -3404,6 +3419,8 @@ void modesAcceptClients(void) {
 
         if (Modes.maxfd < fd) Modes.maxfd = fd;
         if (services[j] == Modes.sbsos) Modes.stat_sbs_connections++;
+        if (services[j] == Modes.ros)   Modes.stat_raw_connections++;
+        if (services[j] == Modes.bos)   Modes.stat_beast_connections++;
 
         j--; /* Try again with the same listening port. */
 
@@ -3415,6 +3432,15 @@ void modesAcceptClients(void) {
 /* On error free the client, collect the structure, adjust maxfd if needed. */
 void modesFreeClient(int fd) {
     close(fd);
+    if (Modes.clients[fd]->service == Modes.sbsos) {
+        if (Modes.stat_sbs_connections) Modes.stat_sbs_connections--;
+    }
+    else if (Modes.clients[fd]->service == Modes.ros) {
+        if (Modes.stat_raw_connections) Modes.stat_raw_connections--;
+    }
+    else if (Modes.clients[fd]->service == Modes.bos) {
+        if (Modes.stat_beast_connections) Modes.stat_beast_connections--;
+    }
     free(Modes.clients[fd]);
     Modes.clients[fd] = NULL;
 
@@ -3451,7 +3477,7 @@ void modesSendAllClients(int service, void *msg, int len) {
 
 /* Write raw output in Beast Binary format with Timestamp to TCP clients */
 void modesSendBeastOutput(struct modesMessage *mm) {
-    char *p = &Modes.rawOut[Modes.rawOutUsed];
+    char *p = &Modes.beastOut[Modes.beastOutUsed];
     int  msgLen = mm->msgbits / 8;
     char * pTimeStamp;
     int  j;
@@ -3475,11 +3501,11 @@ void modesSendBeastOutput(struct modesMessage *mm) {
 
     memcpy(p, mm->msg, msgLen);
 
-    Modes.rawOutUsed += (msgLen + 9);
-    if (Modes.rawOutUsed >= Modes.net_output_raw_size)
+    Modes.beastOutUsed += (msgLen + 9);
+    if (Modes.beastOutUsed >= Modes.net_output_raw_size)
       {
-      modesSendAllClients(Modes.ros, Modes.rawOut, Modes.rawOutUsed);
-      Modes.rawOutUsed = 0;
+      modesSendAllClients(Modes.bos, Modes.beastOut, Modes.beastOutUsed);
+      Modes.beastOutUsed = 0;
       Modes.net_output_raw_rate_count = 0;
       }
 }
@@ -3665,42 +3691,80 @@ void modesSendSBSOutput(struct modesMessage *mm) {
     p += sprintf(p, "\r\n");
     modesSendAllClients(Modes.sbsos, msg, p-msg);
 }
+//
+// This function decodes a Beast binary format message
+// 
+// The message is passed to the higher level layers, so it feeds
+// the selected screen output, the network output and so forth.
+// 
+// If the message looks invalid it is silently discarded.
+//
+// The function always returns 0 (success) to the caller as there is no 
+// case where we want broken messages here to close the client connection.
+int decodeBinMessage(struct client *c, char *p) {
+    int msgLen = 0;
+    unsigned char msg[MODES_LONG_MSG_BYTES];
+    struct modesMessage mm;
+    MODES_NOTUSED(c);
+    memset(&mm, 0, sizeof(mm));
 
-/* Turn an hex digit into its 4 bit decimal value.
- * Returns -1 if the digit is not in the 0-F range. */
+    if ((*p == '1') && (Modes.mode_ac)) { // skip ModeA/C unless user enables --modes-ac
+        msgLen = MODEAC_MSG_BYTES;
+    } else if (*p == '2') {
+        msgLen = MODES_SHORT_MSG_BYTES;
+    } else if (*p == '3') {
+        msgLen = MODES_LONG_MSG_BYTES;
+    }
+
+    if (msgLen) {
+        // Mark messages received over the internet as remote so that we don't try to
+        // pass them off as being received by this instance when forwarding them
+        mm.remote      =    1;
+        p += 7;                 // Skip the timestamp       
+        mm.signalLevel = *p++;  // Grab the signal level
+        memcpy(msg, p, msgLen); // and the data
+
+        if (msgLen == MODEAC_MSG_BYTES) { // ModeA or ModeC
+            decodeModeAMessage(&mm, ((msg[0] << 8) | msg[1])); 
+        } else {
+            decodeModesMessage(&mm, msg);
+        }
+    
+        useModesMessage(&mm);
+    }
+    return (0);
+}
+//
+// Turn an hex digit into its 4 bit decimal value.
+// Returns -1 if the digit is not in the 0-F range.
 int hexDigitVal(int c) {
     c = tolower(c);
     if (c >= '0' && c <= '9') return c-'0';
     else if (c >= 'a' && c <= 'f') return c-'a'+10;
     else return -1;
 }
-
-/* This function decodes a string representing a Mode S message in
- * raw hex format like: *8D4B969699155600E87406F5B69F;
- * The string is supposed to be at the start of the client buffer
- * and null-terminated.
- * 
- * The message is passed to the higher level layers, so it feeds
- * the selected screen output, the network output and so forth.
- * 
- * If the message looks invalid is silently discarded.
- *
- * The function always returns 0 (success) to the caller as there is
- * no case where we want broken messages here to close the client
- * connection. */
-int decodeHexMessage(struct client *c) {
-    char *hex = c->buf;
+//
+// This function decodes a string representing message in raw hex format
+// like: *8D4B969699155600E87406F5B69F; The string is null-terminated.
+// 
+// The message is passed to the higher level layers, so it feeds
+// the selected screen output, the network output and so forth.
+// 
+// If the message looks invalid it is silently discarded.
+//
+// The function always returns 0 (success) to the caller as there is no 
+// case where we want broken messages here to close the client connection.
+int decodeHexMessage(struct client *c, char *hex) {
     int l = strlen(hex), j;
     unsigned char msg[MODES_LONG_MSG_BYTES];
     struct modesMessage mm;
+    MODES_NOTUSED(c);
     memset(&mm, 0, sizeof(mm));
 
-    // Always mark the timestamp as invalid for packets received over the internet
-    // Mixing of data from two or more different receivers and publishing
-    // as coming from one would lead to corrupt mlat data
-    // Non timemarked internet data has indeterminate delay
-    mm.timestampMsg =  0;
-    mm.signalLevel  = -1;
+    // Mark messages received over the internet as remote so that we don't try to
+    // pass them off as being received by this instance when forwarding them
+    mm.remote      =    1;
+    mm.signalLevel = 0xFF;
 
     // Remove spaces on the left and on the right
     while(l && isspace(hex[l-1])) {
@@ -3736,7 +3800,15 @@ int decodeHexMessage(struct client *c) {
             break;}
     }
 
-    if ( (l < 4) || (l > MODES_LONG_MSG_BYTES*2) ) return (0); // Too short or long message... broken
+    if ( (l != (MODEAC_MSG_BYTES      * 2)) 
+      && (l != (MODES_SHORT_MSG_BYTES * 2)) 
+      && (l != (MODES_LONG_MSG_BYTES  * 2)) )
+        {return (0);} // Too short or long message... broken
+
+    if ( (0 == Modes.mode_ac) 
+      && (l == (MODEAC_MSG_BYTES * 2)) ) 
+        {return (0);} // Right length for ModeA/C, but not enabled
+
     for (j = 0; j < l; j += 2) {
         int high = hexDigitVal(hex[j]);
         int low  = hexDigitVal(hex[j+1]);
@@ -3745,8 +3817,11 @@ int decodeHexMessage(struct client *c) {
         msg[j/2] = (high << 4) | low;
     }
 
-    if (l < 5) {decodeModeAMessage(&mm, ((msg[0] << 8) | msg[1]));} // ModeA or ModeC
-    else       {decodeModesMessage(&mm, msg);}
+    if (l == (MODEAC_MSG_BYTES * 2)) {  // ModeA or ModeC
+        decodeModeAMessage(&mm, ((msg[0] << 8) | msg[1]));
+    } else {       // Assume ModeS
+        decodeModesMessage(&mm, msg);
+    }
 
     useModesMessage(&mm);
     return (0);
@@ -3766,6 +3841,11 @@ char *aircraftsToJson(int *len) {
         int altitude = a->altitude, speed = a->speed;
         int position = 0;
         int track = 0;
+
+        if (a->modeACflags & MODEAC_MSG_FLAG) { // skip any fudged ICAO records Mode A/C
+            a = a->next;
+            continue;
+        }
         
         /* Convert units to metric if --metric was specified. */
         if (Modes.metric) {
@@ -3823,11 +3903,11 @@ char *aircraftsToJson(int *len) {
  *
  * Returns 1 on error to signal the caller the client connection should
  * be closed. */
-int handleHTTPRequest(struct client *c) {
+int handleHTTPRequest(struct client *c, char *p) {
     char hdr[512];
     int clen, hdrlen;
     int httpver, keepalive;
-    char *p, *url, *content;
+    char *url, *content;
     char ctype[48];
     char getFile[1024];
     char *ext;
@@ -3836,17 +3916,17 @@ int handleHTTPRequest(struct client *c) {
         printf("\nHTTP request: %s\n", c->buf);
 
     // Minimally parse the request.
-    httpver = (strstr(c->buf, "HTTP/1.1") != NULL) ? 11 : 10;
+    httpver = (strstr(p, "HTTP/1.1") != NULL) ? 11 : 10;
     if (httpver == 10) {
         // HTTP 1.0 defaults to close, unless otherwise specified.
-        keepalive = strstr(c->buf, "Connection: keep-alive") != NULL;
+        keepalive = strstr(p, "Connection: keep-alive") != NULL;
     } else if (httpver == 11) {
         // HTTP 1.1 defaults to keep-alive, unless close is specified.
-        keepalive = strstr(c->buf, "Connection: close") == NULL;
+        keepalive = strstr(p, "Connection: close") == NULL;
     }
 
     // Identify he URL.
-    p = strchr(c->buf,' ');
+    p = strchr(p,' ');
     if (!p) return 1; /* There should be the method and a space... */
     url = ++p; /* Now this should point to the requested URL. */
     p = strchr(p, ' ');
@@ -3930,77 +4010,110 @@ int handleHTTPRequest(struct client *c) {
     Modes.stat_http_requests++;
     return !keepalive;
 }
-
-/* This function polls the clients using read() in order to receive new
- * messages from the net.
- *
- * The message is supposed to be separated by the next message by the
- * separator 'sep', that is a null-terminated C string.
- *
- * Every full message received is decoded and passed to the higher layers
- * calling the function 'handler'.
- *
- * The handelr returns 0 on success, or 1 to signal this function we
- * should close the connection with the client in case of non-recoverable
- * errors. */
+//
+// This function polls the clients using read() in order to receive new
+// messages from the net.
+//
+// The message is supposed to be separated from the next message by the
+// separator 'sep', which is a null-terminated C string.
+//
+// Every full message received is decoded and passed to the higher layers
+// calling the function's 'handler'.
+//
+// The handler returns 0 on success, or 1 to signal this function we should
+// close the connection with the client in case of non-recoverable errors.
 void modesReadFromClient(struct client *c, char *sep,
-                         int(*handler)(struct client *))
-{
+                         int(*handler)(struct client *, char *)) {
+    int left;
+    int nread;
+    int fullmsg;
+    char *s, *e;
+
     while(1) {
-        int left = MODES_CLIENT_BUF_SIZE - c->buflen;
-        int nread = read(c->fd, c->buf+c->buflen, left);
-        int fullmsg = 0;
-        int i;
-        char *p;
+
+        fullmsg = 0;
+        left = MODES_CLIENT_BUF_SIZE - c->buflen;
+        // If our buffer is full discard it, this is some badly formatted shit
+        if (left == 0) {
+            c->buflen = 0;
+            left = MODES_CLIENT_BUF_SIZE;
+            // If there is garbage, read more to discard it ASAP
+        }
+        nread = read(c->fd, c->buf+c->buflen, left);
 
         if (nread <= 0) {
-            if (nread == 0 || errno != EAGAIN) {
-                /* Error, or end of file. */
+            if (nread == 0 || errno != EAGAIN) { // Error, or end of file
                 modesFreeClient(c->fd);
             }
-            break; /* Serve next client. */
+            break; // Serve next client
         }
         c->buflen += nread;
 
-        /* Always null-term so we are free to use strstr() */
+        // Always null-term so we are free to use strstr() (it won't affect binary case)
         c->buf[c->buflen] = '\0';
 
-        /* If there is a complete message there must be the separator 'sep'
-         * in the buffer, note that we full-scan the buffer at every read
-         * for simplicity. */
-        while ((p = strstr(c->buf, sep)) != NULL) {
-            i = p - c->buf; /* Turn it as an index inside the buffer. */
-            c->buf[i] = '\0'; /* Te handler expects null terminated strings. */
-            /* Call the function to process the message. It returns 1
-             * on error to signal we should close the client connection. */
-            if (handler(c)) {
-                modesFreeClient(c->fd);
-                return;
+        e = s = c->buf;                                // Start with the start of buffer, first message
+
+        if (c->service == Modes.bis) {
+            // This is the Bease Binary scanning case.
+            // If there is a complete message still in the buffer, there must be the separator 'sep'
+            // in the buffer, note that we full-scan the buffer at every read for simplicity.
+
+            left = c->buflen;                                  // Length of valid search for memchr()
+            while (left && ((s = memchr(e, (char) 0x1a, left)) != NULL)) {    // In reality the first byte of buffer 'should' be 0x1a
+                s++;                                           // skip the 0x1a
+                if        (*s == '1') {
+                    e = s + MODEAC_MSG_BYTES      + 8;         // point past remainder of message
+                } else if (*s == '2') {
+                    e = s + MODES_SHORT_MSG_BYTES + 8;
+                } else if (*s == '3') {
+                    e = s + MODES_LONG_MSG_BYTES  + 8;
+                } else {
+                    e = s;                                     // Not a valid beast message, skip
+                    left = &(c->buf[c->buflen]) - e;
+                    continue;
+                }
+                left = &(c->buf[c->buflen]) - e;
+                if (left < 0) {                                // Incomplete message in buffer
+                    e = s - 1;                                 // point back at last found 0x1a.
+                    break;
+                }
+                // Have a 0x1a followed by 1, 2 or 3 - pass message less 0x1a to handler.
+                if (handler(c, s)) {
+                    modesFreeClient(c->fd);          
+                    return;
+                }
+                fullmsg = 1;
+            }
+            s = e;     // For the buffer remainder below
+
+        } else {
+            // This is the ASCII scanning case, AVR RAW or HTTP at present
+            // If there is a complete message still in the buffer, there must be the separator 'sep'
+            // in the buffer, note that we full-scan the buffer at every read for simplicity.
+
+            while ((e = strstr(s, sep)) != NULL) { // end of first message if found
+                *e = '\0';                         // The handler expects null terminated strings
+                if (handler(c, s)) {               // Pass message to handler. 
+                    modesFreeClient(c->fd);        // Handler returns 1 on error to signal we .
+                    return;                        // should close the client connection
+                }
+                s = e + strlen(sep);               // Move to start of next message
+                fullmsg = 1;
             }
-            /* Move what's left at the start of the buffer. */
-            i += strlen(sep); /* The separator is part of the previous msg. */
-            memmove(c->buf,c->buf+i,c->buflen-i);
-            c->buflen -= i;
-            c->buf[c->buflen] = '\0';
-            /* Maybe there are more messages inside the buffer.
-             * Start looping from the start again. */
-            fullmsg = 1;
         }
-        /* If our buffer is full discard it, this is some badly
-         * formatted shit. */
-        if (c->buflen == MODES_CLIENT_BUF_SIZE) {
-            c->buflen = 0;
-            /* If there is garbage, read more to discard it ASAP. */
-            continue;
+        
+        if (fullmsg) { // We processed something - so 
+            c->buflen = &(c->buf[c->buflen]) - s;  // The unprocessed buffer length
+            memmove(c->buf, s, c->buflen);         // move what's remaining to the start of the buffer
+        } else { // If no message was decoded process the next client
+            break;
         }
-        /* If no message was decoded process the next client, otherwise
-         * read more data from the same client. */
-        if (!fullmsg) break;
     }
 }
-
-/* Read data from clients. This function actually delegates a lower-level
- * function that depends on the kind of service (raw, http, ...). */
+//
+// Read data from clients. This function actually delegates a lower-level
+// function that depends on the kind of service (raw, http, ...).
 void modesReadFromClients(void) {
     int j;
     struct client *c;
@@ -4009,6 +4122,8 @@ void modesReadFromClients(void) {
         if ((c = Modes.clients[j]) == NULL) continue;
         if (c->service == Modes.ris)
             modesReadFromClient(c,"\n",decodeHexMessage);
+        else if (c->service == Modes.bis)
+            modesReadFromClient(c,"",decodeBinMessage);
         else if (c->service == Modes.https)
             modesReadFromClient(c,"\r\n\r\n",handleHTTPRequest);
     }
@@ -4035,12 +4150,14 @@ void showHelp(void) {
 "--modeac                 Enable decoding of SSR Modes 3/A & 3/C\n"
 "--net-beast              TCP raw output in Beast binary format\n"
 "--net-only               Enable just networking, no RTL device or file used\n"
-"--net-ro-size <size>     TCP raw output minimum size (default: 0)\n"
-"--net-ro-rate <rate>     TCP raw output memory flush rate (default: 0)\n"
-"--net-ro-port <port>     TCP raw output listen port (default: 30002)\n"
-"--net-ri-port <port>     TCP raw input listen port  (default: 30001)\n"
 "--net-http-port <port>   HTTP server port (default: 8080)\n"
+"--net-ri-port <port>     TCP raw input listen port  (default: 30001)\n"
+"--net-ro-port <port>     TCP raw output listen port (default: 30002)\n"
 "--net-sbs-port <port>    TCP BaseStation output listen port (default: 30003)\n"
+"--net-bi-port <port>     TCP Beast input listen port  (default: 30004)\n"
+"--net-bo-port <port>     TCP Beast output listen port (default: 30005)\n"
+"--net-ro-size <size>     TCP raw output minimum size (default: 0)\n"
+"--net-ro-rate <rate>     TCP raw output memory flush rate (default: 0)\n"
 "--lat <latitude>         Reference/receiver latitide for surface posn (opt)\n"
 "--lon <longitude>        Reference/receiver longitude for surface posn (opt)\n"
 "--fix                    Enable single-bits error correction using CRC\n"
@@ -4143,8 +4260,14 @@ int main(int argc, char **argv) {
             Modes.net_output_raw_rate = atoi(argv[++j]);
         } else if (!strcmp(argv[j],"--net-ro-port") && more) {
             Modes.net_output_raw_port = atoi(argv[++j]);
+            if (Modes.beast) // Required for legacy backward compatibility
+                {Modes.net_output_beast_port = Modes.net_output_raw_port;}
         } 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) {
@@ -4292,7 +4415,7 @@ int main(int argc, char **argv) {
             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_bit_fix[j], j+1, (j==0)?"error":"errors");
+                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);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-hamradio/dump1090.git



More information about the pkg-hamradio-commits mailing list