mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-21 06:03:12 +00:00
Fixed select() problems with dummy interfaces and EOF reporting.
Dummy interfaces now work. Supressed lots of debug messages.
This commit is contained in:
parent
ec1fe22e93
commit
0cf6e545c4
3
mphlr.h
3
mphlr.h
@ -385,8 +385,9 @@ extern int overlayMode;
|
||||
#define OVERLAY_INTERFACE_PACKETRADIO 3
|
||||
typedef struct overlay_interface {
|
||||
char name[80];
|
||||
int socket;
|
||||
int fd;
|
||||
int offset;
|
||||
int fileP;
|
||||
int bits_per_second;
|
||||
int port;
|
||||
int type;
|
||||
|
57
overlay.c
57
overlay.c
@ -45,7 +45,62 @@
|
||||
|
||||
#include "mphlr.h"
|
||||
|
||||
int overlay_socket=-1;
|
||||
int overlayMode=0;
|
||||
|
||||
overlay_txqueue overlay_tx[4];
|
||||
|
||||
int overlayServerMode()
|
||||
{
|
||||
/* In overlay mode we need to listen to all of our sockets, and also to
|
||||
send periodic traffic. This means we need to */
|
||||
fprintf(stderr,"Running in overlay mode.\n");
|
||||
|
||||
/* Get the set of socket file descriptors we need to monitor.
|
||||
Note that end-of-file will trigger select(), so we cannot run select() if we
|
||||
have any dummy interfaces running. So we do an ugly hack of just waiting no more than
|
||||
5ms between checks if we have a dummy interface running. This is a reasonable simulation
|
||||
of wifi latency anyway, so we'll live with it. Larger values will affect voice transport,
|
||||
and smaller values would affect CPU and energy use, and make the simulation less realistic. */
|
||||
int i;
|
||||
fd_set read_fds;
|
||||
int maxfd=-1;
|
||||
while(1) {
|
||||
/* Work out how long we can wait before we need to tick */
|
||||
long long ms=overlay_time_until_next_tick();
|
||||
struct timeval waittime;
|
||||
|
||||
int filesPresent=0;
|
||||
FD_ZERO(&read_fds);
|
||||
for(i=0;i<overlay_interface_count;i++)
|
||||
{
|
||||
if (!overlay_interfaces[i].fileP)
|
||||
{
|
||||
if (overlay_interfaces[i].fd>maxfd) maxfd=overlay_interfaces[i].fd;
|
||||
FD_SET(overlay_interfaces[i].fd,&read_fds);
|
||||
}
|
||||
else { filesPresent=1; if (ms>5) ms=5; }
|
||||
}
|
||||
|
||||
waittime.tv_usec=(ms%1000)*1000;
|
||||
waittime.tv_sec=ms/1000;
|
||||
|
||||
if (debug&4) fprintf(stderr,"Waiting via select() for up to %lldms\n",ms);
|
||||
int r=select(maxfd+1,&read_fds,NULL,NULL,&waittime);
|
||||
if (r<0) {
|
||||
/* select had a problem */
|
||||
if (debug&4) perror("select()");
|
||||
WHY("select() complained.");
|
||||
} else if (r>0) {
|
||||
/* We have data, so try to receive it */
|
||||
if (debug&4) fprintf(stderr,"select() reports packets waiting\n");
|
||||
overlay_rx_messages();
|
||||
} else {
|
||||
/* No data before tick occurred, so do nothing.
|
||||
Well, for now let's just check anyway. */
|
||||
if (debug&4) fprintf(stderr,"select() timeout.\n");
|
||||
overlay_rx_messages();
|
||||
}
|
||||
/* Check if we need to trigger any ticks on any interfaces */
|
||||
overlay_check_ticks();
|
||||
}
|
||||
}
|
||||
|
@ -136,9 +136,10 @@ int overlay_interface_init_socket(int interface,struct sockaddr_in src_addr,stru
|
||||
I(local_address)=src_addr;
|
||||
I(broadcast_address)=broadcast;
|
||||
I(netmask)=netmask;
|
||||
I(fileP)=0;
|
||||
|
||||
I(socket)=socket(PF_INET,SOCK_DGRAM,0);
|
||||
if (I(socket)<0) {
|
||||
I(fd)=socket(PF_INET,SOCK_DGRAM,0);
|
||||
if (I(fd)<0) {
|
||||
return WHY("Could not create UDP socket for interface");
|
||||
}
|
||||
|
||||
@ -147,15 +148,15 @@ int overlay_interface_init_socket(int interface,struct sockaddr_in src_addr,stru
|
||||
/* XXX Is this right? Are we really setting the local side address?
|
||||
I was in a plane when at the time, so couldn't Google it.
|
||||
*/
|
||||
fprintf(stderr,"src_addr=%08x\n",(unsigned int)src_addr.sin_addr.s_addr);
|
||||
if(bind(I(socket),(struct sockaddr *)&src_addr,sizeof(src_addr))) {
|
||||
if (debug&4) fprintf(stderr,"src_addr=%08x\n",(unsigned int)src_addr.sin_addr.s_addr);
|
||||
if(bind(I(fd),(struct sockaddr *)&src_addr,sizeof(src_addr))) {
|
||||
perror("bind()");
|
||||
return WHY("MP HLR server could not bind to requested UDP port (bind() failed)");
|
||||
}
|
||||
fprintf(stderr,"Bound to port 0x%04x\n",src_addr.sin_port);
|
||||
if (debug&4) fprintf(stderr,"Bound to port 0x%04x\n",src_addr.sin_port);
|
||||
|
||||
int broadcastP=1;
|
||||
if(setsockopt(I(socket), SOL_SOCKET, SO_BROADCAST, &broadcastP, sizeof(broadcastP)) < 0) {
|
||||
if(setsockopt(I(fd), SOL_SOCKET, SO_BROADCAST, &broadcastP, sizeof(broadcastP)) < 0) {
|
||||
perror("setsockopt");
|
||||
return WHY("setsockopt() failed");
|
||||
}
|
||||
@ -192,11 +193,12 @@ int overlay_interface_init(char *name,struct sockaddr_in src_addr,struct sockadd
|
||||
}
|
||||
|
||||
if (name[0]=='>') {
|
||||
I(fileP)=1;
|
||||
I(fd) = open(&name[1],O_APPEND|O_NONBLOCK|O_RDWR);
|
||||
if (I(fd)<1)
|
||||
return WHY("could not open dummy interface file for append");
|
||||
/* Seek to end of file as initial reading point */
|
||||
I(socket)=lseek(I(fd),0,SEEK_END); /* socket gets reused to hold file offset */
|
||||
I(offset)=lseek(I(fd),0,SEEK_END); /* socket gets reused to hold file offset */
|
||||
/* XXX later add pretend location information so that we can decide which "packets" to receive
|
||||
based on closeness */
|
||||
} else {
|
||||
@ -234,12 +236,15 @@ int overlay_rx_messages()
|
||||
unsigned int addrlen=sizeof(src_addr);
|
||||
unsigned char transaction_id[8];
|
||||
|
||||
if (overlay_interfaces[i].fd) {
|
||||
if (overlay_interfaces[i].fileP) {
|
||||
/* Read from dummy interface file */
|
||||
lseek(overlay_interfaces[i].fd,overlay_interfaces[i].socket,SEEK_SET);
|
||||
long long length=lseek(overlay_interfaces[i].fd,0,SEEK_END);
|
||||
lseek(overlay_interfaces[i].fd,overlay_interfaces[i].offset,SEEK_SET);
|
||||
if (debug&4) fprintf(stderr,"Reading from interface log at offset %d, end of file at %lld.\n",
|
||||
overlay_interfaces[i].offset,length);
|
||||
if (read(overlay_interfaces[i].fd,packet,overlay_interfaces[i].mtu)==overlay_interfaces[i].mtu)
|
||||
{
|
||||
overlay_interfaces[i].socket+=overlay_interfaces[i].mtu;
|
||||
overlay_interfaces[i].offset+=overlay_interfaces[i].mtu;
|
||||
plen=overlay_interfaces[i].mtu;
|
||||
bzero(&transaction_id[0],8);
|
||||
bzero(&src_addr,sizeof(src_addr));
|
||||
@ -248,11 +253,11 @@ int overlay_rx_messages()
|
||||
else { c[i]=0; count--; }
|
||||
} else {
|
||||
/* Read from UDP socket */
|
||||
plen=recvfrom(overlay_interfaces[i].socket,packet,sizeof(packet),MSG_DONTWAIT,
|
||||
plen=recvfrom(overlay_interfaces[i].fd,packet,sizeof(packet),MSG_DONTWAIT,
|
||||
&src_addr,&addrlen);
|
||||
if (plen<0) { c[i]=0; count--; } else {
|
||||
/* We have a frame from this interface */
|
||||
fprintf(stderr,"Received %d bytes on interface #%d\n",plen,i);
|
||||
if (debug&4)fprintf(stderr,"Received %d bytes on interface #%d\n",plen,i);
|
||||
|
||||
bzero(&transaction_id[0],8);
|
||||
if (!packetOk(packet,plen,transaction_id,&src_addr,addrlen,1)) WHY("Malformed packet");
|
||||
@ -288,10 +293,10 @@ int overlay_broadcast_ensemble(int interface_number,unsigned char *bytes,int len
|
||||
memset(&s, '\0', sizeof(struct sockaddr_in));
|
||||
s = overlay_interfaces[interface_number].broadcast_address;
|
||||
s.sin_family = AF_INET;
|
||||
fprintf(stderr,"Port=%d\n",overlay_interfaces[interface_number].port);
|
||||
if (debug&4) fprintf(stderr,"Port=%d\n",overlay_interfaces[interface_number].port);
|
||||
s.sin_port = htons( overlay_interfaces[interface_number].port );
|
||||
|
||||
if (overlay_interfaces[interface_number].fd)
|
||||
if (overlay_interfaces[interface_number].fileP)
|
||||
{
|
||||
if (write(overlay_interfaces[interface_number].fd,bytes,overlay_interfaces[interface_number].mtu)
|
||||
!=overlay_interfaces[interface_number].mtu)
|
||||
@ -304,7 +309,7 @@ int overlay_broadcast_ensemble(int interface_number,unsigned char *bytes,int len
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sendto(overlay_interfaces[interface_number].socket, bytes, len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) < 0)
|
||||
if(sendto(overlay_interfaces[interface_number].fd, bytes, len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) < 0)
|
||||
{
|
||||
/* Failed to send */
|
||||
perror("sendto");
|
||||
@ -345,7 +350,7 @@ int overlay_interface_discover()
|
||||
1000000,PORT_DNA,OVERLAY_INTERFACE_WIFI))
|
||||
WHY("Could not initialise newly seen interface");
|
||||
else
|
||||
fprintf(stderr,"Registered interface %s\n",r->namespec);
|
||||
if (debug&4)fprintf(stderr,"Registered interface %s\n",r->namespec);
|
||||
}
|
||||
}
|
||||
r=r->next;
|
||||
@ -363,7 +368,7 @@ int overlay_interface_discover()
|
||||
unsigned int broadcast_bits=local.sin_addr.s_addr|~netmask.sin_addr.s_addr;
|
||||
struct sockaddr_in broadcast=local;
|
||||
broadcast.sin_addr.s_addr=broadcast_bits;
|
||||
printf("%s: %08x %08x %08x\n",name,local.sin_addr.s_addr,netmask.sin_addr.s_addr,broadcast.sin_addr.s_addr);
|
||||
if (debug>1) printf("%s: %08x %08x %08x\n",name,local.sin_addr.s_addr,netmask.sin_addr.s_addr,broadcast.sin_addr.s_addr);
|
||||
/* Now register the interface, or update the existing interface registration */
|
||||
struct interface_rules *r=interface_filter,*me=NULL;
|
||||
while(r) {
|
||||
@ -372,7 +377,7 @@ int overlay_interface_discover()
|
||||
r=r->next;
|
||||
}
|
||||
if (me&&(!me->excludeP)) {
|
||||
fprintf(stderr,"Interface %s is interesting.\n",name);
|
||||
if (debug&4)fprintf(stderr,"Interface %s is interesting.\n",name);
|
||||
/* We should register or update this interface. */
|
||||
int i;
|
||||
for(i=0;i<overlay_interface_count;i++) if (!strcasecmp(overlay_interfaces[i].name,(char *)name)) break;
|
||||
@ -389,7 +394,7 @@ int overlay_interface_discover()
|
||||
else
|
||||
{
|
||||
/* Interface has changed */
|
||||
close(overlay_interfaces[i].socket);
|
||||
close(overlay_interfaces[i].fd);
|
||||
if (overlay_interface_init_socket(i,local,broadcast,netmask))
|
||||
WHY("Could not reinitialise changed interface");
|
||||
}
|
||||
@ -400,7 +405,7 @@ int overlay_interface_discover()
|
||||
me->speed_in_bits,me->port,me->type))
|
||||
WHY("Could not initialise newly seen interface");
|
||||
else
|
||||
fprintf(stderr,"Registered interface %s\n",name);
|
||||
if (debug&4) fprintf(stderr,"Registered interface %s\n",name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -424,7 +429,7 @@ int overlay_tick_interface(int i, long long now)
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr,"Ticking interface #%d\n",i);
|
||||
if (debug&4) fprintf(stderr,"Ticking interface #%d\n",i);
|
||||
overlay_interfaces[i].sequence_number++;
|
||||
|
||||
/* Get a buffer ready, and limit it's size appropriately.
|
||||
@ -491,11 +496,11 @@ int overlay_tick_interface(int i, long long now)
|
||||
|
||||
/* Now send the frame. This takes the form of a special DNA packet with a different
|
||||
service code, which we setup earlier. */
|
||||
fprintf(stderr,"Sending %d bytes\n",e->length);
|
||||
if (debug&4) fprintf(stderr,"Sending %d bytes\n",e->length);
|
||||
if (!overlay_broadcast_ensemble(i,e->bytes,e->length))
|
||||
{
|
||||
fprintf(stderr,"Successfully transmitted tick frame #%d on interface #%d\n",
|
||||
overlay_interfaces[i].sequence_number,i);
|
||||
fprintf(stderr,"Successfully transmitted tick frame #%d on interface #%d (%d bytes)\n",
|
||||
overlay_interfaces[i].sequence_number,i,e->length);
|
||||
/* De-queue the passengers who were aboard. */
|
||||
int j;
|
||||
overlay_payload **p=&overlay_tx[OVERLAY_ISOCHRONOUS_VOICE].first;
|
||||
@ -535,13 +540,13 @@ int overlay_check_ticks()
|
||||
|
||||
/* Now check if the next tick time for the interfaces is no later than that time.
|
||||
If so, trigger a tick on the interface. */
|
||||
fprintf(stderr,"Examining %d interfaces.\n",overlay_interface_count);
|
||||
if (debug&4) fprintf(stderr,"Examining %d interfaces.\n",overlay_interface_count);
|
||||
for(i=0;i<overlay_interface_count;i++)
|
||||
{
|
||||
/* Only tick live interfaces */
|
||||
if (overlay_interfaces[i].observed>0)
|
||||
{
|
||||
fprintf(stderr,"Interface %s ticks every %dms, last at %lld.\n",overlay_interfaces[i].name,
|
||||
if (debug&4)fprintf(stderr,"Interface %s ticks every %dms, last at %lld.\n",overlay_interfaces[i].name,
|
||||
overlay_interfaces[i].tick_ms,overlay_interfaces[i].last_tick_ms);
|
||||
if (now>=overlay_interfaces[i].last_tick_ms+overlay_interfaces[i].tick_ms)
|
||||
{
|
||||
@ -551,7 +556,7 @@ int overlay_check_ticks()
|
||||
}
|
||||
}
|
||||
else
|
||||
fprintf(stderr,"Interface %s is awol.\n",overlay_interfaces[i].name);
|
||||
if (debug&4)fprintf(stderr,"Interface %s is awol.\n",overlay_interfaces[i].name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -568,12 +573,12 @@ long long overlay_time_until_next_tick()
|
||||
now=tv.tv_sec*1000LL+tv.tv_usec/1000;
|
||||
|
||||
int i;
|
||||
fprintf(stderr,"Tick-check on %d interfaces at %lldms\n",overlay_interface_count,now);
|
||||
if (debug&4)fprintf(stderr,"Tick-check on %d interfaces at %lldms\n",overlay_interface_count,now);
|
||||
for(i=0;i<overlay_interface_count;i++)
|
||||
if (overlay_interfaces[i].observed>0)
|
||||
{
|
||||
fprintf(stderr,"Interface %s ticks every %dms, last at %lld.\n",overlay_interfaces[i].name,
|
||||
overlay_interfaces[i].tick_ms,overlay_interfaces[i].last_tick_ms);
|
||||
if (debug&4) fprintf(stderr,"Interface %s ticks every %dms, last at T-%lldms.\n",overlay_interfaces[i].name,
|
||||
overlay_interfaces[i].tick_ms,now-overlay_interfaces[i].last_tick_ms);
|
||||
|
||||
long long thistick=(overlay_interfaces[i].last_tick_ms+overlay_interfaces[i].tick_ms)-now;
|
||||
if (thistick<0) thistick=0;
|
||||
|
43
server.c
43
server.c
@ -61,49 +61,8 @@ int server(char *backing_file,int size,int foregroundMode)
|
||||
if (!foregroundMode) daemon(0,0);
|
||||
|
||||
if (!overlayMode) simpleServerMode();
|
||||
else {
|
||||
/* In overlay mode we need to listen to all of our sockets, and also to
|
||||
send periodic traffic. This means we need to */
|
||||
fprintf(stderr,"Running in overlay mode.\n");
|
||||
else overlayServerMode();
|
||||
|
||||
/* Get the set of socket file descriptors we need to monitor */
|
||||
int i;
|
||||
fd_set read_fds;
|
||||
int maxfd=-1;
|
||||
FD_ZERO(&read_fds);
|
||||
for(i=0;i<overlay_interface_count;i++)
|
||||
{
|
||||
if (overlay_interfaces[i].socket>maxfd) maxfd=overlay_interfaces[i].socket;
|
||||
FD_SET(overlay_interfaces[i].socket,&read_fds);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
/* Work out how long we can wait before we need to tick */
|
||||
long long ms=overlay_time_until_next_tick();
|
||||
struct timeval waittime;
|
||||
waittime.tv_usec=(ms%1000)*1000;
|
||||
waittime.tv_sec=ms/1000;
|
||||
|
||||
fprintf(stderr,"%d,%d\n",(int)waittime.tv_sec,waittime.tv_usec);
|
||||
int r=select(maxfd+1,&read_fds,NULL,NULL,&waittime);
|
||||
if (r<0) {
|
||||
/* select had a problem */
|
||||
perror("select()");
|
||||
return WHY("select() complained.");
|
||||
} else if (r>0) {
|
||||
/* We have data, so try to receive it */
|
||||
fprintf(stderr,"select() reports packets waiting\n");
|
||||
overlay_rx_messages();
|
||||
} else {
|
||||
/* No data before tick occurred, so do nothing.
|
||||
Well, for now let's just check anyway. */
|
||||
fprintf(stderr,"select() timeout.\n");
|
||||
overlay_rx_messages();
|
||||
}
|
||||
/* Check if we need to trigger any ticks on any interfaces */
|
||||
overlay_check_ticks();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user