[hamradio-commits] [dump1090] 252/389: Bug Fix in modesReadFromClient()

Matthew Ernisse mernisse-guest at moszumanska.debian.org
Wed Nov 5 00:20:01 UTC 2014


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

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

commit 7ea2e8fdefa2142d908112290ce8ed5893aa5fa1
Author: Malcolm Robb <Support at ATTAvionics.com>
Date:   Fri Sep 20 16:48:15 2013 +0100

    Bug Fix in modesReadFromClient()
    
    The modesReadFromClient() funtion is called from modesReadFromClients(),
    which in turn is called from backgroundTasks(). backgroundTasks() is
    called from within the main processing loop.
    
    However, modesReadFromClient() can and does block. It attempts to read
    characters from the input stream, and loops whilst there was no error.
    This stalls the main RTL processing loop until an error occurs. In order
    to support simultaneous local reception (via our RTL dongle) and remote
    forwarding (data received from the interweb) we cannot allow this
    internet read to stall.
    
    To fix this, in modesReadFromClient() attempt to read a buffer of data
    (currently 0x400 bytes). If we get a full buffer of bytes, then process
    them, and attempt to read another full buffer. Keep doing thios untill
    we read only a partial buffer (less than 0x400 bytes). Process the
    partial buffer bytes and return.
    
    This allows us to occasionally process data that is arriving from the
    internet (which is buffered anyway in the TCP stack), without blocking
    local RTL dongle decoding.
---
 dump1090.h    |  7 +++++--
 interactive.c | 38 ++++++++++++++++++++++++++++++++++++--
 net_io.c      | 30 ++++++++++++++++++------------
 3 files changed, 59 insertions(+), 16 deletions(-)

diff --git a/dump1090.h b/dump1090.h
index dd55c50..3f8d34f 100644
--- a/dump1090.h
+++ b/dump1090.h
@@ -159,7 +159,7 @@
 #define MODES_INTERACTIVE_DELETE_TTL   300      // Delete from the list after 300 seconds
 #define MODES_INTERACTIVE_DISPLAY_TTL   60      // Delete from display after 60 seconds
 
-#define MODES_NET_MAX_FD 1024
+#define MODES_NET_MAX_FD             1024
 #define MODES_NET_INPUT_RAW_PORT    30001
 #define MODES_NET_OUTPUT_RAW_PORT   30002
 #define MODES_NET_OUTPUT_SBS_PORT   30003
@@ -181,8 +181,8 @@
 struct client {
     int  fd;                           // File descriptor
     int  service;                      // TCP port the client is connected to
-    char buf[MODES_CLIENT_BUF_SIZE+1]; // Read buffer
     int  buflen;                       // Amount of data on buffer
+    char buf[MODES_CLIENT_BUF_SIZE+1]; // Read buffer
 };
 
 // Structure used to describe an aircraft in iteractive mode
@@ -405,6 +405,8 @@ void modesInitErrorInfo ();
 struct aircraft* interactiveReceiveData(struct modesMessage *mm);
 void  interactiveShowData(void);
 void  interactiveRemoveStaleAircrafts(void);
+int   decodeBinMessage   (struct client *c, char *p);
+
 //
 // Functions exported from net_io.c
 //
@@ -412,6 +414,7 @@ void modesInitNet         (void);
 void modesReadFromClients (void);
 void modesSendAllClients  (int service, void *msg, int len);
 void modesQueueOutput     (struct modesMessage *mm);
+void modesReadFromClient(struct client *c, char *sep, int(*handler)(struct client *, char *));
 
 #ifdef __cplusplus
 }
diff --git a/interactive.c b/interactive.c
index 061da78..6bc4efb 100644
--- a/interactive.c
+++ b/interactive.c
@@ -41,6 +41,40 @@ static uint64_t mstime(void) {
     mst += tv.tv_usec/1000;
     return mst;
 }
+
+#ifdef _WIN32
+// Standard error macro for reporting API errors 
+#define PERR(bSuccess, api){if(!(bSuccess)) printf("%s:Error %d from %s on line %d\n", __FILE__, GetLastError(), api, __LINE__);}
+
+void cls( HANDLE hConsole ) {
+    COORD coordScreen = { 0, 0 };    // here's where we'll home the cursor
+    BOOL bSuccess;
+    DWORD cCharsWritten;
+    CONSOLE_SCREEN_BUFFER_INFO csbi; // to get buffer info
+    DWORD dwConSize;                 // number of character cells in the current buffer
+
+    // get the number of character cells in the current buffer
+    bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );
+    PERR( bSuccess, "GetConsoleScreenBufferInfo" );
+    dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
+
+    // fill the entire screen with blanks
+    bSuccess = FillConsoleOutputCharacter( hConsole, (TCHAR) ' ', dwConSize, coordScreen, &cCharsWritten );
+    PERR( bSuccess, "FillConsoleOutputCharacter" );
+
+    // get the current text attribute
+    bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );
+    PERR( bSuccess, "ConsoleScreenBufferInfo" );
+
+    // now set the buffer's attributes accordingly
+    bSuccess = FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten );
+    PERR( bSuccess, "FillConsoleOutputAttribute" );
+
+    // put the cursor at (0, 0)
+    bSuccess = SetConsoleCursorPosition( hConsole, coordScreen );
+    PERR( bSuccess, "SetConsoleCursorPosition" );
+}
+#endif
 //
 //========================= Interactive mode ===============================
 //
@@ -342,7 +376,7 @@ void interactiveShowData(void) {
 #ifndef _WIN32
     printf("\x1b[H\x1b[2J");    // Clear the screen
 #else
-    system("cls");
+    cls(GetStdHandle(STD_OUTPUT_HANDLE));
 #endif
 
     if (Modes.interactive_rtl1090 == 0) {
@@ -439,7 +473,7 @@ void interactiveShowData(void) {
 //=========================================================================
 //
 // When in interactive mode If we don't receive new nessages within
-// MODES_INTERACTIVE__DELETE_TTL seconds we remove the aircraft from the list.
+// MODES_INTERACTIVE_DELETE_TTL seconds we remove the aircraft from the list.
 //
 void interactiveRemoveStaleAircrafts(void) {
     struct aircraft *a = Modes.aircrafts;
diff --git a/net_io.c b/net_io.c
index 538c92b..50bf803 100644
--- a/net_io.c
+++ b/net_io.c
@@ -759,24 +759,29 @@ void modesReadFromClient(struct client *c, char *sep,
     int left;
     int nread;
     int fullmsg;
+    int bContinue = 1;
     char *s, *e;
 
-    while(1) {
+    while(bContinue) {
 
         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) {
+        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 we didn't get all the data we asked for, then return once we've processed what we did get.
+        if (nread != left) {
+            bContinue = 0;
+        }
+        if ( (nread < 0) && (errno != EAGAIN)) { // Error, or end of file
+            modesFreeClient(c->fd);
+        }
         if (nread <= 0) {
-            if (nread == 0 || errno != EAGAIN) { // Error, or end of file
-                modesFreeClient(c->fd);
-            }
             break; // Serve next client
         }
         c->buflen += nread;
@@ -787,12 +792,12 @@ void modesReadFromClient(struct client *c, char *sep,
         e = s = c->buf;                                // Start with the start of buffer, first message
 
         if (c->service == Modes.bis) {
-            // This is the Bease Binary scanning case.
+            // This is the Beast 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
+            while (left && ((s = memchr(e, (char) 0x1a, left)) != NULL)) { // 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
@@ -820,10 +825,11 @@ void modesReadFromClient(struct client *c, char *sep,
             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. 
@@ -835,10 +841,10 @@ void modesReadFromClient(struct client *c, char *sep,
             }
         }
         
-        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
+        if (fullmsg) {                             // We processed something - so 
+            c->buflen = &(c->buf[c->buflen]) - s;  //     Update 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;
         }
     }

-- 
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