Windows Version of dump1090

Make the modifications necessary to compile dump1090 for WinXP, Win7 and
hopefully Win8.

The files can be compiled using M$ Visual Studio/C++ 6.0. Due to various
licensing issues, I haven't included the libraries or DLLs. You will
need to locate pthreadVC2.lib and rtlsdr.lib to link the file, install
the zadig drivers to support the dongle, and locate libusb-1.0.dll,
msvcr100.dll, pthreadVC2.dll and rtlsdr.dll.

dump1090.exe will not run on any Windows version prior to XP SP2,
because msvcr100.dll imports several functions from the Windows kernel
that are not available on earlier versions. This means dump1090 won't
work on Win2K.

The major change to the code relates to file handles. The original code
assumes Linux behaviour in that handles are allocated from 0
sequentially upwards. However Windows handles are allocated pseudo
randomly, and handle numbers greater than 1024 would break the code. The
code has therefore been modified to use a linked list of connection
structures, rather than a static array limited to 1024 entries.
This commit is contained in:
Malcolm Robb 2014-04-25 14:48:14 +01:00
parent f7843c1691
commit 30ae45ec2b
19 changed files with 2869 additions and 188 deletions

142
net_io.c
View file

@ -61,8 +61,18 @@ void modesInitNet(void) {
};
int j;
memset(Modes.clients,0,sizeof(Modes.clients));
Modes.maxfd = -1;
Modes.clients = NULL;
#ifdef _WIN32
if ( (!Modes.wsaData.wVersion)
&& (!Modes.wsaData.wHighVersion) ) {
// Try to start the windows socket support
if (WSAStartup(MAKEWORD(2,1),&Modes.wsaData) != 0)
{
fprintf(stderr, "WSAStartup returned Error\n");
}
}
#endif
for (j = 0; j < MODES_NET_SERVICES_NUM; j++) {
int s = anetTcpServer(Modes.aneterr, services[j].port, NULL);
@ -75,7 +85,9 @@ void modesInitNet(void) {
*services[j].socket = s;
}
#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
}
//
//=========================================================================
@ -83,7 +95,7 @@ void modesInitNet(void) {
// This function gets called from time to time when the decoding thread is
// awakened by new data arriving. This usually happens a few times every second
//
void modesAcceptClients(void) {
struct client * modesAcceptClients(void) {
int fd, port;
unsigned int j;
struct client *c;
@ -100,20 +112,15 @@ void modesAcceptClients(void) {
fd = anetTcpAccept(Modes.aneterr, services[j], NULL, &port);
if (fd == -1) continue;
if (fd >= MODES_NET_MAX_FD) {
close(fd);
return; // Max number of clients reached
}
anetNonBlock(Modes.aneterr, fd);
c = (struct client *) malloc(sizeof(*c));
c->service = services[j];
c->fd = fd;
c->buflen = 0;
Modes.clients[fd] = c;
c->service = services[j];
c->next = Modes.clients;
c->fd = fd;
c->buflen = 0;
Modes.clients = c;
anetSetSendBuffer(Modes.aneterr,fd,MODES_NET_SNDBUF_SIZE);
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++;
@ -123,43 +130,44 @@ void modesAcceptClients(void) {
if (Modes.debug & MODES_DEBUG_NET)
printf("Created new client %d\n", fd);
}
return Modes.clients;
}
//
//=========================================================================
//
// 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;
void modesFreeClient(struct client *c) {
if (Modes.debug & MODES_DEBUG_NET)
printf("Closing client %d\n", fd);
// If this was our maxfd, scan the clients array to find trhe new max.
// Note that we are sure there is no active fd greater than the closed
// fd, so we scan from fd-1 to 0.
if (Modes.maxfd == fd) {
int j;
Modes.maxfd = -1;
for (j = fd-1; j >= 0; j--) {
if (Modes.clients[j]) {
Modes.maxfd = j;
break;
// Unhook this client from the linked list of clients
struct client *p = Modes.clients;
if (p) {
if (p == c) {
Modes.clients = c->next;
} else {
while ((p) && (p->next != c)) {
p = p->next;
}
if (p) {
p->next = c->next;
}
}
}
// It's now safe to remove this client
close(c->fd);
if (c->service == Modes.sbsos) {
if (Modes.stat_sbs_connections) Modes.stat_sbs_connections--;
} else if (c->service == Modes.ros) {
if (Modes.stat_raw_connections) Modes.stat_raw_connections--;
} else if (c->service == Modes.bos) {
if (Modes.stat_beast_connections) Modes.stat_beast_connections--;
}
if (Modes.debug & MODES_DEBUG_NET)
printf("Closing client %d\n", c->fd);
free(c);
}
//
//=========================================================================
@ -167,17 +175,21 @@ void modesFreeClient(int fd) {
// Send the specified message to all clients listening for a given service
//
void modesSendAllClients(int service, void *msg, int len) {
int j;
struct client *c;
struct client *c = Modes.clients;
for (j = 0; j <= Modes.maxfd; j++) {
c = Modes.clients[j];
if (c && c->service == service) {
int nwritten = write(j, msg, len);
while (c) {
struct client *next = c->next;
if (c->service == service) {
#ifndef _WIN32
int nwritten = write(c->fd, msg, len);
#else
int nwritten = send(c->fd, msg, len, 0 );
#endif
if (nwritten != len) {
modesFreeClient(j);
modesFreeClient(c);
}
}
c = next;
}
}
//
@ -707,7 +719,12 @@ int handleHTTPRequest(struct client *c, char *p) {
if (stat(getFile, &sbuf) != -1 && (fd = open(getFile, O_RDONLY)) != -1) {
content = (char *) malloc(sbuf.st_size);
#ifndef _WIN32
if (read(fd, content, sbuf.st_size) == -1) {
#else
if (recv(fd, content, sbuf.st_size, 0) == -1) {
errno = WSAGetLastError();
#endif
snprintf(content, sbuf.st_size, "Error reading from file: %s", strerror(errno));
}
clen = sbuf.st_size;
@ -755,8 +772,13 @@ int handleHTTPRequest(struct client *c, char *p) {
}
// Send header and content.
#ifndef _WIN32
if ( (write(c->fd, hdr, hdrlen) != hdrlen)
|| (write(c->fd, content, clen) != clen) ) {
#else
if ( (send(c->fd, hdr, hdrlen, 0) != hdrlen)
|| (send(c->fd, content, clen, 0) != clen) ) {
#endif
free(content);
return 1;
}
@ -797,14 +819,19 @@ void modesReadFromClient(struct client *c, char *sep,
left = MODES_CLIENT_BUF_SIZE;
// If there is garbage, read more to discard it ASAP
}
#ifndef _WIN32
nread = read(c->fd, c->buf+c->buflen, left);
#else
nread = recv(c->fd, c->buf+c->buflen, left, 0);
if (nread < 0) {errno = WSAGetLastError();}
#endif
// 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);
modesFreeClient(c);
}
if (nread <= 0) {
break; // Serve next client
@ -851,7 +878,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->fd);
modesFreeClient(c);
return;
}
fullmsg = 1;
@ -867,7 +894,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->fd); // Handler returns 1 on error to signal we .
modesFreeClient(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
@ -890,19 +917,18 @@ void modesReadFromClient(struct client *c, char *sep,
// function that depends on the kind of service (raw, http, ...).
//
void modesReadFromClients(void) {
int j;
struct client *c;
modesAcceptClients();
struct client *c = modesAcceptClients();
for (j = 0; j <= Modes.maxfd; j++) {
if ((c = Modes.clients[j]) == NULL) continue;
if (c->service == Modes.ris)
while (c) {
if (c->service == Modes.ris) {
modesReadFromClient(c,"\n",decodeHexMessage);
else if (c->service == Modes.bis)
} else if (c->service == Modes.bis) {
modesReadFromClient(c,"",decodeBinMessage);
else if (c->service == Modes.https)
} else if (c->service == Modes.https) {
modesReadFromClient(c,"\r\n\r\n",handleHTTPRequest);
}
c = c->next;
}
}
//