diff --git a/coaa1090.obj b/coaa1090.obj index ea337ca..ea54fde 100644 Binary files a/coaa1090.obj and b/coaa1090.obj differ diff --git a/dump1090-win.1.09.0608.14.zip b/dump1090-win.1.10.3010.14.zip similarity index 80% rename from dump1090-win.1.09.0608.14.zip rename to dump1090-win.1.10.3010.14.zip index 5bd3d84..670d418 100644 Binary files a/dump1090-win.1.09.0608.14.zip and b/dump1090-win.1.10.3010.14.zip differ diff --git a/dump1090.c b/dump1090.c index cc46f3d..e510ff8 100644 --- a/dump1090.c +++ b/dump1090.c @@ -406,6 +406,7 @@ void showHelp(void) { "--net Enable networking\n" "--modeac Enable decoding of SSR Modes 3/A & 3/C\n" "--net-only Enable just networking, no RTL device or file used\n" +"--net-bind-address IP address to bind to (default: Any; Use 127.0.0.1 for private)\n" "--net-http-port HTTP server port (default: 8080)\n" "--net-ri-port TCP raw input listen port (default: 30001)\n" "--net-ro-port TCP raw output listen port (default: 30002)\n" @@ -715,6 +716,8 @@ int main(int argc, char **argv) { 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-bind-address") && more) { + Modes.net_bind_address = strdup(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) { diff --git a/dump1090.dsp b/dump1090.dsp index d64d0d1..6bd819b 100644 --- a/dump1090.dsp +++ b/dump1090.dsp @@ -131,6 +131,10 @@ SOURCE=.\winstubs.h # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\Dump1090.rc +# End Source File # End Group # Begin Group "Library Files" diff --git a/dump1090.h b/dump1090.h index fe1f8bf..39ad636 100644 --- a/dump1090.h +++ b/dump1090.h @@ -37,7 +37,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.09.0608.14" +#define MODES_DUMP1090_VERSION "1.10.3010.14" // ============================= Include files ========================== @@ -310,6 +310,7 @@ struct { // Internal state 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 + char *net_bind_address; // Bind address int net_http_port; // HTTP port int net_sndbuf_size; // TCP output buffer size (64Kb * 2^n) int quiet; // Suppress stdout diff --git a/dump1090.rc b/dump1090.rc new file mode 100644 index 0000000..bde0227 --- /dev/null +++ b/dump1090.rc @@ -0,0 +1,115 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +#include "ntverp.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,10,2910,14 + PRODUCTVERSION 1,10,2910,14 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x3L + FILESUBTYPE 0x7L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "Dump1090 for Win32 \0" + VALUE "CompanyName", "\0" + VALUE "FileDescription", "Mode A/C/S decoder for RTL Dongles\0" + VALUE "FileVersion", "1, 10, 2910, 14\0" + VALUE "InternalName", "DUMP1090.EXE\0" + VALUE "LegalCopyright", "Copyright © 2012 by Salvatore Sanfilippo \r\nCopyright © 2014 by Malcolm Robb \0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "DUMP1090.EXE\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "DUMP1090\0" + VALUE "ProductVersion", "1, 10, 2910, 14\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""ntverp.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/mode_s.c b/mode_s.c index a1014c6..7f9d0ed 100644 --- a/mode_s.c +++ b/mode_s.c @@ -1456,46 +1456,75 @@ int detectOutOfPhase(uint16_t *pPreamble) { if (pPreamble[-1] > pPreamble[1]/3) return -1; return 0; } + + +uint16_t clamped_scale(uint16_t v, uint16_t scale) { + uint32_t scaled = (uint32_t)v * scale / 16384; + if (scaled > 65535) return 65535; + return (uint16_t) scaled; +} +// This function decides whether we are sampling early or late, +// and by approximately how much, by looking at the energy in +// preamble bits before and after the expected pulse locations. // -//========================================================================= -// -// This function does not really correct the phase of the message, it just -// applies a transformation to the first sample representing a given bit: -// -// If the previous bit was one, we amplify it a bit. -// If the previous bit was zero, we decrease it a bit. -// -// This simple transformation makes the message a bit more likely to be -// correctly decoded for out of phase messages: -// -// When messages are out of phase there is more uncertainty in -// sequences of the same bit multiple times, since 11111 will be -// transmitted as continuously altering magnitude (high, low, high, low...) -// -// However because the message is out of phase some part of the high -// is mixed in the low part, so that it is hard to distinguish if it is -// a zero or a one. -// -// However when the message is out of phase passing from 0 to 1 or from -// 1 to 0 happens in a very recognizable way, for instance in the 0 -> 1 -// transition, magnitude goes low, high, high, low, and one of of the -// two middle samples the high will be *very* high as part of the previous -// or next high signal will be mixed there. -// -// Applying our simple transformation we make more likely if the current -// bit is a zero, to detect another zero. Symmetrically if it is a one -// it will be more likely to detect a one because of the transformation. -// In this way similar levels will be interpreted more likely in the -// correct way. +// It then deals with one sample pair at a time, comparing samples +// to make a decision about the bit value. Based on this decision it +// modifies the sample value of the *adjacent* sample which will +// contain some of the energy from the bit we just inspected. // +// pPayload[0] should be the start of the preamble, +// pPayload[-1 .. MODES_PREAMBLE_SAMPLES + MODES_LONG_MSG_SAMPLES - 1] should be accessible. +// pPayload[MODES_PREAMBLE_SAMPLES .. MODES_PREAMBLE_SAMPLES + MODES_LONG_MSG_SAMPLES - 1] will be updated. void applyPhaseCorrection(uint16_t *pPayload) { int j; - for (j = 0; j < MODES_LONG_MSG_SAMPLES; j += 2, pPayload += 2) { - if (pPayload[0] > pPayload[1]) { // One - pPayload[2] = (pPayload[2] * 5) / 4; - } else { // Zero - pPayload[2] = (pPayload[2] * 4) / 5; + // we expect 1 bits at 0, 2, 7, 9 + // and 0 bits at -1, 1, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14 + // use bits -1,6 for early detection (bit 0/7 arrived a little early, our sample period starts after the bit phase so we include some of the next bit) + // use bits 3,10 for late detection (bit 2/9 arrived a little late, our sample period starts before the bit phase so we include some of the last bit) + + uint32_t onTime = (pPayload[0] + pPayload[2] + pPayload[7] + pPayload[9]); + uint32_t early = (pPayload[-1] + pPayload[6]) << 1; + uint32_t late = (pPayload[3] + pPayload[10]) << 1; + + if (early > late) { + // Our sample period starts late and so includes some of the next bit. + + uint16_t scaleUp = 16384 + 16384 * early / (early + onTime); // 1 + early / (early+onTime) + uint16_t scaleDown = 16384 - 16384 * early / (early + onTime); // 1 - early / (early+onTime) + + // trailing bits are 0; final data sample will be a bit low. + pPayload[MODES_PREAMBLE_SAMPLES + MODES_LONG_MSG_SAMPLES - 1] = + clamped_scale(pPayload[MODES_PREAMBLE_SAMPLES + MODES_LONG_MSG_SAMPLES - 1], scaleUp); + for (j = MODES_PREAMBLE_SAMPLES + MODES_LONG_MSG_SAMPLES - 2; j > MODES_PREAMBLE_SAMPLES; j -= 2) { + if (pPayload[j] > pPayload[j+1]) { + // x [1 0] y + // x overlapped with the "1" bit and is slightly high + pPayload[j-1] = clamped_scale(pPayload[j-1], scaleDown); + } else { + // x [0 1] y + // x overlapped with the "0" bit and is slightly low + pPayload[j-1] = clamped_scale(pPayload[j-1], scaleUp); + } + } + } else { + // Our sample period starts early and so includes some of the previous bit. + + uint16_t scaleUp = 16384 + 16384 * late / (late + onTime); // 1 + late / (late+onTime) + uint16_t scaleDown = 16384 - 16384 * late / (late + onTime); // 1 - late / (late+onTime) + + // leading bits are 0; first data sample will be a bit low. + pPayload[MODES_PREAMBLE_SAMPLES] = clamped_scale(pPayload[MODES_PREAMBLE_SAMPLES], scaleUp); + for (j = MODES_PREAMBLE_SAMPLES; j < MODES_PREAMBLE_SAMPLES + MODES_LONG_MSG_SAMPLES - 2; j += 2) { + if (pPayload[j] > pPayload[j+1]) { + // x [1 0] y + // y overlapped with the "0" bit and is slightly low + pPayload[j+2] = clamped_scale(pPayload[j+2], scaleUp); + } else { + // x [0 1] y + // y overlapped with the "1" bit and is slightly high + pPayload[j+2] = clamped_scale(pPayload[j+2], scaleDown); + } } } } @@ -1509,7 +1538,7 @@ void applyPhaseCorrection(uint16_t *pPayload) { void detectModeS(uint16_t *m, uint32_t mlen) { struct modesMessage mm; unsigned char msg[MODES_LONG_MSG_BYTES], *pMsg; - uint16_t aux[MODES_LONG_MSG_SAMPLES]; + uint16_t aux[MODES_PREAMBLE_SAMPLES+MODES_LONG_MSG_SAMPLES+1]; uint32_t j; int use_correction = 0; @@ -1631,10 +1660,10 @@ void detectModeS(uint16_t *m, uint32_t mlen) { // If the previous attempt with this message failed, retry using // magnitude correction // Make a copy of the Payload, and phase correct the copy - memcpy(aux, pPayload, sizeof(aux)); - applyPhaseCorrection(aux); + memcpy(aux, &pPreamble[-1], sizeof(aux)); + applyPhaseCorrection(&aux[1]); Modes.stat_out_of_phase++; - pPayload = aux; + pPayload = &aux[1 + MODES_PREAMBLE_SAMPLES]; // TODO ... apply other kind of corrections } diff --git a/net_io.c b/net_io.c index 294a37d..632e013 100644 --- a/net_io.c +++ b/net_io.c @@ -86,7 +86,7 @@ void modesInitNet(void) { for (j = 0; j < MODES_NET_SERVICES_NUM; j++) { services[j].enabled = (services[j].port != 0); if (services[j].enabled) { - int s = anetTcpServer(Modes.aneterr, services[j].port, NULL); + int s = anetTcpServer(Modes.aneterr, services[j].port, Modes.net_bind_address); if (s == -1) { fprintf(stderr, "Error opening the listening port %d (%s): %s\n", services[j].port, services[j].descr, Modes.aneterr); @@ -159,7 +159,7 @@ struct client * modesAcceptClients(void) { // // On error free the client, collect the structure, adjust maxfd if needed. // -void modesFreeClient(struct client *c) { +void modesCloseClient(struct client *c) { int j; // Clean up, but defer removing from the list until modesNetCleanup(). @@ -200,7 +200,7 @@ static void flushWrites(struct net_writer *writer) { int nwritten = send(c->fd, writer->data, writer->dataUsed, 0 ); #endif if (nwritten != writer->dataUsed) { - modesFreeClient(c); + modesCloseClient(c); } } } @@ -744,6 +744,7 @@ int handleHTTPRequest(struct client *c, char *p) { char hdr[512]; int clen, hdrlen; int httpver, keepalive; + int statuscode = 500; char *url, *content; char ctype[48]; char getFile[1024]; @@ -756,11 +757,12 @@ int handleHTTPRequest(struct client *c, char *p) { httpver = (strstr(p, "HTTP/1.1") != NULL) ? 11 : 10; if (httpver == 10) { // HTTP 1.0 defaults to close, unless otherwise specified. - keepalive = strstr(p, "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(p, "Connection: close") == NULL; + //keepalive = strstr(p, "Connection: close") == NULL; } + keepalive = 0; // Identify he URL. p = strchr(p,' '); @@ -785,22 +787,35 @@ int handleHTTPRequest(struct client *c, char *p) { // "/" -> Our google map application. // "/data.json" -> Our ajax request to update planes. if (strstr(url, "/data.json")) { + statuscode = 200; content = aircraftsToJson(&clen); //snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_JSON); } else { struct stat sbuf; int fd = -1; + char *rp, *hrp; - if (stat(getFile, &sbuf) != -1 && (fd = open(getFile, O_RDONLY)) != -1) { - content = (char *) malloc(sbuf.st_size); - if (read(fd, content, sbuf.st_size) == -1) { - snprintf(content, sbuf.st_size, "Error reading from file: %s", strerror(errno)); + rp = realpath(getFile, NULL); + hrp = realpath(HTMLPATH, NULL); + hrp = (hrp ? hrp : HTMLPATH); + clen = -1; + content = strdup("Server error occured"); + if (rp && (!strncmp(hrp, rp, strlen(hrp)))) { + if (stat(getFile, &sbuf) != -1 && (fd = open(getFile, O_RDONLY)) != -1) { + content = (char *) realloc(content, sbuf.st_size); + if (read(fd, content, sbuf.st_size) != -1) { + clen = sbuf.st_size; + statuscode = 200; + } } - clen = sbuf.st_size; } else { - char buf[128]; - clen = snprintf(buf,sizeof(buf),"Error opening HTML file: %s", strerror(errno)); - content = strdup(buf); + errno = ENOENT; + } + + if (clen < 0) { + content = realloc(content, 128); + clen = snprintf(content, 128,"Error opening HTML file: %s", strerror(errno)); + statuscode = 404; } if (fd != -1) { @@ -824,7 +839,7 @@ int handleHTTPRequest(struct client *c, char *p) { // Create the header and send the reply hdrlen = snprintf(hdr, sizeof(hdr), - "HTTP/1.1 200 OK\r\n" + "HTTP/1.1 %d \r\n" "Server: Dump1090\r\n" "Content-Type: %s\r\n" "Connection: %s\r\n" @@ -832,6 +847,7 @@ int handleHTTPRequest(struct client *c, char *p) { "Cache-Control: no-cache, must-revalidate\r\n" "Expires: Sat, 26 Jul 1997 05:00:00 GMT\r\n" "\r\n", + statuscode, ctype, keepalive ? "keep-alive" : "close", clen); @@ -899,17 +915,25 @@ void modesReadFromClient(struct client *c, char *sep, if (nread != left) { bContinue = 0; } -#ifndef _WIN32 - if ( (nread < 0 && errno != EAGAIN && errno != EWOULDBLOCK) || nread == 0 ) { // Error, or end of file -#else - if ( (nread < 0) && (errno != EWOULDBLOCK)) { // Error, or end of file -#endif - modesFreeClient(c); + + if (nread == 0) { // End of file + modesCloseClient(c); return; } - if (nread <= 0) { - break; // Serve next client + +#ifndef _WIN32 + if (nread < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { // No data available (not really an error) +#else + if (nread < 0 && errno == EWOULDBLOCK) { // No data available (not really an error) +#endif + return; } + + if (nread < 0) { // Other errors + modesCloseClient(c); + return; + } + c->buflen += nread; // Always null-term so we are free to use strstr() (it won't affect binary case) @@ -952,7 +976,7 @@ void modesReadFromClient(struct client *c, char *sep, } // Have a 0x1a followed by 1, 2 or 3 - pass message less 0x1a to handler. if (handler(c, s)) { - modesFreeClient(c); + modesCloseClient(c); return; } fullmsg = 1; @@ -968,7 +992,7 @@ void modesReadFromClient(struct client *c, char *sep, 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); // Handler returns 1 on error to signal we . + modesCloseClient(c); // Handler returns 1 on error to signal we . return; // should close the client connection } s = e + strlen(sep); // Move to start of next message @@ -980,7 +1004,7 @@ void modesReadFromClient(struct client *c, char *sep, 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; + return; } } } diff --git a/public_html/config.js b/public_html/config.js index c4d7ecd..f7d8e2e 100644 --- a/public_html/config.js +++ b/public_html/config.js @@ -20,6 +20,7 @@ CONST_ZOOMLVL = 5; // The default marker color MarkerColor = "rgb(127, 127, 127)"; SelectedColor = "rgb(225, 225, 225)"; +StaleColor = "rgb(190, 190, 190)"; // -- Site Settings --------------------------------------- SiteShow = false; // true or false diff --git a/public_html/gmap.html b/public_html/gmap.html index 96f412a..9ab2dc2 100644 --- a/public_html/gmap.html +++ b/public_html/gmap.html @@ -1,10 +1,11 @@ + - + @@ -13,6 +14,7 @@ + DUMP1090