mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-02-21 01:42:18 +00:00
core of overlay mode getting closer.
Compiles. With -N start to try to send regular packets.
This commit is contained in:
parent
6e172c76c9
commit
92768cdcd0
4
Makefile
4
Makefile
@ -1,10 +1,10 @@
|
||||
SRCS= dna.c server.c client.c peers.c ciphers.c responses.c packetformats.c dataformats.c \
|
||||
hlrdata.c srandomdev.c simulate.c batman.c export.c gateway.c \
|
||||
overlay.c overlay_buffer.c overlay_interface.c
|
||||
overlay.c overlay_buffer.c overlay_interface.c overlay_payload.c overlay_route.c
|
||||
|
||||
OBJS= dna.o server.o client.o peers.o ciphers.o responses.o packetformats.o dataformats.o \
|
||||
hlrdata.o srandomdev.o simulate.o batman.o export.o gateway.o \
|
||||
overlay.o overlay_buffer.o overlay_interface.o
|
||||
overlay.o overlay_buffer.o overlay_interface.o overlay_payload.o overlay_route.o
|
||||
HDRS= Makefile mphlr.h
|
||||
LDFLAGS= -L/Developer/SDKs/MacOSX10.6.sdk/usr/lib
|
||||
CFLAGS= -I/Developer/SDKs/MacOSX10.6.sdk/usr/include
|
||||
|
@ -1,10 +1,10 @@
|
||||
SRCS= dna.c server.c client.c peers.c ciphers.c responses.c packetformats.c dataformats.c \
|
||||
hlrdata.c srandomdev.c simulate.c batman.c export.c gateway.c \
|
||||
overlay.c overlay_buffer.c overlay_interface.c
|
||||
overlay.c overlay_buffer.c overlay_interface.c overlay_payload.c overlay_route.c
|
||||
|
||||
OBJS= dna.o server.o client.o peers.o ciphers.o responses.o packetformats.o dataformats.o \
|
||||
hlrdata.o srandomdev.o simulate.o batman.o export.o gateway.o \
|
||||
overlay.o overlay_buffer.o overlay_interface.o
|
||||
overlay.o overlay_buffer.o overlay_interface.o overlay_payload.o overlay_route.o
|
||||
HDRS= Makefile mphlr.h
|
||||
LDFLAGS= @LDFLAGS@
|
||||
CFLAGS= @CFLAGS@
|
||||
|
1
dna.c
1
dna.c
@ -291,6 +291,7 @@ int main(int argc,char **argv)
|
||||
case 'N': /* Ask for overlay network to setup one or more interfaces */
|
||||
if (overlay_interface_args(optarg))
|
||||
return WHY("Invalid interface specification(s) passed to -N");
|
||||
overlayMode=1;
|
||||
break;
|
||||
case 'G': /* Offer gateway services */
|
||||
gatewayuri=strdup(optarg);
|
||||
|
30
mphlr.h
30
mphlr.h
@ -71,9 +71,9 @@ struct in_addr {
|
||||
//FIXME #include <getopt.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* UDP Port numbers for various Serval services */
|
||||
/* UDP Port numbers for various Serval services.
|
||||
The overlay mesh works over DNA */
|
||||
#define PORT_DNA 4110
|
||||
#define PORT_OVERLAY 4119
|
||||
|
||||
/* OpenWRT libc doesn't have bcopy, but has memmove */
|
||||
#define bcopy(A,B,C) memmove(B,A,C)
|
||||
@ -351,6 +351,7 @@ int asteriskObtainGateway(char *requestor_sid,char *did,char *uri_out);
|
||||
#define CRYPT_SIGNED 2
|
||||
#define CRYPT_PUBLIC 4
|
||||
|
||||
extern int overlayMode;
|
||||
#define OVERLAY_INTERFACE_UNKNOWN 0
|
||||
#define OVERLAY_INTERFACE_ETHERNET 1
|
||||
#define OVERLAY_INTERFACE_WIFI 2
|
||||
@ -372,6 +373,17 @@ typedef struct overlay_interface {
|
||||
These figures will be refined over time, and we will allow people to set them per-interface.
|
||||
*/
|
||||
int tick_ms;
|
||||
/* The time of the last tick on this interface in milli seconds */
|
||||
long long last_tick_ms;
|
||||
|
||||
/* Broadcast address and netmask, if known */
|
||||
struct sockaddr_in broadcast_address;
|
||||
struct sockaddr_in netmask;
|
||||
|
||||
/* Not necessarily the real MTU, but the largest frame size we are willing to TX on this interface.
|
||||
For radio links the actual maximum and the maximum that is likely to be delivered reliably are
|
||||
potentially two quite different values. */
|
||||
int mtu;
|
||||
} overlay_interface;
|
||||
|
||||
/* Maximum interface count is rather arbitrary.
|
||||
@ -473,6 +485,9 @@ typedef struct overlay_payload {
|
||||
/* make the payload pointer be at the end, so that we can conveniently have the data follow this structure if necessary.
|
||||
(this lets us change the char * to a char payload[1] down the track to simplify this) */
|
||||
unsigned char *payload;
|
||||
|
||||
/* time this frame was enqueued */
|
||||
long long enqueued_at;
|
||||
} overlay_payload;
|
||||
|
||||
typedef struct overlay_txqueue {
|
||||
@ -514,6 +529,17 @@ int ob_append_bytes(overlay_buffer *b,unsigned char *bytes,int count);
|
||||
int ob_append_short(overlay_buffer *b,unsigned short v);
|
||||
int ob_append_int(overlay_buffer *b,unsigned int v);
|
||||
|
||||
int op_free(overlay_payload *p);
|
||||
|
||||
long long parse_quantity(char *q);
|
||||
|
||||
int overlay_init_interface(in_addr_t src_addr,int speed_in_bits,int port,int type);
|
||||
int overlay_interface_discover();
|
||||
int overlay_interface_discover();
|
||||
long long overlay_time_until_next_tick();
|
||||
int overlay_rx_messages();
|
||||
int overlay_check_ticks();
|
||||
int overlay_add_selfannouncement();
|
||||
int overlay_payload_package_fmt1(overlay_payload *p,overlay_buffer *b);
|
||||
|
||||
extern int overlay_interface_count;
|
||||
|
110
overlay.c
110
overlay.c
@ -37,117 +37,15 @@
|
||||
frames from every call if we know that this can be safely done. That is, when traffic is low, we maximise redundancy, and when we
|
||||
start to hit the limit of traffic, we start to throw away some of the redundancy. This of course relies on us knowing when the
|
||||
network channel is getting too full.
|
||||
|
||||
This file currently seems to exist solely to contain this introduction, which is fine with me. Functions land in here until their
|
||||
proper place becomes apparent.
|
||||
|
||||
*/
|
||||
|
||||
#include "mphlr.h"
|
||||
|
||||
int overlay_socket=-1;
|
||||
|
||||
int ob_unlimitsize(overlay_buffer *b);
|
||||
int overlayMode=0;
|
||||
|
||||
overlay_txqueue overlay_tx[4];
|
||||
|
||||
|
||||
int overlay_payload_verify()
|
||||
{
|
||||
/* Make sure that an incoming payload has a valid signature from the sender.
|
||||
This is used to prevent spoofing */
|
||||
|
||||
return WHY("function not implemented");
|
||||
}
|
||||
|
||||
|
||||
int overlay_get_nexthop(overlay_payload *p,unsigned char *hopout,int *hopaddrlen)
|
||||
{
|
||||
return WHY("function not implemented");
|
||||
}
|
||||
|
||||
int overlay_payload_package_fmt1(overlay_payload *p,overlay_buffer *b)
|
||||
{
|
||||
/* Convert a payload structure into a series of bytes.
|
||||
Also select next-hop address to help payload get to its' destination */
|
||||
|
||||
unsigned char nexthop[SIDDIDFIELD_LEN+1];
|
||||
int nexthoplen=0;
|
||||
|
||||
overlay_buffer *headers=ob_new(256);
|
||||
|
||||
if (!headers) return WHY("could not allocate overlay buffer for headers");
|
||||
if (!p) return WHY("p is NULL");
|
||||
if (!b) return WHY("b is NULL");
|
||||
|
||||
/* Build header */
|
||||
int fail=0;
|
||||
|
||||
if (overlay_get_nexthop(p,nexthop,&nexthoplen)) fail++;
|
||||
if (ob_append_bytes(headers,nexthop,nexthoplen)) fail++;
|
||||
|
||||
/* XXX Can use shorter fields for different address types, and if we know that the next hop
|
||||
knows a short-hand for the address.
|
||||
XXX Need a prefix byte for the type of address being used.
|
||||
BETTER - We just insist that the first byte of Curve25519 addresses be >0x0f, and use
|
||||
the low numbers for special cases:
|
||||
|
||||
*/
|
||||
if (p->src[0]<0x10||p->dst[0]<0x10) {
|
||||
// Make sure that addresses do not overload the special address spaces of 0x00*-0x0f*
|
||||
fail++;
|
||||
return WHY("address begins with reserved value 0x00-0x0f");
|
||||
}
|
||||
if (ob_append_bytes(headers,(unsigned char *)p->src,SIDDIDFIELD_LEN)) fail++;
|
||||
if (ob_append_bytes(headers,(unsigned char *)p->dst,SIDDIDFIELD_LEN)) fail++;
|
||||
|
||||
if (fail) {
|
||||
ob_free(headers);
|
||||
return WHY("failure count was non-zero");
|
||||
}
|
||||
|
||||
/* Write payload format plus total length of header bits */
|
||||
if (ob_makespace(b,2+headers->length+p->payloadLength)) {
|
||||
/* Not enough space free in output buffer */
|
||||
ob_free(headers);
|
||||
return WHY("Could not make enough space free in output buffer");
|
||||
}
|
||||
|
||||
/* Package up headers and payload */
|
||||
ob_checkpoint(b);
|
||||
if (ob_append_short(b,0x1000|(p->payloadLength+headers->length)))
|
||||
{ fail++; WHY("could not append version and length bytes"); }
|
||||
if (ob_append_bytes(b,headers->bytes,headers->length))
|
||||
{ fail++; WHY("could not append header"); }
|
||||
if (ob_append_bytes(b,p->payload,p->payloadLength))
|
||||
{ fail++; WHY("could not append payload"); }
|
||||
|
||||
/* XXX SIGN &/or ENCRYPT */
|
||||
|
||||
ob_free(headers);
|
||||
|
||||
if (fail) { ob_rewind(b); return WHY("failure count was non-zero"); } else return 0;
|
||||
}
|
||||
|
||||
overlay_payload *overlay_payload_unpackage(overlay_buffer *b) {
|
||||
/* Extract the payload at the current location in the buffer. */
|
||||
|
||||
WHY("not implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int overlay_payload_enqueue(int q,overlay_payload *p,int urgentP)
|
||||
{
|
||||
/* Add payload p to queue q.
|
||||
If urgentP is set, then ask for the payload queue to be sent now.
|
||||
*/
|
||||
|
||||
return WHY("not implemented");
|
||||
if (urgentP) overlay_push_queued();
|
||||
}
|
||||
|
||||
int overlay_push_queued()
|
||||
{
|
||||
/* Try to send frames.
|
||||
The trick here is that we need to aggregate payloads based on which interface they need to go to */
|
||||
|
||||
return WHY("not implemented");
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
#include "mphlr.h"
|
||||
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
int overlay_ready=0;
|
||||
int overlay_interface_count=0;
|
||||
overlay_interface overlay_interfaces[OVERLAY_MAX_INTERFACES];
|
||||
@ -108,6 +112,12 @@ int overlay_init_interface(in_addr_t src_addr,int speed_in_bits,int port,int typ
|
||||
I(bits_per_second)=speed_in_bits;
|
||||
I(port)=bind_addr.sin_port;
|
||||
I(type)=type;
|
||||
I(tick_ms)=500;
|
||||
switch(type) {
|
||||
case OVERLAY_INTERFACE_PACKETRADIO: I(tick_ms)=15000; break;
|
||||
case OVERLAY_INTERFACE_ETHERNET: I(tick_ms)=500; break;
|
||||
case OVERLAY_INTERFACE_WIFI: I(tick_ms)=500; break;
|
||||
}
|
||||
|
||||
overlay_interface_count++;
|
||||
#undef I(X)
|
||||
@ -126,7 +136,7 @@ int overlay_rx_messages()
|
||||
{
|
||||
}
|
||||
|
||||
return 0;
|
||||
return WHY("Not implemented");
|
||||
}
|
||||
|
||||
int overlay_tx_messages()
|
||||
@ -147,14 +157,14 @@ int overlay_tx_messages()
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_broadcast_ensemble(int interface_number,char *bytes,int len)
|
||||
int overlay_broadcast_ensemble(int interface_number,unsigned char *bytes,int len)
|
||||
{
|
||||
struct sockaddr_in s;
|
||||
|
||||
memset(&s, '\0', sizeof(struct sockaddr_in));
|
||||
s = overlay_interfaces[interface_number].broadcast_address;
|
||||
s.sin_family = AF_INET;
|
||||
s.sin_port = htons( PORT_OVERLAY );
|
||||
s.sin_addr.s_addr = htonl( INADDR_BROADCAST );
|
||||
s.sin_port = htons( overlay_interfaces[interface_number].port );
|
||||
|
||||
if(sendto(overlay_interfaces[interface_number].socket, bytes, len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) < 0)
|
||||
/* Failed to send */
|
||||
@ -163,3 +173,182 @@ int overlay_broadcast_ensemble(int interface_number,char *bytes,int len)
|
||||
/* Sent okay */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_interface_discover()
|
||||
{
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
struct ifaddrs *ifaddr,*ifa;
|
||||
int family;
|
||||
|
||||
if (getifaddrs(&ifaddr) == -1) {
|
||||
perror("getifaddr()");
|
||||
return WHY("getifaddrs() failed");
|
||||
}
|
||||
|
||||
for (ifa=ifaddr;ifa!=NULL;ifa=ifa->ifa_next) {
|
||||
family=ifa->ifa_addr->sa_family;
|
||||
switch(family) {
|
||||
case AF_INET:
|
||||
{
|
||||
unsigned char *name=(unsigned char *)ifa->ifa_name;
|
||||
unsigned int local=(((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr);
|
||||
unsigned int netmask=(((struct sockaddr_in *)(ifa->ifa_netmask))->sin_addr.s_addr);
|
||||
unsigned int broadcast=local|~netmask;
|
||||
printf("%s: %08x %08x %08x\n",name,local,netmask,broadcast);
|
||||
/* XXX now register the interface, or update the existing interface registration */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_tick_interface(int i, long long now)
|
||||
{
|
||||
int frame_pax=0;
|
||||
#define MAX_FRAME_PAX 1024
|
||||
overlay_payload *pax[MAX_FRAME_PAX];
|
||||
|
||||
if (overlay_interfaces[i].bits_per_second<1) {
|
||||
/* An interface with no speed budget is for listening only, so doesn't get ticked */
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr,"Ticking interface #%d\n",i);
|
||||
|
||||
/* Get a buffer ready, and limit it's size appropriately.
|
||||
XXX size limit should be reduced from MTU.
|
||||
XXX we should also take account of the volume of data likely to be in the TX buffer. */
|
||||
overlay_buffer *e=ob_new(overlay_interfaces[i].mtu);
|
||||
if (!e) return WHY("ob_new() failed");
|
||||
ob_limitsize(e,overlay_interfaces[i].mtu);
|
||||
|
||||
/* 0. Setup Serval Mesh frame header. We do not use an explicit length field for these, as the various
|
||||
component payloads are all self-authenticating, or at least that is the theory. */
|
||||
unsigned char bytes[]={/* Magic */ 'O',0x10,
|
||||
/* Version */ 0x00,0x01};
|
||||
ob_append_bytes(e,bytes,4);
|
||||
|
||||
/* 1. Send announcement about ourselves, including one SID that we host if we host more than one SID
|
||||
(the first SID we host becomes our own identity, saving a little bit of data here).
|
||||
*/
|
||||
overlay_add_selfannouncement(i,e);
|
||||
|
||||
/* 2. Add any queued high-priority isochronous data (i.e. voice) to the frame. */
|
||||
overlay_payload **p=&overlay_tx[OVERLAY_ISOCHRONOUS_VOICE].first;
|
||||
while(p)
|
||||
{
|
||||
/* Throw away any stale frames */
|
||||
overlay_payload *pp=*p;
|
||||
|
||||
if (!pp) break;
|
||||
|
||||
if (now>((*p)->enqueued_at+200)) {
|
||||
/* Stale, so remove from queue */
|
||||
*p=pp->next;
|
||||
pp->next->prev=*p;
|
||||
op_free(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX Filter for those which should be sent via this interface.
|
||||
To do that we need to know the nexthop, and the best route to the next hop. */
|
||||
|
||||
/* We keep trying to queue frames in case they will fit, as not all frames are of equal size.
|
||||
This means that lower bit-rate codecs will get higher priority, which is probably not all
|
||||
bad. The only hard limit is the maximum number of payloads we allow in a frame, which is
|
||||
set so high as to be irrelevant, even on loopback or gigabit ethernet interface */
|
||||
if (frame_pax>=MAX_FRAME_PAX) break;
|
||||
if (!overlay_payload_package_fmt1(*p,e))
|
||||
{
|
||||
/* Add payload to list of payloads we are sending with this frame so that we can dequeue them
|
||||
if we send them. */
|
||||
pax[frame_pax++]=*p;
|
||||
}
|
||||
p=&(*p)->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* 3. Add some mesh reachability reports (unlike BATMAN we announce reachability to peers progressively).
|
||||
Give priority to newly observed nodes so that good news travels quickly to help roaming.
|
||||
XXX - Don't forget about PONGing reachability reports to allow use of monodirectional links.
|
||||
*/
|
||||
|
||||
/* 4. XXX Add lower-priority queued data */
|
||||
|
||||
/* 5. XXX Fill the packet up to a suitable size with anything that seems a good idea */
|
||||
|
||||
/* Now send the frame. This takes the form of a special DNA packet with a different
|
||||
service code, which we setup earlier. */
|
||||
if (!overlay_broadcast_ensemble(i,e->bytes,e->length))
|
||||
{
|
||||
fprintf(stderr,"Successfully transmitted tick frame on interface #%d\n",i);
|
||||
/* De-queue the passengers who were aboard. */
|
||||
int j;
|
||||
overlay_payload **p=&overlay_tx[OVERLAY_ISOCHRONOUS_VOICE].first;
|
||||
for(j=0;j<frame_pax;j++)
|
||||
{
|
||||
/* Skip any frames that didn't get queued */
|
||||
while ((*p)&&(*p!=pax[j])) p=&(*p)->next;
|
||||
/* Now get rid of this frame once we have found it */
|
||||
if (*p) {
|
||||
*p=pax[j]->next;
|
||||
if (pax[j]->next) pax[j]->next->prev=pax[j]->prev;
|
||||
if (op_free(pax[j])) WHY("op_free() failed");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else WHY("overlay_broadcast_ensemble() failed");
|
||||
}
|
||||
|
||||
int overlay_check_ticks()
|
||||
{
|
||||
/* Check if any interface(s) are due for a tick */
|
||||
int i;
|
||||
struct timeval nowtv;
|
||||
long long now;
|
||||
|
||||
if (gettimeofday(&nowtv,NULL))
|
||||
return WHY("gettimeofday() failed");
|
||||
|
||||
/* Get current time in milliseconds */
|
||||
now=nowtv.tv_sec*1000;
|
||||
now=now+nowtv.tv_usec/1000;
|
||||
|
||||
/* Now check if the next tick time for the interfaces is no later than that time.
|
||||
If so, trigger a tick on the interface. */
|
||||
for(i=0;i<overlay_interface_count;i++)
|
||||
{
|
||||
if (now>=overlay_interfaces[i].last_tick_ms+overlay_interfaces[i].tick_ms)
|
||||
{
|
||||
/* This interface is due for a tick */
|
||||
overlay_tick_interface(i,now);
|
||||
overlay_interfaces[i].last_tick_ms=now;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long long overlay_time_until_next_tick()
|
||||
{
|
||||
/* By default only tick once per day */
|
||||
long long nexttick=86400*1000;
|
||||
long long now;
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv,NULL);
|
||||
now=tv.tv_sec*1000+tv.tv_usec/1000;
|
||||
|
||||
int i;
|
||||
for(i=0;i<overlay_interface_count;i++)
|
||||
{
|
||||
long long thistick=(overlay_interfaces[i].last_tick_ms+overlay_interfaces[i].tick_ms)-now;
|
||||
if (thistick<0) thistick=0;
|
||||
if (thistick<nexttick) nexttick=thistick;
|
||||
}
|
||||
|
||||
return nexttick;
|
||||
}
|
||||
|
100
overlay_payload.c
Normal file
100
overlay_payload.c
Normal file
@ -0,0 +1,100 @@
|
||||
#include "mphlr.h"
|
||||
|
||||
int overlay_payload_verify(overlay_payload *p)
|
||||
{
|
||||
/* Make sure that an incoming payload has a valid signature from the sender.
|
||||
This is used to prevent spoofing */
|
||||
|
||||
return WHY("function not implemented");
|
||||
}
|
||||
|
||||
int overlay_payload_package_fmt1(overlay_payload *p,overlay_buffer *b)
|
||||
{
|
||||
/* Convert a payload structure into a series of bytes.
|
||||
Also select next-hop address to help payload get to its' destination */
|
||||
|
||||
unsigned char nexthop[SIDDIDFIELD_LEN+1];
|
||||
int nexthoplen=0;
|
||||
|
||||
overlay_buffer *headers=ob_new(256);
|
||||
|
||||
if (!headers) return WHY("could not allocate overlay buffer for headers");
|
||||
if (!p) return WHY("p is NULL");
|
||||
if (!b) return WHY("b is NULL");
|
||||
|
||||
/* Build header */
|
||||
int fail=0;
|
||||
|
||||
if (overlay_get_nexthop(p,nexthop,&nexthoplen)) fail++;
|
||||
if (ob_append_bytes(headers,nexthop,nexthoplen)) fail++;
|
||||
|
||||
/* XXX Can use shorter fields for different address types, and if we know that the next hop
|
||||
knows a short-hand for the address.
|
||||
XXX Need a prefix byte for the type of address being used.
|
||||
BETTER - We just insist that the first byte of Curve25519 addresses be >0x0f, and use
|
||||
the low numbers for special cases:
|
||||
|
||||
*/
|
||||
if (p->src[0]<0x10||p->dst[0]<0x10) {
|
||||
// Make sure that addresses do not overload the special address spaces of 0x00*-0x0f*
|
||||
fail++;
|
||||
return WHY("address begins with reserved value 0x00-0x0f");
|
||||
}
|
||||
if (ob_append_bytes(headers,(unsigned char *)p->src,SIDDIDFIELD_LEN)) fail++;
|
||||
if (ob_append_bytes(headers,(unsigned char *)p->dst,SIDDIDFIELD_LEN)) fail++;
|
||||
|
||||
if (fail) {
|
||||
ob_free(headers);
|
||||
return WHY("failure count was non-zero");
|
||||
}
|
||||
|
||||
/* Write payload format plus total length of header bits */
|
||||
if (ob_makespace(b,2+headers->length+p->payloadLength)) {
|
||||
/* Not enough space free in output buffer */
|
||||
ob_free(headers);
|
||||
return WHY("Could not make enough space free in output buffer");
|
||||
}
|
||||
|
||||
/* Package up headers and payload */
|
||||
ob_checkpoint(b);
|
||||
if (ob_append_short(b,0x1000|(p->payloadLength+headers->length)))
|
||||
{ fail++; WHY("could not append version and length bytes"); }
|
||||
if (ob_append_bytes(b,headers->bytes,headers->length))
|
||||
{ fail++; WHY("could not append header"); }
|
||||
if (ob_append_bytes(b,p->payload,p->payloadLength))
|
||||
{ fail++; WHY("could not append payload"); }
|
||||
|
||||
/* XXX SIGN &/or ENCRYPT */
|
||||
|
||||
ob_free(headers);
|
||||
|
||||
if (fail) { ob_rewind(b); return WHY("failure count was non-zero"); } else return 0;
|
||||
}
|
||||
|
||||
overlay_payload *overlay_payload_unpackage(overlay_buffer *b) {
|
||||
/* Extract the payload at the current location in the buffer. */
|
||||
|
||||
WHY("not implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int overlay_payload_enqueue(int q,overlay_payload *p)
|
||||
{
|
||||
/* Add payload p to queue q.
|
||||
*/
|
||||
|
||||
return WHY("not implemented");
|
||||
}
|
||||
|
||||
int op_free(overlay_payload *p)
|
||||
{
|
||||
if (!p) return WHY("Asked to free NULL");
|
||||
if (p->prev&&p->prev->next==p) return WHY("p->prev->next still points here");
|
||||
if (p->next&&p->next->prev==p) return WHY("p->next->prev still points here");
|
||||
p->prev=NULL;
|
||||
p->next=NULL;
|
||||
if (p->payload) free(p->payload);
|
||||
p->payload=NULL;
|
||||
free(p);
|
||||
return 0;
|
||||
}
|
11
overlay_route.c
Normal file
11
overlay_route.c
Normal file
@ -0,0 +1,11 @@
|
||||
#include "mphlr.h"
|
||||
|
||||
int overlay_add_selfannouncement(overlay_buffer *b)
|
||||
{
|
||||
return WHY("Not implemented");
|
||||
}
|
||||
|
||||
int overlay_get_nexthop(overlay_payload *p,unsigned char *nexthop,int *nexthoplen)
|
||||
{
|
||||
return WHY("Not implemented");
|
||||
}
|
195
server.c
195
server.c
@ -28,13 +28,85 @@ struct sockaddr recvaddr;
|
||||
struct in_addr client_addr;
|
||||
int client_port;
|
||||
|
||||
int getBackingStore(char *s,int size);
|
||||
int createServerSocket();
|
||||
int simpleServerMode();
|
||||
|
||||
|
||||
int server(char *backing_file,int size,int foregroundMode)
|
||||
{
|
||||
|
||||
struct sockaddr_in bind_addr;
|
||||
|
||||
/* Get backing store */
|
||||
if (!backing_file)
|
||||
/* Get backing store for HLR */
|
||||
getBackingStore(backing_file,size);
|
||||
|
||||
if (overlayMode)
|
||||
{
|
||||
/* Now find and initialise all the suitable network interfaces, i.e.,
|
||||
those running IPv4.
|
||||
Packet radio dongles will get discovered later as the interfaces get probed.
|
||||
|
||||
This will setup the sockets for the server to communicate on each interface.
|
||||
|
||||
XXX - Problems may persist where the same address is used on multiple interfaces,
|
||||
but otherwise hopefully it will allow us to bridge multiple networks.
|
||||
*/
|
||||
overlay_interface_discover();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create a simple socket for listening on if we are not in overlay mesh mode. */
|
||||
createServerSocket();
|
||||
}
|
||||
|
||||
/* Detach from the console */
|
||||
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");
|
||||
|
||||
/* 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",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 */
|
||||
overlay_rx_messages();
|
||||
} else {
|
||||
/* No data before tick occurred, so do nothing. */
|
||||
}
|
||||
/* Check if we need to trigger any ticks on any interfaces */
|
||||
overlay_check_ticks();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getBackingStore(char *backing_file,int size)
|
||||
{
|
||||
if (!backing_file)
|
||||
{
|
||||
/* transitory storage of HLR data, so just malloc() the memory */
|
||||
hlr=calloc(size,1);
|
||||
@ -77,60 +149,7 @@ int server(char *backing_file,int size,int foregroundMode)
|
||||
size,backing_file);
|
||||
}
|
||||
hlr_size=size;
|
||||
|
||||
|
||||
sock=socket(PF_INET,SOCK_DGRAM,0);
|
||||
if (sock<0) {
|
||||
fprintf(stderr,"Could not create UDP socket.\n");
|
||||
perror("socket");
|
||||
exit(-3);
|
||||
}
|
||||
|
||||
int TRUE=1;
|
||||
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &TRUE, sizeof(TRUE));
|
||||
|
||||
bind_addr.sin_family = AF_INET;
|
||||
bind_addr.sin_port = htons( PORT_DNA );
|
||||
bind_addr.sin_addr.s_addr = htonl( INADDR_ANY );
|
||||
if(bind(sock,(struct sockaddr *)&bind_addr,sizeof(bind_addr))) {
|
||||
fprintf(stderr,"MP HLR server could not bind to UDP port %d\n", PORT_DNA);
|
||||
perror("bind");
|
||||
exit(-3);
|
||||
}
|
||||
|
||||
/* Detach from the console */
|
||||
if (!foregroundMode) daemon(0,0);
|
||||
|
||||
while(1) {
|
||||
unsigned char buffer[16384];
|
||||
socklen_t recvaddrlen=sizeof(recvaddr);
|
||||
struct pollfd fds;
|
||||
int len;
|
||||
|
||||
bzero((void *)&recvaddr,sizeof(recvaddr));
|
||||
fds.fd=sock; fds.events=POLLIN;
|
||||
|
||||
/* Wait patiently for packets to arrive */
|
||||
while (poll(&fds,1,1000)<1) sleep(0);
|
||||
|
||||
len=recvfrom(sock,buffer,sizeof(buffer),0,&recvaddr,&recvaddrlen);
|
||||
|
||||
client_port=((struct sockaddr_in*)&recvaddr)->sin_port;
|
||||
client_addr=((struct sockaddr_in*)&recvaddr)->sin_addr;
|
||||
|
||||
if (debug) fprintf(stderr,"Received packet from %s (len=%d).\n",inet_ntoa(client_addr),len);
|
||||
if (debug>1) dump("recvaddr",(unsigned char *)&recvaddr,recvaddrlen);
|
||||
if (debug>3) dump("packet",(unsigned char *)buffer,len);
|
||||
if (dropPacketP(len)) {
|
||||
if (debug) fprintf(stderr,"Simulation mode: Dropped packet due to simulated link parameters.\n");
|
||||
continue;
|
||||
}
|
||||
if (!packetOk(buffer,len,NULL)) process_packet(buffer,len,&recvaddr,recvaddrlen);
|
||||
else {
|
||||
if (debug) setReason("Ignoring invalid packet");
|
||||
}
|
||||
if (debug>1) fprintf(stderr,"Finished processing packet, waiting for next one.\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int processRequest(unsigned char *packet,int len,
|
||||
@ -493,3 +512,63 @@ int respondSimple(char *sid,int action,unsigned char *action_text,int action_len
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int createServerSocket()
|
||||
{
|
||||
struct sockaddr_in bind_addr;
|
||||
|
||||
sock=socket(PF_INET,SOCK_DGRAM,0);
|
||||
if (sock<0) {
|
||||
fprintf(stderr,"Could not create UDP socket.\n");
|
||||
perror("socket");
|
||||
exit(-3);
|
||||
}
|
||||
|
||||
int TRUE=1;
|
||||
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &TRUE, sizeof(TRUE));
|
||||
|
||||
bind_addr.sin_family = AF_INET;
|
||||
bind_addr.sin_port = htons( PORT_DNA );
|
||||
bind_addr.sin_addr.s_addr = htonl( INADDR_ANY );
|
||||
if(bind(sock,(struct sockaddr *)&bind_addr,sizeof(bind_addr))) {
|
||||
fprintf(stderr,"MP HLR server could not bind to UDP port %d\n", PORT_DNA);
|
||||
perror("bind");
|
||||
exit(-3);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int simpleServerMode()
|
||||
{
|
||||
while(1) {
|
||||
unsigned char buffer[16384];
|
||||
socklen_t recvaddrlen=sizeof(recvaddr);
|
||||
struct pollfd fds;
|
||||
int len;
|
||||
|
||||
bzero((void *)&recvaddr,sizeof(recvaddr));
|
||||
fds.fd=sock; fds.events=POLLIN;
|
||||
|
||||
/* Wait patiently for packets to arrive */
|
||||
while (poll(&fds,1,1000)<1) sleep(0);
|
||||
|
||||
len=recvfrom(sock,buffer,sizeof(buffer),0,&recvaddr,&recvaddrlen);
|
||||
|
||||
client_port=((struct sockaddr_in*)&recvaddr)->sin_port;
|
||||
client_addr=((struct sockaddr_in*)&recvaddr)->sin_addr;
|
||||
|
||||
if (debug) fprintf(stderr,"Received packet from %s (len=%d).\n",inet_ntoa(client_addr),len);
|
||||
if (debug>1) dump("recvaddr",(unsigned char *)&recvaddr,recvaddrlen);
|
||||
if (debug>3) dump("packet",(unsigned char *)buffer,len);
|
||||
if (dropPacketP(len)) {
|
||||
if (debug) fprintf(stderr,"Simulation mode: Dropped packet due to simulated link parameters.\n");
|
||||
continue;
|
||||
}
|
||||
if (!packetOk(buffer,len,NULL)) process_packet(buffer,len,&recvaddr,recvaddrlen);
|
||||
else {
|
||||
if (debug) setReason("Ignoring invalid packet");
|
||||
}
|
||||
if (debug>1) fprintf(stderr,"Finished processing packet, waiting for next one.\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user