Refactor overlay buffer interface to support simple parsing

This commit is contained in:
Jeremy Lakeman 2012-08-22 10:21:38 +09:30
parent 22c6b530ed
commit f6c899e107
14 changed files with 460 additions and 421 deletions

View File

@ -82,6 +82,7 @@ MONITORCLIENTOBJS= $(MONITORCLIENTSRCS:.c=.o)
HDRS= fifo.h \ HDRS= fifo.h \
Makefile \ Makefile \
overlay_buffer.h \
rhizome.h \ rhizome.h \
serval.h \ serval.h \
strbuf.h \ strbuf.h \

View File

@ -1506,7 +1506,7 @@ int app_id_self(int argc, const char *const *argv, struct command_line_option *o
a.addrlist.mode = MDP_ADDRLIST_MODE_ROUTABLE_PEERS; /* get routable (reachable) peers */ a.addrlist.mode = MDP_ADDRLIST_MODE_ROUTABLE_PEERS; /* get routable (reachable) peers */
else else
return WHYF("unsupported arg '%s'", argv[1]); return WHYF("unsupported arg '%s'", argv[1]);
a.addrlist.first_sid=-1; a.addrlist.first_sid=0;
a.addrlist.last_sid=0x7fffffff; a.addrlist.last_sid=0x7fffffff;
a.addrlist.frame_sid_count=MDP_MAX_SID_REQUEST; a.addrlist.frame_sid_count=MDP_MAX_SID_REQUEST;

View File

@ -71,6 +71,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "serval.h" #include "serval.h"
#include "rhizome.h" #include "rhizome.h"
#include "strbuf.h" #include "strbuf.h"
#include "overlay_buffer.h"
int overlayMode=0; int overlayMode=0;
@ -199,8 +200,7 @@ int process_incoming_frame(time_ms_t now, struct overlay_interface *interface, o
overlay_saw_mdp_containing_frame(f,now); overlay_saw_mdp_containing_frame(f,now);
break; break;
default: default:
DEBUGF("Unsupported f->type=0x%x",f->type); return WHYF("Support for f->type=0x%x not yet implemented",f->type);
return WHY("Support for that f->type not yet implemented");
break; break;
} }
return 0; return 0;
@ -214,7 +214,7 @@ int overlay_frame_process(struct overlay_interface *interface,overlay_frame *f)
time_ms_t now = gettime_ms(); time_ms_t now = gettime_ms();
if (debug&DEBUG_OVERLAYFRAMES) if (debug&DEBUG_OVERLAYFRAMES)
DEBUGF(">>> Received frame (type=%02x, bytes=%d)",f->type,f->payload?f->payload->length:-1); DEBUGF(">>> Received frame (type=%02x, bytes=%d)",f->type,f->payload ? f->payload->sizeLimit:-1);
// only examine payloads that are broadcasts, or where I'm the next hop // only examine payloads that are broadcasts, or where I'm the next hop
if (overlay_address_is_broadcast(f->nexthop)) { if (overlay_address_is_broadcast(f->nexthop)) {

View File

@ -18,7 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#include "serval.h" #include "serval.h"
#include "overlay_buffer.h"
/* /*
We use 256bit Curve25519 addresses in the overlay mesh. This means we have very large We use 256bit Curve25519 addresses in the overlay mesh. This means we have very large
addresses to send around the place on a regular basis, which is bad. addresses to send around the place on a regular basis, which is bad.
@ -240,17 +240,17 @@ int overlay_abbreviate_try_byindex(unsigned char *in,unsigned char *out,int *ofs
return 1; return 1;
} }
int overlay_abbreviate_append_address(overlay_buffer *b,unsigned char *a) int overlay_abbreviate_append_address(struct overlay_buffer *b,unsigned char *a)
{ {
int count=0; int count=0;
ob_makespace(b,SID_SIZE+3); ob_makespace(b,SID_SIZE+3);
int r=overlay_abbreviate_address(a,&b->bytes[b->length],&count); int r=overlay_abbreviate_address(a,&b->bytes[b->position],&count);
if (debug&DEBUG_PACKETCONSTRUCTION) { if (debug&DEBUG_PACKETCONSTRUCTION) {
DEBUGF("address %s abbreviates as shown in this", alloca_tohex_sid(a)); DEBUGF("address %s abbreviates as shown in this", alloca_tohex_sid(a));
dump(NULL, &b->bytes[b->length], count); dump(NULL, &b->bytes[b->position], count);
} }
if (r) return r; if (r) return r;
b->length+=count; b->position+=count;
overlay_abbreviate_set_most_recent_address(a); overlay_abbreviate_set_most_recent_address(a);
return 0; return 0;
} }

View File

@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "serval.h" #include "serval.h"
#include "subscribers.h" #include "subscribers.h"
#include "overlay_buffer.h"
/* List of prioritised advertisements */ /* List of prioritised advertisements */
#define OVERLAY_MAX_ADVERTISEMENT_REQUESTS 16 #define OVERLAY_MAX_ADVERTISEMENT_REQUESTS 16
@ -59,7 +60,7 @@ int overlay_route_please_advertise(overlay_node *n)
struct subscriber *last_advertised=NULL; struct subscriber *last_advertised=NULL;
int add_advertisement(struct subscriber *subscriber, void *context){ int add_advertisement(struct subscriber *subscriber, void *context){
overlay_buffer *e=context; struct overlay_buffer *e=context;
if (subscriber->node){ if (subscriber->node){
overlay_node *n=subscriber->node; overlay_node *n=subscriber->node;
@ -84,7 +85,7 @@ int add_advertisement(struct subscriber *subscriber, void *context){
return 0; return 0;
} }
int overlay_route_add_advertisements(overlay_buffer *e) int overlay_route_add_advertisements(struct overlay_buffer *e)
{ {
/* Construct a route advertisement frame and append it to e. /* Construct a route advertisement frame and append it to e.
@ -113,12 +114,14 @@ int overlay_route_add_advertisements(overlay_buffer *e)
*/ */
int i; int i;
ob_checkpoint(e);
if (ob_append_byte(e,OF_TYPE_NODEANNOUNCE)) if (ob_append_byte(e,OF_TYPE_NODEANNOUNCE))
return WHY("could not add node advertisement header"); return WHY("could not add node advertisement header");
ob_append_byte(e,1); /* TTL */ ob_append_byte(e,1); /* TTL */
// assume we might fill the packet // assume we might fill the packet
ob_append_rfs(e, e->sizeLimit - e->length); ob_append_rfs(e, e->sizeLimit - e->position);
/* Stuff in dummy address fields */ /* Stuff in dummy address fields */
ob_append_byte(e,OA_CODE_BROADCAST); ob_append_byte(e,OA_CODE_BROADCAST);
@ -142,16 +145,22 @@ int overlay_route_add_advertisements(overlay_buffer *e)
} }
*/ */
struct subscriber *start = last_advertised; struct subscriber *start = last_advertised;
int start_pos = e->position;
// append announcements starting from the last node we advertised // append announcements starting from the last node we advertised
enum_subscribers(start, add_advertisement, e); enum_subscribers(start, add_advertisement, e);
// if we didn't start at the beginning and still have space, start again from the beginning // if we didn't start at the beginning and still have space, start again from the beginning
if (start && e->sizeLimit - e->length >=8){ if (start && e->sizeLimit - e->position >=8){
enum_subscribers(NULL, add_advertisement, e); enum_subscribers(NULL, add_advertisement, e);
} }
ob_patch_rfs(e,COMPUTE_RFS_LENGTH); if (e->position == start_pos){
// no advertisements? don't bother to send the payload at all.
ob_rewind(e);
overlay_abbreviate_clear_most_recent_address();
}else
ob_patch_rfs(e,COMPUTE_RFS_LENGTH);
return 0; return 0;
} }
@ -168,26 +177,30 @@ int overlay_route_add_advertisements(overlay_buffer *e)
*/ */
int overlay_route_saw_advertisements(int i,overlay_frame *f, long long now) int overlay_route_saw_advertisements(int i,overlay_frame *f, long long now)
{ {
int ofs=0;
IN(); IN();
while(ofs<f->payload->length) while(f->payload->position < f->payload->sizeLimit)
{ {
struct subscriber *subscriber; struct subscriber *subscriber;
unsigned char *sid = ob_get_bytes_ptr(f->payload, 6);
int score=ob_get(f->payload);
int gateways_en_route=ob_get(f->payload);
// stop if hit end of payload
if (!sid || score<0 || gateways_en_route<0)
continue;
subscriber = find_subscriber(sid, 6, 0);
subscriber = find_subscriber(&f->payload->bytes[ofs], 6, 0);
if (!subscriber){ if (!subscriber){
//WARN("Dispatch PLEASEEXPLAIN not implemented"); //WARN("Dispatch PLEASEEXPLAIN not implemented");
goto next; continue;
} }
int score=f->payload->bytes[ofs+6];
int gateways_en_route=f->payload->bytes[ofs+7];
/* Don't record routes to ourselves */ /* Don't record routes to ourselves */
if (overlay_address_is_local(subscriber->sid)) { if (overlay_address_is_local(subscriber->sid)) {
if (debug & DEBUG_OVERLAYROUTING) if (debug & DEBUG_OVERLAYROUTING)
DEBUGF("Ignore announcement about me (%s)", alloca_tohex_sid(subscriber->sid)); DEBUGF("Ignore announcement about me (%s)", alloca_tohex_sid(subscriber->sid));
goto next; continue;
} }
/* Don't let nodes advertise paths to themselves! /* Don't let nodes advertise paths to themselves!
@ -195,7 +208,7 @@ int overlay_route_saw_advertisements(int i,overlay_frame *f, long long now)
if (!memcmp(overlay_abbreviate_current_sender.b,subscriber->sid,SID_SIZE)){ if (!memcmp(overlay_abbreviate_current_sender.b,subscriber->sid,SID_SIZE)){
if (debug & DEBUG_OVERLAYROUTING) if (debug & DEBUG_OVERLAYROUTING)
DEBUGF("Ignore announcement about neighbour (%s)", alloca_tohex_sid(subscriber->sid)); DEBUGF("Ignore announcement about neighbour (%s)", alloca_tohex_sid(subscriber->sid));
goto next; continue;
} }
/* File it */ /* File it */
@ -206,8 +219,6 @@ int overlay_route_saw_advertisements(int i,overlay_frame *f, long long now)
now-2500,now, now-2500,now,
score,gateways_en_route); score,gateways_en_route);
next:
ofs+=8;
} }
RETURN(0);; RETURN(0);;

View File

@ -18,12 +18,23 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#include "serval.h" #include "serval.h"
#include "overlay_buffer.h"
overlay_buffer *ob_new(int size) /*
When writing to a buffer, sizeLimit may place an upper bound on the amount of space to use
When reading from a buffer, sizeLimit should first be set to the length of any existing data.
In either case, functions that don't take an offset use and advance the position.
*/
struct overlay_buffer *ob_new(void)
{ {
overlay_buffer *ret=calloc(sizeof(overlay_buffer),1); struct overlay_buffer *ret=calloc(sizeof(struct overlay_buffer),1);
if (!ret) return NULL; if (!ret) return NULL;
ob_unlimitsize(ret); ob_unlimitsize(ret);
return ret; return ret;
@ -31,19 +42,52 @@ overlay_buffer *ob_new(int size)
// index an existing static buffer. // index an existing static buffer.
// and allow other callers to use the ob_ convenience methods for reading and writing up to size bytes. // and allow other callers to use the ob_ convenience methods for reading and writing up to size bytes.
overlay_buffer *ob_static(unsigned char *bytes, int size){ struct overlay_buffer *ob_static(unsigned char *bytes, int size){
overlay_buffer *ret=calloc(sizeof(overlay_buffer),1); struct overlay_buffer *ret=calloc(sizeof(struct overlay_buffer),1);
if (!ret) return NULL; if (!ret) return NULL;
ret->bytes = bytes; ret->bytes = bytes;
ret->allocSize =-1; ret->allocSize = size;
ret->sizeLimit=size; ret->allocated = 0;
ob_unlimitsize(ret);
return ret; return ret;
} }
int ob_free(overlay_buffer *b) // create a new overlay buffer from an existing piece of another buffer.
// Both buffers will point to the same memory region.
// It is up to the caller to ensure this buffer is not used after the parent buffer is freed.
struct overlay_buffer *ob_slice(struct overlay_buffer *b, int offset, int length){
struct overlay_buffer *ret=calloc(sizeof(struct overlay_buffer),1);
if (!ret) return NULL;
ret->bytes = b->bytes+offset;
ret->allocSize = length;
ret->allocated = 0;
ob_unlimitsize(ret);
return ret;
}
struct overlay_buffer *ob_dup(struct overlay_buffer *b){
struct overlay_buffer *ret=calloc(sizeof(struct overlay_buffer),1);
ret->sizeLimit = b->sizeLimit;
ret->position = b->position;
ret->checkpointLength = b->checkpointLength;
if (b->bytes){
int byteCount = b->sizeLimit;
if (byteCount > b->allocSize)
byteCount = b->allocSize;
ob_append_bytes(ret, b->bytes, byteCount);
}
return ret;
}
int ob_free(struct overlay_buffer *b)
{ {
if (!b) return WHY("Asked to free NULL"); if (!b) return WHY("Asked to free NULL");
if (b->bytes && b->allocSize>0) free(b->bytes); if (b->bytes && b->allocated) free(b->bytes);
b->bytes=NULL; b->bytes=NULL;
b->allocSize=0; b->allocSize=0;
b->sizeLimit=0; b->sizeLimit=0;
@ -51,109 +95,100 @@ int ob_free(overlay_buffer *b)
return 0; return 0;
} }
int ob_checkpoint(overlay_buffer *b) int ob_checkpoint(struct overlay_buffer *b)
{ {
if (!b) return WHY("Asked to checkpoint NULL"); if (!b) return WHY("Asked to checkpoint NULL");
b->checkpointLength=b->length; b->checkpointLength=b->position;
return 0; return 0;
} }
int ob_rewind(overlay_buffer *b) int ob_rewind(struct overlay_buffer *b)
{ {
if (!b) return WHY("Asked to rewind NULL"); if (!b) return WHY("Asked to rewind NULL");
b->length=b->checkpointLength; b->position=b->checkpointLength;
return 0; return 0;
} }
int ob_setlength(overlay_buffer *b,int bytes){ int ob_limitsize(struct overlay_buffer *b,int bytes)
if (bytes > b->sizeLimit) return WHY("Length exceeds size limit");
if (b->allocSize>=0 && bytes > b->allocSize) return WHY("Length exceeds allocated size");
b->length=bytes;
return 0;
}
int ob_limitsize(overlay_buffer *b,int bytes)
{ {
if (!b) return WHY("Asked to limit size of NULL"); if (!b) return WHY("Asked to limit size of NULL");
if (b->length>bytes) return WHY("Length of data in buffer already exceeds size limit"); if (b->position>bytes) return WHY("Length of data in buffer already exceeds size limit");
if (b->checkpointLength>bytes) return WHY("Checkpointed length of data in buffer already exceeds size limit"); if (b->checkpointLength>bytes) return WHY("Checkpointed length of data in buffer already exceeds size limit");
if (b->bytes && (!b->allocated) && bytes > b->allocSize) return WHY("Size limit exceeds buffer size");
if (bytes<0) return WHY("Can't limit buffer to a negative size"); if (bytes<0) return WHY("Can't limit buffer to a negative size");
if (b->allocSize<0) return WHY("Can't change the limit of a static buffer");
b->sizeLimit=bytes; b->sizeLimit=bytes;
return 0; return 0;
} }
int ob_unlimitsize(overlay_buffer *b) int ob_unlimitsize(struct overlay_buffer *b)
{ {
if (!b) return WHY("b is NULL"); if (!b) return WHY("b is NULL");
if (b->allocSize<0) return WHY("Can't change the limit of a static buffer");
b->sizeLimit=-1; b->sizeLimit=-1;
return 0; return 0;
} }
int ob_makespace(overlay_buffer *b,int bytes) int ob_makespace(struct overlay_buffer *b,int bytes)
{ {
if (b->sizeLimit!=-1 && b->length+bytes>b->sizeLimit) { if (b->sizeLimit!=-1 && b->position+bytes>b->sizeLimit) {
if (debug&DEBUG_PACKETFORMATS) WHY("Asked to make space beyond size limit"); if (debug&DEBUG_PACKETFORMATS) WHY("Asked to make space beyond size limit");
return -1; return -1;
}
if (b->allocSize<0){
return WHY("Can't resize a static buffer");
} }
// already enough space?
if (b->position + bytes < b->allocSize)
return 0;
if (b->bytes && !b->allocated)
return WHY("Can't resize a static buffer");
if (0) if (0)
DEBUGF("ob_makespace(%p,%d)\n b->bytes=%p,b->length=%d,b->allocSize=%d\n", DEBUGF("ob_makespace(%p,%d)\n b->bytes=%p,b->position=%d,b->allocSize=%d\n",
b,bytes,b->bytes,b->length,b->allocSize); b,bytes,b->bytes,b->position,b->allocSize);
if (b->length+bytes>=b->allocSize) int newSize=b->position+bytes;
{ if (newSize<64) newSize=64;
int newSize=b->length+bytes; if (newSize&63) newSize+=64-(newSize&63);
if (newSize<64) newSize=64; if (newSize>1024) {
if (newSize&63) newSize+=64-(newSize&63); if (newSize&1023) newSize+=1024-(newSize&1023);
if (newSize>1024) { }
if (newSize&1023) newSize+=1024-(newSize&1023); if (newSize>65536) {
} if (newSize&65535) newSize+=65536-(newSize&65535);
if (newSize>65536) { }
if (newSize&65535) newSize+=65536-(newSize&65535); if (0) DEBUGF("realloc(b->bytes=%p,newSize=%d)", b->bytes,newSize);
} /* XXX OSX realloc() seems to be able to corrupt things if the heap is not happy when calling realloc(), making debugging memory corruption much harder.
if (0) DEBUGF("realloc(b->bytes=%p,newSize=%d)", b->bytes,newSize); So will do a three-stage malloc,bcopy,free to see if we can tease the bug out that way. */
/* XXX OSX realloc() seems to be able to corrupt things if the heap is not happy when calling realloc(), making debugging memory corruption much harder. /*
So will do a three-stage malloc,bcopy,free to see if we can tease the bug out that way. */ unsigned char *r=realloc(b->bytes,newSize);
/* if (!r) return WHY("realloc() failed");
unsigned char *r=realloc(b->bytes,newSize); b->bytes=r;
if (!r) return WHY("realloc() failed"); */
b->bytes=r;
*/
#ifdef MALLOC_PARANOIA #ifdef MALLOC_PARANOIA
#warning adding lots of padding to try to catch overruns #warning adding lots of padding to try to catch overruns
if (b->bytes) { if (b->bytes) {
int i; int i;
int corrupt=0; int corrupt=0;
for(i=0;i<4096;i++) if (b->bytes[b->allocSize+i]!=0xbd) corrupt++; for(i=0;i<4096;i++) if (b->bytes[b->allocSize+i]!=0xbd) corrupt++;
if (corrupt) { if (corrupt) {
WHYF("!!!!!! %d corrupted bytes in overrun catch tray", corrupt); WHYF("!!!!!! %d corrupted bytes in overrun catch tray", corrupt);
dump("overrun catch tray",&b->bytes[b->allocSize],4096); dump("overrun catch tray",&b->bytes[b->allocSize],4096);
sleep(3600); sleep(3600);
}
}
unsigned char *new=malloc(newSize+4096);
if (!new) return WHY("realloc() failed");
{
int i;
for(i=0;i<4096;i++) new[newSize+i]=0xbd;
}
#else
unsigned char *new=malloc(newSize);
#endif
bcopy(b->bytes,new,b->length);
if (b->bytes) free(b->bytes);
b->bytes=new;
b->allocSize=newSize;
return 0;
} }
else }
return 0; unsigned char *new=malloc(newSize+4096);
if (!new) return WHY("realloc() failed");
{
int i;
for(i=0;i<4096;i++) new[newSize+i]=0xbd;
}
#else
unsigned char *new=malloc(newSize);
#endif
bcopy(b->bytes,new,b->position);
if (b->bytes) free(b->bytes);
b->bytes=new;
b->allocated=1;
b->allocSize=newSize;
return 0;
} }
@ -162,44 +197,53 @@ int ob_makespace(overlay_buffer *b,int bytes)
Functions that append data and increase the size of the buffer if possible / required Functions that append data and increase the size of the buffer if possible / required
*/ */
int ob_append_byte(overlay_buffer *b,unsigned char byte) int ob_append_byte(struct overlay_buffer *b,unsigned char byte)
{ {
if (ob_makespace(b,1)) return WHY("ob_makespace() failed"); if (ob_makespace(b,1)) return WHY("ob_makespace() failed");
b->bytes[b->length++] = byte; b->bytes[b->position++] = byte;
return 0; return 0;
} }
unsigned char *ob_append_space(overlay_buffer *b,int count) unsigned char *ob_append_space(struct overlay_buffer *b,int count)
{ {
if (ob_makespace(b,count)) { WHY("ob_makespace() failed"); return NULL; } if (ob_makespace(b,count))
return WHYNULL("ob_makespace() failed");
unsigned char *r=&b->bytes[b->length]; unsigned char *r=&b->bytes[b->position];
b->length+=count; b->position+=count;
return r; return r;
} }
int ob_append_bytes(overlay_buffer *b,unsigned char *bytes,int count) int ob_append_bytes(struct overlay_buffer *b,unsigned char *bytes,int count)
{ {
if (ob_makespace(b,count)) return WHY("ob_makespace() failed"); if (ob_makespace(b,count)) return WHY("ob_makespace() failed");
bcopy(bytes,&b->bytes[b->length],count); bcopy(bytes,&b->bytes[b->position],count);
b->length+=count; b->position+=count;
return 0; return 0;
} }
int ob_append_short(overlay_buffer *b,unsigned short v) int ob_append_ui16(struct overlay_buffer *b, uint16_t v)
{ {
unsigned short s=htons(v); if (ob_makespace(b, 2)) return WHY("ob_makespace() failed");
return ob_append_bytes(b,(unsigned char *)&s,sizeof(unsigned short)); b->bytes[b->position] = (v >> 8) & 0xFF;
b->bytes[b->position+1] = v & 0xFF;
b->position+=2;
return 0;
} }
int ob_append_int(overlay_buffer *b,unsigned int v) int ob_append_ui32(struct overlay_buffer *b, uint32_t v)
{ {
unsigned int s=htonl(v); if (ob_makespace(b, 4)) return WHY("ob_makespace() failed");
return ob_append_bytes(b,(unsigned char *)&s,sizeof(unsigned int)); b->bytes[b->position] = (v >> 24) & 0xFF;
b->bytes[b->position+1] = (v >> 16) & 0xFF;
b->bytes[b->position+2] = (v >> 8) & 0xFF;
b->bytes[b->position+3] = v & 0xFF;
b->position+=4;
return 0;
} }
int ob_append_rfs(overlay_buffer *b,int l) int ob_append_rfs(struct overlay_buffer *b,int l)
{ {
/* Encode the specified length and append it to the buffer */ /* Encode the specified length and append it to the buffer */
if (l<0||l>0xffff) return -1; if (l<0||l>0xffff) return -1;
@ -208,7 +252,7 @@ int ob_append_rfs(overlay_buffer *b,int l)
and use ob_patch_rfs to set the value. That way we have only one and use ob_patch_rfs to set the value. That way we have only one
lot of code that does the encoding. */ lot of code that does the encoding. */
b->var_length_offset=b->length; b->var_length_offset=b->position;
b->var_length_bytes=rfs_length(l); b->var_length_bytes=rfs_length(l);
unsigned char c[3]={0,0,0}; unsigned char c[3]={0,0,0};
@ -228,41 +272,70 @@ int ob_append_rfs(overlay_buffer *b,int l)
*/ */
// make sure a range of bytes is valid for reading
int test_offset(overlay_buffer *b,int start,int length){ int test_offset(struct overlay_buffer *b,int start,int length){
if (!b) FATAL("b is NULL"); if (!b) return -1;
if (start<0) FATALF("passed illegal offset %d",start); if (start<0) return -1;
if (b->sizeLimit>=0 && start+length>b->sizeLimit) FATALF("passed offset too large %d", start+length); if (b->sizeLimit>=0 && start+length>b->sizeLimit) return -1;
if (b->allocSize>=0 && start+length>b->allocSize) FATALF("passed offset too large %d", start+length); if (start+length>b->allocSize) return -1;
return 0; return 0;
} }
int ob_setbyte(overlay_buffer *b,int ofs,unsigned char value) int ob_getbyte(struct overlay_buffer *b, int ofs)
{ {
test_offset(b, ofs, 1); if (test_offset(b, ofs, 1))
b->bytes[ofs]=value; return -1;
return 0;
}
int ob_getbyte(overlay_buffer *b,int ofs)
{
test_offset(b, ofs, 1);
if (ofs >= b->length) FATALF("passed offset too large %d", ofs);
return b->bytes[ofs]; return b->bytes[ofs];
} }
unsigned int ob_get_int(overlay_buffer *b,int offset) int ob_get_bytes(struct overlay_buffer *b, unsigned char *buff, int len){
{ if (test_offset(b, b->position, len))
// TODO unsigned -1? FATAL? return -1;
test_offset(b, offset, sizeof(unsigned int));
bcopy(b->bytes + b->position, buff, len);
b->position+=len;
return 0;
}
// Some platforms require alignment unsigned char * ob_get_bytes_ptr(struct overlay_buffer *b, int len){
if (((uintptr_t)&b->bytes[offset])&3) { if (test_offset(b, b->position, len))
union { unsigned char uc[4]; uint32_t ui32; } bb; return NULL;
bcopy(&b->bytes[offset], &bb.uc[0], 4);
return ntohl(bb.ui32); unsigned char *ret = b->bytes + b->position;
} else b->position+=len;
return ntohl(*((uint32_t*)&b->bytes[offset])); return ret;
}
uint32_t ob_get_ui32(struct overlay_buffer *b)
{
if (test_offset(b, b->position, 4))
return 0xFFFFFFFF; // ... unsigned
uint32_t ret = b->bytes[b->position] << 24
| b->bytes[b->position +1] << 16
| b->bytes[b->position +2] << 8
| b->bytes[b->position +3];
b->position+=4;
return ret;
}
uint16_t ob_get_ui16(struct overlay_buffer *b)
{
if (test_offset(b, b->position, 2))
return 0xFFFF; // ... unsigned
uint16_t ret = b->bytes[b->position] << 8
| b->bytes[b->position +1];
b->position+=2;
return ret;
}
int ob_get(struct overlay_buffer *b){
if (test_offset(b, b->position, 1))
return -1;
return b->bytes[b->position++];
} }
int rfs_length(int l) int rfs_length(int l)
@ -307,21 +380,21 @@ int rfs_decode(unsigned char *b,int *ofs)
} }
// move the data at offset, by shift bytes // move the data at offset, by shift bytes
int ob_indel_space(overlay_buffer *b,int offset,int shift) int ob_indel_space(struct overlay_buffer *b,int offset,int shift)
{ {
if (offset>=b->length) return -1; if (offset>=b->position) return -1;
if (shift>0 && ob_makespace(b, shift)) return -1; if (shift>0 && ob_makespace(b, shift)) return -1;
bcopy(&b->bytes[offset],&b->bytes[offset+shift],b->length-offset); bcopy(&b->bytes[offset],&b->bytes[offset+shift],b->position-offset);
b->length+=shift; b->position+=shift;
return 0; return 0;
} }
int ob_patch_rfs(overlay_buffer *b,int l) int ob_patch_rfs(struct overlay_buffer *b,int l)
{ {
if (l==COMPUTE_RFS_LENGTH){ if (l==COMPUTE_RFS_LENGTH){
// assume the payload has been written, we can now calculate the actual length // assume the payload has been written, we can now calculate the actual length
l = b->length - (b->var_length_offset + b->var_length_bytes); l = b->position - (b->var_length_offset + b->var_length_bytes);
} }
if (l<0||l>0xffff) return -1; if (l<0||l>0xffff) return -1;
@ -334,13 +407,13 @@ int ob_patch_rfs(overlay_buffer *b,int l)
new_size,b->var_length_bytes,shift); new_size,b->var_length_bytes,shift);
dump("before indel", dump("before indel",
&b->bytes[b->var_length_offset], &b->bytes[b->var_length_offset],
b->length-b->var_length_offset); b->position-b->var_length_offset);
} }
if (ob_indel_space(b, b->var_length_offset + b->var_length_bytes, shift)) return -1; if (ob_indel_space(b, b->var_length_offset + b->var_length_bytes, shift)) return -1;
if (debug&DEBUG_PACKETCONSTRUCTION) { if (debug&DEBUG_PACKETCONSTRUCTION) {
dump("after indel", dump("after indel",
&b->bytes[b->var_length_offset], &b->bytes[b->var_length_offset],
b->length-b->var_length_offset); b->position-b->var_length_offset);
} }
} }
@ -350,7 +423,7 @@ int ob_patch_rfs(overlay_buffer *b,int l)
if (debug&DEBUG_PACKETCONSTRUCTION) { if (debug&DEBUG_PACKETCONSTRUCTION) {
dump("after patch", dump("after patch",
&b->bytes[b->var_length_offset], &b->bytes[b->var_length_offset],
b->length-b->var_length_offset); b->position-b->var_length_offset);
} }
return 0; return 0;
@ -364,10 +437,10 @@ int asprintable(int c)
return c; return c;
} }
int ob_dump(overlay_buffer *b,char *desc) int ob_dump(struct overlay_buffer *b,char *desc)
{ {
DEBUGF("overlay_buffer '%s' at %p : length=%d", desc, b, b->length); DEBUGF("overlay_buffer '%s' at %p : length=%d", desc, b, b->position);
dump(NULL, b->bytes, b->length); dump(NULL, b->bytes, b->position);
return 0; return 0;
} }

74
overlay_buffer.h Normal file
View File

@ -0,0 +1,74 @@
/*
Serval Daemon
Copyright (C) 2012 Serval Project Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _SERVALD_OVERLAY_BUFFER_H
#define _SERVALD_OVERLAY_BUFFER_H
struct overlay_buffer {
unsigned char *bytes;
// remembered position for rewinding
int checkpointLength;
// position of data read / written
int position;
// maximum allowed bytes for reading / writing
int sizeLimit;
// size of buffer
int allocSize;
// is this an allocated buffer? can it be resized? Should it be freed?
int allocated;
// length position and size for later patching
int var_length_offset;
int var_length_bytes;
};
struct overlay_buffer *ob_new(void);
struct overlay_buffer *ob_static(unsigned char *bytes, int size);
struct overlay_buffer *ob_slice(struct overlay_buffer *b, int offset, int length);
struct overlay_buffer *ob_dup(struct overlay_buffer *b);
int ob_free(struct overlay_buffer *b);
int ob_checkpoint(struct overlay_buffer *b);
int ob_rewind(struct overlay_buffer *b);
int ob_limitsize(struct overlay_buffer *b,int bytes);
int ob_unlimitsize(struct overlay_buffer *b);
int ob_makespace(struct overlay_buffer *b,int bytes);
int ob_append_byte(struct overlay_buffer *b,unsigned char byte);
int ob_append_bytes(struct overlay_buffer *b,unsigned char *bytes,int count);
unsigned char *ob_append_space(struct overlay_buffer *b,int count);
int ob_append_ui16(struct overlay_buffer *b, uint16_t v);
int ob_append_ui32(struct overlay_buffer *b, uint32_t v);
int ob_patch_rfs(struct overlay_buffer *b,int l);
int ob_append_rfs(struct overlay_buffer *b,int l);
// get one byte, -ve number indicates failure
int ob_getbyte(struct overlay_buffer *b,int ofs);
// get one byte from the current position, -ve number indicates failure
int ob_get(struct overlay_buffer *b);
int ob_get_bytes(struct overlay_buffer *b, unsigned char *buff, int len);
unsigned char * ob_get_bytes_ptr(struct overlay_buffer *b, int len);
uint32_t ob_get_ui32(struct overlay_buffer *b);
uint16_t ob_get_ui16(struct overlay_buffer *b);
int ob_dump(struct overlay_buffer *b,char *desc);
#endif

View File

@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <time.h> #include <time.h>
#include "serval.h" #include "serval.h"
#include "strbuf.h" #include "strbuf.h"
#include "overlay_buffer.h"
#ifdef HAVE_IFADDRS_H #ifdef HAVE_IFADDRS_H
#include <ifaddrs.h> #include <ifaddrs.h>
@ -52,7 +53,7 @@ struct profile_total sock_any_stats;
struct outgoing_packet{ struct outgoing_packet{
overlay_interface *interface; overlay_interface *interface;
int i; int i;
overlay_buffer *buffer; struct overlay_buffer *buffer;
}; };
struct sched_ent next_packet; struct sched_ent next_packet;
@ -925,7 +926,7 @@ static void
overlay_init_packet(struct outgoing_packet *packet, int interface) { overlay_init_packet(struct outgoing_packet *packet, int interface) {
packet->i = interface; packet->i = interface;
packet->interface = &overlay_interfaces[packet->i]; packet->interface = &overlay_interfaces[packet->i];
packet->buffer=ob_new(packet->interface->mtu); packet->buffer=ob_new();
ob_limitsize(packet->buffer, packet->interface->mtu); ob_limitsize(packet->buffer, packet->interface->mtu);
ob_append_bytes(packet->buffer,magic_header,4); ob_append_bytes(packet->buffer,magic_header,4);
@ -1075,14 +1076,14 @@ overlay_fill_send_packet(struct outgoing_packet *packet, time_ms_t now) {
if(packet->buffer){ if(packet->buffer){
// send the packet // send the packet
if (packet->buffer->length>=HEADERFIELDS_LEN){ if (packet->buffer->position>=HEADERFIELDS_LEN){
if (debug&DEBUG_PACKETCONSTRUCTION) if (debug&DEBUG_PACKETCONSTRUCTION)
dump("assembled packet",&packet->buffer->bytes[0],packet->buffer->length); dump("assembled packet",&packet->buffer->bytes[0],packet->buffer->position);
if (debug&DEBUG_OVERLAYINTERFACES) if (debug&DEBUG_OVERLAYINTERFACES)
DEBUGF("Sending %d byte packet",packet->buffer->length); DEBUGF("Sending %d byte packet",packet->buffer->position);
overlay_broadcast_ensemble(packet->i,NULL,packet->buffer->bytes,packet->buffer->length); overlay_broadcast_ensemble(packet->i,NULL,packet->buffer->bytes,packet->buffer->position);
} }
ob_free(packet->buffer); ob_free(packet->buffer);
overlay_abbreviate_clear_most_recent_address(); overlay_abbreviate_clear_most_recent_address();

View File

@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "serval.h" #include "serval.h"
#include "strbuf.h" #include "strbuf.h"
#include "subscribers.h" #include "subscribers.h"
#include "overlay_buffer.h"
struct profile_total mdp_stats={.name="overlay_mdp_poll"}; struct profile_total mdp_stats={.name="overlay_mdp_poll"};
@ -280,7 +281,7 @@ unsigned char *overlay_mdp_decrypt(overlay_frame *f, overlay_mdp_frame *mdp, int
{ {
IN(); IN();
*len=f->payload->length; *len=f->payload->sizeLimit;
unsigned char *b = NULL; unsigned char *b = NULL;
unsigned char plain_block[(*len)+16]; unsigned char plain_block[(*len)+16];
@ -288,7 +289,7 @@ unsigned char *overlay_mdp_decrypt(overlay_frame *f, overlay_mdp_frame *mdp, int
case 0: case 0:
/* get payload */ /* get payload */
b=&f->payload->bytes[0]; b=&f->payload->bytes[0];
*len=f->payload->length; *len=f->payload->sizeLimit;
mdp->packetTypeAndFlags|=MDP_NOCRYPT|MDP_NOSIGN; mdp->packetTypeAndFlags|=MDP_NOCRYPT|MDP_NOSIGN;
break; break;
case OF_CRYPTO_CIPHERED: case OF_CRYPTO_CIPHERED:
@ -306,7 +307,7 @@ unsigned char *overlay_mdp_decrypt(overlay_frame *f, overlay_mdp_frame *mdp, int
/* get payload and following compacted signature */ /* get payload and following compacted signature */
b=&f->payload->bytes[0]; b=&f->payload->bytes[0];
*len=f->payload->length-crypto_sign_edwards25519sha512batch_BYTES; *len=f->payload->sizeLimit-crypto_sign_edwards25519sha512batch_BYTES;
/* get hash */ /* get hash */
unsigned char hash[crypto_hash_sha512_BYTES]; unsigned char hash[crypto_hash_sha512_BYTES];
@ -344,7 +345,7 @@ unsigned char *overlay_mdp_decrypt(overlay_frame *f, overlay_mdp_frame *mdp, int
if (!k) { WHY("I don't have the private key required to decrypt that"); if (!k) { WHY("I don't have the private key required to decrypt that");
RETURN(NULL); } RETURN(NULL); }
bzero(&plain_block[0],crypto_box_curve25519xsalsa20poly1305_ZEROBYTES-16); bzero(&plain_block[0],crypto_box_curve25519xsalsa20poly1305_ZEROBYTES-16);
int cipher_len=f->payload->length-nb; int cipher_len=f->payload->sizeLimit-nb;
bcopy(&f->payload->bytes[nb],&plain_block[16],cipher_len); bcopy(&f->payload->bytes[nb],&plain_block[16],cipher_len);
if (0) { if (0) {
dump("nm bytes",k,crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES); dump("nm bytes",k,crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES);
@ -374,7 +375,7 @@ int overlay_saw_mdp_containing_frame(overlay_frame *f, time_ms_t now)
Take payload from mdp frame itself. Take payload from mdp frame itself.
*/ */
overlay_mdp_frame mdp; overlay_mdp_frame mdp;
int len=f->payload->length; int len=f->payload->sizeLimit;
/* Get source and destination addresses */ /* Get source and destination addresses */
bcopy(f->destination,mdp.in.dst.sid,SID_SIZE); bcopy(f->destination,mdp.in.dst.sid,SID_SIZE);
@ -750,13 +751,15 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
case 0: /* crypted and signed (using CryptoBox authcryption primitive) */ case 0: /* crypted and signed (using CryptoBox authcryption primitive) */
frame->modifiers=OF_CRYPTO_SIGNED|OF_CRYPTO_CIPHERED; frame->modifiers=OF_CRYPTO_SIGNED|OF_CRYPTO_CIPHERED;
/* Prepare payload */ /* Prepare payload */
frame->payload=ob_new(1 /* frame type (MDP) */ frame->payload=ob_new();
+1 /* MDP version */ /*length should be;
+4 /* dst port */ 1 - frame type (MDP)
+4 /* src port */ +1 - MDP version
+crypto_box_curve25519xsalsa20poly1305_NONCEBYTES +4 - dst port
+crypto_box_curve25519xsalsa20poly1305_ZEROBYTES +4 - src port
+mdp->out.payload_length); +crypto_box_curve25519xsalsa20poly1305_NONCEBYTES
+crypto_box_curve25519xsalsa20poly1305_ZEROBYTES
+mdp->out.payload_length*/
{ {
/* write cryptobox nonce */ /* write cryptobox nonce */
unsigned char nonce[crypto_box_curve25519xsalsa20poly1305_NONCEBYTES]; unsigned char nonce[crypto_box_curve25519xsalsa20poly1305_NONCEBYTES];
@ -792,7 +795,7 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
unsigned char *k=keyring_get_nm_bytes(&mdp->out.src,&mdp->out.dst); unsigned char *k=keyring_get_nm_bytes(&mdp->out.src,&mdp->out.dst);
if (!k) { op_free(frame); RETURN(WHY("could not compute Curve25519(NxM)")); } if (!k) { op_free(frame); RETURN(WHY("could not compute Curve25519(NxM)")); }
/* Get pointer to place in frame where the ciphered text needs to go */ /* Get pointer to place in frame where the ciphered text needs to go */
int cipher_offset=frame->payload->length; int cipher_offset=frame->payload->position;
unsigned char *cipher_text=ob_append_space(frame->payload,cipher_len); unsigned char *cipher_text=ob_append_space(frame->payload,cipher_len);
if (fe||(!cipher_text)) if (fe||(!cipher_text))
{ op_free(frame); RETURN(WHY("could not make space for ciphered text")); } { op_free(frame); RETURN(WHY("could not make space for ciphered text")); }
@ -803,16 +806,16 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
/* now shuffle down 16 bytes to get rid of the temporary space that crypto_box /* now shuffle down 16 bytes to get rid of the temporary space that crypto_box
uses. */ uses. */
bcopy(&cipher_text[16],&cipher_text[0],cipher_len-16); bcopy(&cipher_text[16],&cipher_text[0],cipher_len-16);
frame->payload->length-=16; frame->payload->position-=16;
if (0) { if (0) {
DEBUG("authcrypted mdp frame"); DEBUG("authcrypted mdp frame");
dump("nm bytes",k,crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES); dump("nm bytes",k,crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES);
dump("nonce",nonce,crypto_box_curve25519xsalsa20poly1305_NONCEBYTES); dump("nonce",nonce,crypto_box_curve25519xsalsa20poly1305_NONCEBYTES);
dump("plain text",&plain[16],cipher_len-16); dump("plain text",&plain[16],cipher_len-16);
dump("cipher text",cipher_text,cipher_len-16); dump("cipher text",cipher_text,cipher_len-16);
DEBUGF("frame->payload->length=%d,cipher_len-16=%d,cipher_offset=%d", frame->payload->length,cipher_len-16,cipher_offset); DEBUGF("frame->payload->length=%d,cipher_len-16=%d,cipher_offset=%d", frame->payload->position,cipher_len-16,cipher_offset);
dump("frame",&frame->payload->bytes[0], dump("frame",&frame->payload->bytes[0],
frame->payload->length); frame->payload->position);
} }
} }
break; break;
@ -838,12 +841,15 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
*/ */
frame->modifiers=OF_CRYPTO_SIGNED; frame->modifiers=OF_CRYPTO_SIGNED;
/* Prepare payload */ /* Prepare payload */
frame->payload=ob_new(1 /* frame type (MDP) */ frame->payload=ob_new();
+1 /* MDP version */ /* Length should be;
+4 /* dst port */ 1 - frame type (MDP)
+4 /* src port */ +1 - MDP version
+crypto_sign_edwards25519sha512batch_BYTES +4 - dst port
+mdp->out.payload_length); +4 - src port
+crypto_sign_edwards25519sha512batch_BYTES
+mdp->out.payload_length
*/
{ {
unsigned char *key=keyring_find_sas_private(keyring,mdp->out.src.sid,NULL); unsigned char *key=keyring_find_sas_private(keyring,mdp->out.src.sid,NULL);
if (!key) { op_free(frame); RETURN(WHY("could not find signing key")); } if (!key) { op_free(frame); RETURN(WHY("could not find signing key")); }
@ -893,17 +899,20 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
case MDP_NOSIGN|MDP_NOCRYPT: /* clear text and no signature */ case MDP_NOSIGN|MDP_NOCRYPT: /* clear text and no signature */
frame->modifiers=0; frame->modifiers=0;
/* Copy payload body in */ /* Copy payload body in */
frame->payload=ob_new(1 /* frame type (MDP) */ frame->payload=ob_new();
+1 /* MDP version */ /* Length should be;
+4 /* dst port */ 1 - frame type (MDP)
+4 /* src port */ +1 - MDP version
+mdp->out.payload_length); +4 - dst port
+4 - src port
+mdp->out.payload_length
*/
/* MDP version 1 */ /* MDP version 1 */
ob_append_byte(frame->payload,0x01); ob_append_byte(frame->payload,0x01);
ob_append_byte(frame->payload,0x01); ob_append_byte(frame->payload,0x01);
/* Destination port */ /* Destination port */
ob_append_int(frame->payload,mdp->out.src.port); ob_append_ui32(frame->payload,mdp->out.src.port);
ob_append_int(frame->payload,mdp->out.dst.port); ob_append_ui32(frame->payload,mdp->out.dst.port);
ob_append_bytes(frame->payload,mdp->out.payload,mdp->out.payload_length); ob_append_bytes(frame->payload,mdp->out.payload,mdp->out.payload_length);
break; break;
} }

View File

@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "serval.h" #include "serval.h"
#include "strbuf.h" #include "strbuf.h"
#include "overlay_buffer.h"
struct sockaddr_in loopback = { struct sockaddr_in loopback = {
.sin_family=0, .sin_family=0,
@ -236,12 +237,10 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
ensemble */ ensemble */
if (f.type==OF_TYPE_SELFANNOUNCE) if (f.type==OF_TYPE_SELFANNOUNCE)
overlay_abbreviate_set_current_sender(f.source); overlay_abbreviate_set_current_sender(f.source);
// TODO refactor all packet parsing to only allocate additional memory for the payload /* Create an overlay buffer, wrapping around this static packet */
// if it needs to be queued for forwarding.
f.payload = ob_static(&packet[ofs], nextPayload - ofs); f.payload = ob_static(&packet[ofs], nextPayload - ofs);
ob_setlength(f.payload, nextPayload - ofs); ob_limitsize(f.payload, nextPayload - ofs);
/* Finally process the frame */ /* Finally process the frame */
overlay_frame_process(interface,&f); overlay_frame_process(interface,&f);
@ -257,7 +256,7 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
return 0; return 0;
} }
int overlay_add_selfannouncement(int interface,overlay_buffer *b) int overlay_add_selfannouncement(int interface,struct overlay_buffer *b)
{ {
/* Pull the first record from the HLR database and turn it into a /* Pull the first record from the HLR database and turn it into a
@ -351,9 +350,9 @@ int overlay_add_selfannouncement(int interface,overlay_buffer *b)
// number: one millisecond ago. // number: one millisecond ago.
if (last_ms == -1) if (last_ms == -1)
last_ms = now - 1; last_ms = now - 1;
if (ob_append_int(b, last_ms)) if (ob_append_ui32(b, last_ms))
return WHY("Could not add low sequence number to self-announcement"); return WHY("Could not add low sequence number to self-announcement");
if (ob_append_int(b, now)) if (ob_append_ui32(b, now))
return WHY("Could not add high sequence number to self-announcement"); return WHY("Could not add high sequence number to self-announcement");
if (debug&DEBUG_OVERLAYINTERFACES) if (debug&DEBUG_OVERLAYINTERFACES)
DEBUGF("interface #%d: last_tick_ms=%lld, now=%lld (delta=%lld)", DEBUGF("interface #%d: last_tick_ms=%lld, now=%lld (delta=%lld)",

View File

@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#include "serval.h" #include "serval.h"
#include "overlay_buffer.h"
int overlay_payload_verify(overlay_frame *p) int overlay_payload_verify(overlay_frame *p)
{ {
@ -27,7 +28,7 @@ int overlay_payload_verify(overlay_frame *p)
return WHY("function not implemented"); return WHY("function not implemented");
} }
int op_append_type(overlay_buffer *headers,overlay_frame *p) int op_append_type(struct overlay_buffer *headers,overlay_frame *p)
{ {
unsigned char c[3]; unsigned char c[3];
switch(p->type&OF_TYPE_FLAG_BITS) switch(p->type&OF_TYPE_FLAG_BITS)
@ -59,16 +60,16 @@ int op_append_type(overlay_buffer *headers,overlay_frame *p)
} }
int overlay_frame_package_fmt1(overlay_frame *p,overlay_buffer *b) int overlay_frame_package_fmt1(overlay_frame *p, struct overlay_buffer *b)
{ {
/* Convert a payload (frame) structure into a series of bytes. /* Convert a payload (frame) structure into a series of bytes.
Assumes that any encryption etc has already been done. Assumes that any encryption etc has already been done.
Will pick a next hop if one has not been chosen. Will pick a next hop if one has not been chosen.
*/ */
overlay_buffer *headers; struct overlay_buffer *headers;
headers=ob_new(256); headers=ob_new();
if (!headers) return WHY("could not allocate overlay buffer for headers"); if (!headers) return WHY("could not allocate overlay buffer for headers");
@ -111,26 +112,26 @@ int overlay_frame_package_fmt1(overlay_frame *p,overlay_buffer *b)
we rely on context for abbreviating the addresses. So we write it initially and then patch it we rely on context for abbreviating the addresses. So we write it initially and then patch it
after. after.
*/ */
int max_len=((SID_SIZE+3)*3+headers->length+p->payload->length); int max_len=((SID_SIZE+3)*3+headers->position+p->payload->position);
if (debug&DEBUG_PACKETCONSTRUCTION) if (debug&DEBUG_PACKETCONSTRUCTION)
DEBUGF("Appending RFS for max_len=%d\n",max_len); DEBUGF("Appending RFS for max_len=%d\n",max_len);
ob_append_rfs(headers,max_len); ob_append_rfs(headers,max_len);
int addrs_start=headers->length; int addrs_start=headers->position;
/* Write out addresses as abbreviated as possible */ /* Write out addresses as abbreviated as possible */
overlay_abbreviate_append_address(headers,p->nexthop); overlay_abbreviate_append_address(headers,p->nexthop);
overlay_abbreviate_append_address(headers,p->destination); overlay_abbreviate_append_address(headers,p->destination);
overlay_abbreviate_append_address(headers,p->source); overlay_abbreviate_append_address(headers,p->source);
int addrs_len=headers->length-addrs_start; int addrs_len=headers->position-addrs_start;
int actual_len=addrs_len+p->payload->length; int actual_len=addrs_len+p->payload->position;
if (debug&DEBUG_PACKETCONSTRUCTION) if (debug&DEBUG_PACKETCONSTRUCTION)
DEBUGF("Patching RFS for actual_len=%d\n",actual_len); DEBUGF("Patching RFS for actual_len=%d\n",actual_len);
ob_patch_rfs(headers,actual_len); ob_patch_rfs(headers,actual_len);
/* Write payload format plus total length of header bits */ /* Write payload format plus total length of header bits */
if (ob_makespace(b,2+headers->length+p->payload->length)) { if (ob_makespace(b,2+headers->position+p->payload->position)) {
/* Not enough space free in output buffer */ /* Not enough space free in output buffer */
if (debug&DEBUG_PACKETFORMATS) if (debug&DEBUG_PACKETFORMATS)
DEBUGF("Could not make enough space free in output buffer"); DEBUGF("Could not make enough space free in output buffer");
@ -138,11 +139,11 @@ int overlay_frame_package_fmt1(overlay_frame *p,overlay_buffer *b)
} }
/* Package up headers and payload */ /* Package up headers and payload */
if (ob_append_bytes(b,headers->bytes,headers->length)) { if (ob_append_bytes(b,headers->bytes,headers->position)) {
WHY("could not append header"); WHY("could not append header");
goto cleanup; goto cleanup;
} }
if (ob_append_bytes(b,p->payload->bytes,p->payload->length)) { if (ob_append_bytes(b,p->payload->bytes,p->payload->position)) {
WHY("could not append payload"); WHY("could not append payload");
goto cleanup; goto cleanup;
} }
@ -156,13 +157,6 @@ cleanup:
return -1; return -1;
} }
overlay_buffer *overlay_payload_unpackage(overlay_frame *b) {
/* Extract the payload at the current location in the buffer. */
WHY("not implemented");
return NULL;
}
int dump_queue(char *msg,int q) int dump_queue(char *msg,int q)
{ {
overlay_txqueue *qq=&overlay_tx[q]; overlay_txqueue *qq=&overlay_tx[q];
@ -191,7 +185,7 @@ int dump_payload(overlay_frame *p,char *message)
message?message:""); message?message:"");
DEBUGF(" next hop is %s",alloca_tohex_sid(p->nexthop)); DEBUGF(" next hop is %s",alloca_tohex_sid(p->nexthop));
if (p->payload) if (p->payload)
dump("payload contents", &p->payload->bytes[0],p->payload->length); dump("payload contents", &p->payload->bytes[0],p->payload->position);
return 0; return 0;
} }
@ -204,8 +198,8 @@ int overlay_payload_enqueue(int q,overlay_frame *p,int forceBroadcastP)
Complain if there are too many frames in the queue. Complain if there are too many frames in the queue.
*/ */
if (0) if (debug&DEBUG_PACKETTX)
WHYF("Enqueuing packet for %s* (q[%d]length = %d)", DEBUGF("Enqueuing packet for %s* (q[%d]length = %d)",
alloca_tohex(p->destination, 7), alloca_tohex(p->destination, 7),
q,overlay_tx[q].length); q,overlay_tx[q].length);
@ -274,16 +268,8 @@ overlay_frame *op_dup(overlay_frame *in)
/* copy main data structure */ /* copy main data structure */
bcopy(in,out,sizeof(overlay_frame)); bcopy(in,out,sizeof(overlay_frame));
out->payload=ob_new(in->payload->length);
if (!out->payload) { out->payload=ob_dup(in->payload);
free(out);
return WHYNULL("ob_new() failed");
}
if (ob_append_bytes(out->payload,&in->payload->bytes[0],in->payload->length))
{
op_free(out);
return WHYNULL("could not duplicate payload bytes");
}
return out; return out;
} }

View File

@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "serval.h" #include "serval.h"
#include "strbuf.h" #include "strbuf.h"
#include "subscribers.h" #include "subscribers.h"
#include "overlay_buffer.h"
/* /*
Here we implement the actual routing algorithm which is heavily based on BATMAN. Here we implement the actual routing algorithm which is heavily based on BATMAN.
@ -349,6 +350,7 @@ int overlay_route_ack_selfannounce(overlay_frame *f,
if (overlay_resolve_next_hop(out)) { if (overlay_resolve_next_hop(out)) {
/* no open path, so convert to broadcast */ /* no open path, so convert to broadcast */
overlay_frame_set_broadcast_as_destination(out); overlay_frame_set_broadcast_as_destination(out);
out->isBroadcast = 1;
out->ttl=2; out->ttl=2;
if (debug&DEBUG_OVERLAYROUTING) if (debug&DEBUG_OVERLAYROUTING)
DEBUG("Broadcasting ack to selfannounce for hithero unroutable node"); DEBUG("Broadcasting ack to selfannounce for hithero unroutable node");
@ -368,13 +370,12 @@ int overlay_route_ack_selfannounce(overlay_frame *f,
numbers means we can't just take the highest-numbered sequence number. numbers means we can't just take the highest-numbered sequence number.
So we need to take the observation which was most recently received. So we need to take the observation which was most recently received.
*/ */
out->payload=ob_new(4+32*2+1); /* will grow if it isn't big enough, but let's try to out->payload=ob_new();
avoid a realloc() if possible */
/* XXX - we should merge contiguous observation reports so that packet loss /* XXX - we should merge contiguous observation reports so that packet loss
on the return path doesn't count against the link. */ on the return path doesn't count against the link. */
ob_append_int(out->payload,s1); ob_append_ui32(out->payload,s1);
ob_append_int(out->payload,s2); ob_append_ui32(out->payload,s2);
/* The ack needs to contain the per-interface scores that we have built up /* The ack needs to contain the per-interface scores that we have built up
for this neighbour. for this neighbour.
@ -552,9 +553,9 @@ int overlay_route_saw_selfannounce(overlay_frame *f, time_ms_t now)
RETURN(-1); RETURN(-1);
} }
s1=ob_get_int(f->payload, 0); s1=ob_get_ui32(f->payload);
s2=ob_get_int(f->payload, 4); s2=ob_get_ui32(f->payload);
sender_interface=ob_getbyte(f->payload, 8); sender_interface=ob_get(f->payload);
if (debug&DEBUG_OVERLAYROUTING) if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("Received self-announcement for sequence range [%08x,%08x] from interface %d",s1,s2,sender_interface); DEBUGF("Received self-announcement for sequence range [%08x,%08x] from interface %d",s1,s2,sender_interface);
@ -803,14 +804,14 @@ int overlay_route_saw_selfannounce_ack(overlay_frame *f,long long now)
{ {
IN(); IN();
if (debug&DEBUG_OVERLAYROUTING) if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("processing selfannounce ack (payload length=%d)",f->payload->length); DEBUGF("processing selfannounce ack (payload length=%d)",f->payload->sizeLimit);
if (f->payload->length<9) if (f->payload->sizeLimit<9)
RETURN(WHY("FOO! selfannounce ack packet too short")); RETURN(WHY("FOO! selfannounce ack packet too short"));
unsigned int s1=ob_get_int(f->payload,0); unsigned int s1=ob_get_ui32(f->payload);
unsigned int s2=ob_get_int(f->payload,4); unsigned int s2=ob_get_ui32(f->payload);
int iface=ob_getbyte(f->payload,8); int iface=ob_get(f->payload);
// Call something like the following for each link // Call something like the following for each link
overlay_route_node_can_hear_me(f->source,iface,s1,s2,now); overlay_route_node_can_hear_me(f->source,iface,s1,s2,now);

View File

@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "serval.h" #include "serval.h"
#include "rhizome.h" #include "rhizome.h"
#include <assert.h> #include <assert.h>
#include "overlay_buffer.h"
#include <stdlib.h> #include <stdlib.h>
int rhizome_manifest_to_bar(rhizome_manifest *m,unsigned char *bar) int rhizome_manifest_to_bar(rhizome_manifest *m,unsigned char *bar)
@ -73,7 +74,7 @@ int rhizome_manifest_to_bar(rhizome_manifest *m,unsigned char *bar)
int bundles_available=-1; int bundles_available=-1;
int bundle_offset[2]={0,0}; int bundle_offset[2]={0,0};
int overlay_rhizome_add_advertisements(int interface_number,overlay_buffer *e) int overlay_rhizome_add_advertisements(int interface_number, struct overlay_buffer *e)
{ {
IN(); IN();
int voice_mode=0; int voice_mode=0;
@ -93,13 +94,10 @@ int overlay_rhizome_add_advertisements(int interface_number,overlay_buffer *e)
if (voice_mode) if (random()&3) { RETURN(0); } if (voice_mode) if (random()&3) { RETURN(0); }
int pass; int pass;
int bytes=e->sizeLimit-e->length; int bytes=e->sizeLimit-e->position;
int overhead=1+11+1+2+2; /* maximum overhead */ int overhead=1+11+1+2+2; /* maximum overhead */
int slots=(bytes-overhead)/RHIZOME_BAR_BYTES; int slots=(bytes-overhead)/RHIZOME_BAR_BYTES;
if (slots>30) slots=30; if (slots>30) slots=30;
int slots_used=0;
int bytes_used=0;
int bytes_available=bytes-overhead-1 /* one byte held for expanding RFS */;
int bundles_advertised=0; int bundles_advertised=0;
if (slots<1) { RETURN(WHY("No room for node advertisements")); } if (slots<1) { RETURN(WHY("No room for node advertisements")); }
@ -110,7 +108,7 @@ int overlay_rhizome_add_advertisements(int interface_number,overlay_buffer *e)
RETURN(WHY("could not add rhizome bundle advertisement header")); RETURN(WHY("could not add rhizome bundle advertisement header"));
ob_append_byte(e, 1); /* TTL (1 byte) */ ob_append_byte(e, 1); /* TTL (1 byte) */
ob_append_rfs(e,1+11+1+2+RHIZOME_BAR_BYTES*slots_used/* RFS */); ob_append_rfs(e,1+11+1+2+RHIZOME_BAR_BYTES/* RFS */);
/* Stuff in dummy address fields (11 bytes) */ /* Stuff in dummy address fields (11 bytes) */
ob_append_byte(e,OA_CODE_BROADCAST); ob_append_byte(e,OA_CODE_BROADCAST);
@ -129,7 +127,7 @@ int overlay_rhizome_add_advertisements(int interface_number,overlay_buffer *e)
*/ */
ob_append_byte(e,3+skipmanifests); ob_append_byte(e,3+skipmanifests);
/* Rhizome HTTP server port number (2 bytes) */ /* Rhizome HTTP server port number (2 bytes) */
ob_append_short(e, rhizome_http_server_port); ob_append_ui16(e, rhizome_http_server_port);
/* XXX Should add priority bundles here. /* XXX Should add priority bundles here.
XXX Should prioritise bundles for subscribed groups, Serval-authorised files XXX Should prioritise bundles for subscribed groups, Serval-authorised files
@ -165,6 +163,7 @@ int overlay_rhizome_add_advertisements(int interface_number,overlay_buffer *e)
sqlite3_blob *blob=NULL; sqlite3_blob *blob=NULL;
for(pass=skipmanifests;pass<2;pass++) { for(pass=skipmanifests;pass<2;pass++) {
ob_checkpoint(e);
switch(pass) { switch(pass) {
case 0: /* Full manifests */ case 0: /* Full manifests */
statement = sqlite_prepare("SELECT MANIFEST,ROWID FROM MANIFESTS LIMIT %d,%d", bundle_offset[pass], slots); statement = sqlite_prepare("SELECT MANIFEST,ROWID FROM MANIFESTS LIMIT %d,%d", bundle_offset[pass], slots);
@ -175,9 +174,8 @@ int overlay_rhizome_add_advertisements(int interface_number,overlay_buffer *e)
} }
if (!statement) if (!statement)
RETURN(WHY("Could not prepare sql statement for fetching BARs for advertisement")); RETURN(WHY("Could not prepare sql statement for fetching BARs for advertisement"));
while( bytes_used < bytes_available while( sqlite_step_retry(&retry, statement) == SQLITE_ROW
&& sqlite_step_retry(&retry, statement) == SQLITE_ROW && e->position+RHIZOME_BAR_BYTES<=e->sizeLimit
&& e->length + RHIZOME_BAR_BYTES <= e->sizeLimit
) { ) {
int column_type=sqlite3_column_type(statement, 0); int column_type=sqlite3_column_type(statement, 0);
switch(column_type) { switch(column_type) {
@ -214,77 +212,37 @@ int overlay_rhizome_add_advertisements(int interface_number,overlay_buffer *e)
continue; continue;
} }
/* XXX This whole section is too hard to follow how the frame gets
built up. In particular the calculations for space required etc
are quite opaque... and I wrote it! */
int overhead=0; int overhead=0;
int frameFull=0;
if (!pass) overhead=2; if (!pass) overhead=2;
if (0) DEBUGF("e=%p, e->bytes=%p,e->length=%d, e->allocSize=%d", e,e->bytes,e->length,e->allocSize);
if (ob_makespace(e,overhead+2+blob_bytes)) { /* make sure there's enough room for the blob, its length,
if (0||debug&DEBUG_RHIZOME) { the 0xFF end marker and 1 spare for the rfs length to increase */
rhizome_manifest *m=rhizome_new_manifest(); if (ob_makespace(e,overhead+blob_bytes+2))
char mdata[blob_bytes]; mdata[0]=0; mdata[1]=0; goto stopStuffing;
sqlite3_blob_read(blob,&mdata[0],blob_bytes,0);
rhizome_read_manifest_file(m,mdata, blob_bytes); if (!pass) {
long long version = rhizome_manifest_get_ll(m, "version"); /* include manifest length field */
DEBUGF("Stop cramming %s advertisements: not enough space for %s*:v%lld (%d bytes, size limit=%d, used=%d)", ob_append_ui16(e, blob_bytes);
pass?"BARs":"manifests",
alloca_tohex(m->cryptoSignPublic, 8),
version,
blob_bytes,e->sizeLimit,e->length);
rhizome_manifest_free(m);
}
frameFull=1;
} else if (!pass) {
/* put manifest length field and manifest ID */
/* XXX why on earth is this being done this way, instead of
with ob_append_byte() ??? */
ob_setbyte(e,e->length,(blob_bytes>>8)&0xff);
ob_setbyte(e,e->length+1,(blob_bytes>>0)&0xff);
if (0&&debug&DEBUG_RHIZOME)
DEBUGF("length bytes written at offset 0x%x",e->length);
} }
if (frameFull) {
sqlite3_blob_close(blob); unsigned char *dest=ob_append_space(e, blob_bytes);
blob=NULL; if (!dest){
WHY("Reading blob will overflow overlay_buffer");
goto stopStuffing; goto stopStuffing;
} }
if (e->length+overhead+blob_bytes>=e->allocSize) {
WHY("Reading blob will overflow overlay_buffer"); if (sqlite3_blob_read(blob,dest,blob_bytes,0) != SQLITE_OK) {
sqlite3_blob_close(blob);
blob=NULL;
continue;
}
if (sqlite3_blob_read(blob,&e->bytes[e->length+overhead],blob_bytes,0) != SQLITE_OK) {
WHYF("sqlite3_blob_read() failed, %s", sqlite3_errmsg(rhizome_db)); WHYF("sqlite3_blob_read() failed, %s", sqlite3_errmsg(rhizome_db));
sqlite3_blob_close(blob); goto stopStuffing;
blob=NULL;
continue;
} }
/* debug: show which BID/version combos we are advertising */
if (0 && (!pass)) {
rhizome_manifest *m = rhizome_new_manifest();
rhizome_read_manifest_file(m, (char *)&e->bytes[e->length+overhead], blob_bytes);
long long version = rhizome_manifest_get_ll(m, "version");
DEBUGF("Advertising manifest %s* version %lld", alloca_tohex(m->cryptoSignPublic, 8), version);
rhizome_manifest_free(m);
}
e->length+=overhead+blob_bytes;
if (e->length>e->allocSize) {
sqlite3_blob_close(blob);
blob=NULL;
FATAL("e->length > e->size");
}
bytes_used+=overhead+blob_bytes;
bundles_advertised++; bundles_advertised++;
bundle_offset[pass]++; bundle_offset[pass]++;
sqlite3_blob_close(blob); sqlite3_blob_close(blob);
blob=NULL; blob=NULL;
ob_checkpoint(e);
} }
} }
stopStuffing: stopStuffing:
@ -294,23 +252,16 @@ int overlay_rhizome_add_advertisements(int interface_number,overlay_buffer *e)
if (statement) if (statement)
sqlite3_finalize(statement); sqlite3_finalize(statement);
statement = NULL; statement = NULL;
ob_rewind(e);
if (!pass) { if (!pass) {
/* Mark end of whole manifests by writing 0xff, which is more than the MSB /* Mark end of whole manifests by writing 0xff, which is more than the MSB
of a manifest's length is allowed to be. */ of a manifest's length is allowed to be. */
ob_append_byte(e,0xff); ob_append_byte(e,0xff);
bytes_used++;
} }
} }
if (blob)
sqlite3_blob_close(blob);
blob = NULL;
if (statement)
sqlite3_finalize(statement);
statement = NULL;
if (debug & DEBUG_RHIZOME)
DEBUGF("Appended %d rhizome advertisements to packet using %d bytes", bundles_advertised, bytes_used);
ob_patch_rfs(e, COMPUTE_RFS_LENGTH); ob_patch_rfs(e, COMPUTE_RFS_LENGTH);
RETURN(0); RETURN(0);
@ -320,8 +271,7 @@ int overlay_rhizome_saw_advertisements(int i,overlay_frame *f, long long now)
{ {
IN(); IN();
if (!f) { RETURN(-1); } if (!f) { RETURN(-1); }
int ofs=0; int ad_frame_type=ob_get(f->payload);
int ad_frame_type=f->payload->bytes[ofs++];
struct sockaddr_in httpaddr = *(struct sockaddr_in *)f->recvaddr; struct sockaddr_in httpaddr = *(struct sockaddr_in *)f->recvaddr;
httpaddr.sin_port = htons(RHIZOME_HTTP_PORT); httpaddr.sin_port = htons(RHIZOME_HTTP_PORT);
int manifest_length; int manifest_length;
@ -331,26 +281,26 @@ int overlay_rhizome_saw_advertisements(int i,overlay_frame *f, long long now)
switch (ad_frame_type) { switch (ad_frame_type) {
case 3: case 3:
/* The same as type=1, but includes the source HTTP port number */ /* The same as type=1, but includes the source HTTP port number */
httpaddr.sin_port = htons((f->payload->bytes[ofs] << 8) + f->payload->bytes[ofs + 1]); httpaddr.sin_port = htons(ob_get_ui16(f->payload));
ofs += 2;
// FALL THROUGH ... // FALL THROUGH ...
case 1: case 1:
/* Extract whole manifests */ /* Extract whole manifests */
while(ofs<f->payload->length) { while(f->payload->position < f->payload->sizeLimit) {
manifest_length=(f->payload->bytes[ofs]<<8)+f->payload->bytes[ofs+1]; if (ob_getbyte(f->payload, f->payload->position)==0xff){
if (manifest_length>=0xff00) { f->payload->position++;
ofs++;
break; break;
} }
if (manifest_length>f->payload->length - ofs) {
assert(inet_ntop(AF_INET, &httpaddr.sin_addr, httpaddrtxt, sizeof(httpaddrtxt)) != NULL); manifest_length=ob_get_ui16(f->payload);
WHYF("Illegal manifest length field in rhizome advertisement frame from %s:%d (%d vs %d)",
httpaddrtxt, ntohs(httpaddr.sin_port), manifest_length, f->payload->length - ofs);
break;
}
ofs+=2;
if (manifest_length==0) continue; if (manifest_length==0) continue;
unsigned char *data = ob_get_bytes_ptr(f->payload, manifest_length);
if (!data) {
assert(inet_ntop(AF_INET, &httpaddr.sin_addr, httpaddrtxt, sizeof(httpaddrtxt)) != NULL);
WHYF("Illegal manifest length field in rhizome advertisement frame %d vs %d.",
manifest_length, f->payload->sizeLimit - f->payload->position);
break;
}
/* Read manifest without verifying signatures (which would waste lots of /* Read manifest without verifying signatures (which would waste lots of
energy, everytime we see a manifest that we already have). energy, everytime we see a manifest that we already have).
@ -364,12 +314,13 @@ int overlay_rhizome_saw_advertisements(int i,overlay_frame *f, long long now)
WHY("Out of manifests"); WHY("Out of manifests");
RETURN(0); RETURN(0);
} }
if (rhizome_read_manifest_file(m, (char *)&f->payload->bytes[ofs],
manifest_length) == -1) { if (rhizome_read_manifest_file(m, (char *)data, manifest_length) == -1) {
WHY("Error importing manifest body"); WHY("Error importing manifest body");
rhizome_manifest_free(m); rhizome_manifest_free(m);
RETURN(0); RETURN(0);
} }
char manifest_id_prefix[RHIZOME_MANIFEST_ID_STRLEN + 1]; char manifest_id_prefix[RHIZOME_MANIFEST_ID_STRLEN + 1];
if (rhizome_manifest_get(m, "id", manifest_id_prefix, sizeof manifest_id_prefix) == NULL) { if (rhizome_manifest_get(m, "id", manifest_id_prefix, sizeof manifest_id_prefix) == NULL) {
WHY("Manifest does not contain 'id' field"); WHY("Manifest does not contain 'id' field");
@ -395,7 +346,7 @@ int overlay_rhizome_saw_advertisements(int i,overlay_frame *f, long long now)
rhizome_manifest_free(m); rhizome_manifest_free(m);
RETURN(0); RETURN(0);
} }
int importManifest=0;
if (rhizome_ignore_manifest_check(m, &httpaddr)) if (rhizome_ignore_manifest_check(m, &httpaddr))
{ {
/* Ignoring manifest that has caused us problems recently */ /* Ignoring manifest that has caused us problems recently */
@ -407,10 +358,12 @@ int overlay_rhizome_saw_advertisements(int i,overlay_frame *f, long long now)
if (rhizome_manifest_version_cache_lookup(m)) { if (rhizome_manifest_version_cache_lookup(m)) {
/* We already have this version or newer */ /* We already have this version or newer */
if (debug & DEBUG_RHIZOME_RX) DEBUG("We already have that manifest or newer."); if (debug & DEBUG_RHIZOME_RX) DEBUG("We already have that manifest or newer.");
importManifest=0;
} else { } else {
if (debug & DEBUG_RHIZOME_RX) DEBUG("Not seen before."); if (debug & DEBUG_RHIZOME_RX) DEBUG("Not seen before.");
importManifest=1;
rhizome_suggest_queue_manifest_import(m, &httpaddr);
// the above function will free the manifest structure, make sure we don't free it again
m=NULL;
} }
} }
else else
@ -420,42 +373,10 @@ int overlay_rhizome_saw_advertisements(int i,overlay_frame *f, long long now)
a minute. */ a minute. */
rhizome_queue_ignore_manifest(m, &httpaddr, 60000); rhizome_queue_ignore_manifest(m, &httpaddr, 60000);
} }
if (m) rhizome_manifest_free(m);
if (m)
rhizome_manifest_free(m);
m=NULL; m=NULL;
if (importManifest) {
/* Okay, so the manifest looks like it is potentially interesting to us,
i.e., we don't already have it or a later version of it.
Now reread the manifest, this time verifying signatures */
if ((m = rhizome_new_manifest()) == NULL)
WHY("Out of manifests");
else if (rhizome_read_manifest_file(m, (char *)&f->payload->bytes[ofs], manifest_length) == -1) {
WHY("Error importing manifest body");
rhizome_manifest_free(m);
m = NULL;
/* PGS @20120626 - Used to verify manifest here, which is before
checking if we already have the bundle or newer. Trouble is
that signature verification is VERY expensive (~400ms on the ideos
phones), so we now defer it to inside
rhizome_suggest_queue_manifest_import(), where it only gets called
after checking that it is worth adding to the queue. */
} else if (m->errors) {
if (debug&DEBUG_RHIZOME) DEBUGF("Verifying manifest %s* revealed errors -- not storing.", manifest_id_prefix);
rhizome_queue_ignore_manifest(m, &httpaddr, 60000);
rhizome_manifest_free(m);
m = NULL;
} else {
if (debug&DEBUG_RHIZOME) DEBUGF("Verifying manifest %s* revealed no errors -- will try to store.", manifest_id_prefix);
/* Add manifest to import queue. We need to know originating IPv4 address
so that we can transfer by HTTP. */
if (0) DEBUG("Suggesting fetching of a bundle");
rhizome_suggest_queue_manifest_import(m, &httpaddr);
}
}
if (!manifest_length) {
WHY("Infinite loop in packet decoding");
break;
}
ofs+=manifest_length;
} }
break; break;
} }

View File

@ -454,22 +454,6 @@ typedef struct overlay_peer {
extern overlay_peer overlay_peers[OVERLAY_MAX_PEERS]; extern overlay_peer overlay_peers[OVERLAY_MAX_PEERS];
typedef struct overlay_buffer {
unsigned char *bytes;
// position of data read / written
int length;
// allocated size of buffer
int allocSize;
// remembered position for rewinding
int checkpointLength;
// maximum allowed bytes for reading / writing
int sizeLimit;
int var_length_offset;
int var_length_bytes;
} overlay_buffer;
int ob_unlimitsize(overlay_buffer *b);
typedef struct overlay_txqueue { typedef struct overlay_txqueue {
struct overlay_frame *first; struct overlay_frame *first;
@ -627,27 +611,6 @@ int overlay_frame_resolve_addresses(overlay_frame *f);
#define alloca_tohex_sid(sid) alloca_tohex((sid), SID_SIZE) #define alloca_tohex_sid(sid) alloca_tohex((sid), SID_SIZE)
#define alloca_tohex_sas(sas) alloca_tohex((sas), SAS_SIZE) #define alloca_tohex_sas(sas) alloca_tohex((sas), SAS_SIZE)
overlay_buffer *ob_new(int size);
overlay_buffer *ob_static(unsigned char *bytes, int size);
int ob_free(overlay_buffer *b);
int ob_checkpoint(overlay_buffer *b);
int ob_rewind(overlay_buffer *b);
int ob_setlength(overlay_buffer *b,int bytes);
int ob_limitsize(overlay_buffer *b,int bytes);
int ob_unlimitsize(overlay_buffer *b);
int ob_makespace(overlay_buffer *b,int bytes);
int ob_append_byte(overlay_buffer *b,unsigned char byte);
int ob_append_bytes(overlay_buffer *b,unsigned char *bytes,int count);
unsigned char *ob_append_space(overlay_buffer *b,int count);
int ob_append_short(overlay_buffer *b,unsigned short v);
int ob_append_int(overlay_buffer *b,unsigned int v);
int ob_patch_rfs(overlay_buffer *b,int l);
int ob_append_rfs(overlay_buffer *b,int l);
int ob_setbyte(overlay_buffer *b,int ofs,unsigned char value);
int ob_getbyte(overlay_buffer *b,int ofs);
int ob_dump(overlay_buffer *b,char *desc);
unsigned int ob_get_int(overlay_buffer *b,int offset);
int op_free(overlay_frame *p); int op_free(overlay_frame *p);
overlay_frame *op_dup(overlay_frame *f); overlay_frame *op_dup(overlay_frame *f);
@ -657,11 +620,11 @@ int overlay_rx_messages();
#define DEBUG_packet_visualise(M,P,N) logServalPacket(LOG_LEVEL_DEBUG, __HERE__, (M), (P), (N)) #define DEBUG_packet_visualise(M,P,N) logServalPacket(LOG_LEVEL_DEBUG, __HERE__, (M), (P), (N))
int overlay_add_selfannouncement(); int overlay_add_selfannouncement();
int overlay_frame_package_fmt1(overlay_frame *p,overlay_buffer *b); int overlay_frame_package_fmt1(overlay_frame *p, struct overlay_buffer *b);
int overlay_interface_args(const char *arg); int overlay_interface_args(const char *arg);
int overlay_get_nexthop(unsigned char *d,unsigned char *nexthop,int *interface); int overlay_get_nexthop(unsigned char *d,unsigned char *nexthop,int *interface);
int overlay_sendto(struct sockaddr_in *recipientaddr,unsigned char *bytes,int len); int overlay_sendto(struct sockaddr_in *recipientaddr,unsigned char *bytes,int len);
int overlay_rhizome_add_advertisements(int interface_number,overlay_buffer *e); int overlay_rhizome_add_advertisements(int interface_number,struct overlay_buffer *e);
int overlay_add_local_identity(unsigned char *s); int overlay_add_local_identity(unsigned char *s);
int overlay_address_is_local(unsigned char *s); int overlay_address_is_local(unsigned char *s);
void overlay_update_queue_schedule(overlay_txqueue *queue, overlay_frame *frame); void overlay_update_queue_schedule(overlay_txqueue *queue, overlay_frame *frame);
@ -674,7 +637,7 @@ extern int overlay_local_identity_count;
extern unsigned char *overlay_local_identities[OVERLAY_MAX_LOCAL_IDENTITIES]; extern unsigned char *overlay_local_identities[OVERLAY_MAX_LOCAL_IDENTITIES];
int overlay_abbreviate_address(unsigned char *in,unsigned char *out,int *ofs); int overlay_abbreviate_address(unsigned char *in,unsigned char *out,int *ofs);
int overlay_abbreviate_append_address(overlay_buffer *b,unsigned char *a); int overlay_abbreviate_append_address(struct overlay_buffer *b,unsigned char *a);
int overlay_abbreviate_expand_address(unsigned char *in,int *inofs,unsigned char *out,int *ofs); int overlay_abbreviate_expand_address(unsigned char *in,int *inofs,unsigned char *out,int *ofs);
int overlay_abbreviate_cache_address(unsigned char *sid); int overlay_abbreviate_cache_address(unsigned char *sid);
@ -731,7 +694,7 @@ int overlay_route_record_link( time_ms_t now,unsigned char *to,
unsigned char *via,int sender_interface, unsigned char *via,int sender_interface,
unsigned int s1,unsigned int s2,int score,int gateways_en_route); unsigned int s1,unsigned int s2,int score,int gateways_en_route);
int overlay_route_dump(); int overlay_route_dump();
int overlay_route_add_advertisements(overlay_buffer *e); int overlay_route_add_advertisements(struct overlay_buffer *e);
int ovleray_route_please_advertise(overlay_node *n); int ovleray_route_please_advertise(overlay_node *n);
int overlay_abbreviate_set_current_sender(unsigned char *in); int overlay_abbreviate_set_current_sender(unsigned char *in);