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 \
Makefile \
overlay_buffer.h \
rhizome.h \
serval.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 */
else
return WHYF("unsupported arg '%s'", argv[1]);
a.addrlist.first_sid=-1;
a.addrlist.first_sid=0;
a.addrlist.last_sid=0x7fffffff;
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 "rhizome.h"
#include "strbuf.h"
#include "overlay_buffer.h"
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);
break;
default:
DEBUGF("Unsupported f->type=0x%x",f->type);
return WHY("Support for that f->type not yet implemented");
return WHYF("Support for f->type=0x%x not yet implemented",f->type);
break;
}
return 0;
@ -214,7 +214,7 @@ int overlay_frame_process(struct overlay_interface *interface,overlay_frame *f)
time_ms_t now = gettime_ms();
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
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 "overlay_buffer.h"
/*
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.
@ -240,17 +240,17 @@ int overlay_abbreviate_try_byindex(unsigned char *in,unsigned char *out,int *ofs
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;
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) {
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;
b->length+=count;
b->position+=count;
overlay_abbreviate_set_most_recent_address(a);
return 0;
}

View File

@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "serval.h"
#include "subscribers.h"
#include "overlay_buffer.h"
/* List of prioritised advertisements */
#define OVERLAY_MAX_ADVERTISEMENT_REQUESTS 16
@ -59,7 +60,7 @@ int overlay_route_please_advertise(overlay_node *n)
struct subscriber *last_advertised=NULL;
int add_advertisement(struct subscriber *subscriber, void *context){
overlay_buffer *e=context;
struct overlay_buffer *e=context;
if (subscriber->node){
overlay_node *n=subscriber->node;
@ -84,7 +85,7 @@ int add_advertisement(struct subscriber *subscriber, void *context){
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.
@ -113,12 +114,14 @@ int overlay_route_add_advertisements(overlay_buffer *e)
*/
int i;
ob_checkpoint(e);
if (ob_append_byte(e,OF_TYPE_NODEANNOUNCE))
return WHY("could not add node advertisement header");
ob_append_byte(e,1); /* TTL */
// 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 */
ob_append_byte(e,OA_CODE_BROADCAST);
@ -142,16 +145,22 @@ int overlay_route_add_advertisements(overlay_buffer *e)
}
*/
struct subscriber *start = last_advertised;
int start_pos = e->position;
// append announcements starting from the last node we advertised
enum_subscribers(start, add_advertisement, e);
// 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);
}
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;
}
@ -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 ofs=0;
IN();
while(ofs<f->payload->length)
while(f->payload->position < f->payload->sizeLimit)
{
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){
//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 */
if (overlay_address_is_local(subscriber->sid)) {
if (debug & DEBUG_OVERLAYROUTING)
DEBUGF("Ignore announcement about me (%s)", alloca_tohex_sid(subscriber->sid));
goto next;
continue;
}
/* 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 (debug & DEBUG_OVERLAYROUTING)
DEBUGF("Ignore announcement about neighbour (%s)", alloca_tohex_sid(subscriber->sid));
goto next;
continue;
}
/* File it */
@ -206,8 +219,6 @@ int overlay_route_saw_advertisements(int i,overlay_frame *f, long long now)
now-2500,now,
score,gateways_en_route);
next:
ofs+=8;
}
RETURN(0);;

View File

@ -18,12 +18,23 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#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;
ob_unlimitsize(ret);
return ret;
@ -31,19 +42,52 @@ overlay_buffer *ob_new(int size)
// index an existing static buffer.
// 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){
overlay_buffer *ret=calloc(sizeof(overlay_buffer),1);
struct overlay_buffer *ob_static(unsigned char *bytes, int size){
struct overlay_buffer *ret=calloc(sizeof(struct overlay_buffer),1);
if (!ret) return NULL;
ret->bytes = bytes;
ret->allocSize =-1;
ret->sizeLimit=size;
ret->allocSize = size;
ret->allocated = 0;
ob_unlimitsize(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->bytes && b->allocSize>0) free(b->bytes);
if (b->bytes && b->allocated) free(b->bytes);
b->bytes=NULL;
b->allocSize=0;
b->sizeLimit=0;
@ -51,109 +95,100 @@ int ob_free(overlay_buffer *b)
return 0;
}
int ob_checkpoint(overlay_buffer *b)
int ob_checkpoint(struct overlay_buffer *b)
{
if (!b) return WHY("Asked to checkpoint NULL");
b->checkpointLength=b->length;
b->checkpointLength=b->position;
return 0;
}
int ob_rewind(overlay_buffer *b)
int ob_rewind(struct overlay_buffer *b)
{
if (!b) return WHY("Asked to rewind NULL");
b->length=b->checkpointLength;
b->position=b->checkpointLength;
return 0;
}
int ob_setlength(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)
int ob_limitsize(struct overlay_buffer *b,int bytes)
{
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->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 (b->allocSize<0) return WHY("Can't change the limit of a static buffer");
b->sizeLimit=bytes;
return 0;
}
int ob_unlimitsize(overlay_buffer *b)
int ob_unlimitsize(struct overlay_buffer *b)
{
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;
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");
return -1;
}
if (b->allocSize<0){
return WHY("Can't resize a static buffer");
return -1;
}
// 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)
DEBUGF("ob_makespace(%p,%d)\n b->bytes=%p,b->length=%d,b->allocSize=%d\n",
b,bytes,b->bytes,b->length,b->allocSize);
DEBUGF("ob_makespace(%p,%d)\n b->bytes=%p,b->position=%d,b->allocSize=%d\n",
b,bytes,b->bytes,b->position,b->allocSize);
if (b->length+bytes>=b->allocSize)
{
int newSize=b->length+bytes;
if (newSize<64) newSize=64;
if (newSize&63) newSize+=64-(newSize&63);
if (newSize>1024) {
if (newSize&1023) newSize+=1024-(newSize&1023);
}
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.
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");
b->bytes=r;
*/
int newSize=b->position+bytes;
if (newSize<64) newSize=64;
if (newSize&63) newSize+=64-(newSize&63);
if (newSize>1024) {
if (newSize&1023) newSize+=1024-(newSize&1023);
}
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.
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");
b->bytes=r;
*/
#ifdef MALLOC_PARANOIA
#warning adding lots of padding to try to catch overruns
if (b->bytes) {
int i;
int corrupt=0;
for(i=0;i<4096;i++) if (b->bytes[b->allocSize+i]!=0xbd) corrupt++;
if (corrupt) {
WHYF("!!!!!! %d corrupted bytes in overrun catch tray", corrupt);
dump("overrun catch tray",&b->bytes[b->allocSize],4096);
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;
if (b->bytes) {
int i;
int corrupt=0;
for(i=0;i<4096;i++) if (b->bytes[b->allocSize+i]!=0xbd) corrupt++;
if (corrupt) {
WHYF("!!!!!! %d corrupted bytes in overrun catch tray", corrupt);
dump("overrun catch tray",&b->bytes[b->allocSize],4096);
sleep(3600);
}
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
*/
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");
b->bytes[b->length++] = byte;
b->bytes[b->position++] = byte;
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];
b->length+=count;
unsigned char *r=&b->bytes[b->position];
b->position+=count;
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");
bcopy(bytes,&b->bytes[b->length],count);
b->length+=count;
bcopy(bytes,&b->bytes[b->position],count);
b->position+=count;
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);
return ob_append_bytes(b,(unsigned char *)&s,sizeof(unsigned short));
if (ob_makespace(b, 2)) return WHY("ob_makespace() failed");
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);
return ob_append_bytes(b,(unsigned char *)&s,sizeof(unsigned int));
if (ob_makespace(b, 4)) return WHY("ob_makespace() failed");
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 */
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
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);
unsigned char c[3]={0,0,0};
@ -228,41 +272,70 @@ int ob_append_rfs(overlay_buffer *b,int l)
*/
int test_offset(overlay_buffer *b,int start,int length){
if (!b) FATAL("b is NULL");
if (start<0) FATALF("passed illegal offset %d",start);
if (b->sizeLimit>=0 && start+length>b->sizeLimit) FATALF("passed offset too large %d", start+length);
if (b->allocSize>=0 && start+length>b->allocSize) FATALF("passed offset too large %d", start+length);
// make sure a range of bytes is valid for reading
int test_offset(struct overlay_buffer *b,int start,int length){
if (!b) return -1;
if (start<0) return -1;
if (b->sizeLimit>=0 && start+length>b->sizeLimit) return -1;
if (start+length>b->allocSize) return -1;
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);
b->bytes[ofs]=value;
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);
if (test_offset(b, ofs, 1))
return -1;
return b->bytes[ofs];
}
unsigned int ob_get_int(overlay_buffer *b,int offset)
{
// TODO unsigned -1? FATAL?
test_offset(b, offset, sizeof(unsigned int));
int ob_get_bytes(struct overlay_buffer *b, unsigned char *buff, int len){
if (test_offset(b, b->position, len))
return -1;
bcopy(b->bytes + b->position, buff, len);
b->position+=len;
return 0;
}
// Some platforms require alignment
if (((uintptr_t)&b->bytes[offset])&3) {
union { unsigned char uc[4]; uint32_t ui32; } bb;
bcopy(&b->bytes[offset], &bb.uc[0], 4);
return ntohl(bb.ui32);
} else
return ntohl(*((uint32_t*)&b->bytes[offset]));
unsigned char * ob_get_bytes_ptr(struct overlay_buffer *b, int len){
if (test_offset(b, b->position, len))
return NULL;
unsigned char *ret = b->bytes + b->position;
b->position+=len;
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)
@ -307,21 +380,21 @@ int rfs_decode(unsigned char *b,int *ofs)
}
// 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;
bcopy(&b->bytes[offset],&b->bytes[offset+shift],b->length-offset);
b->length+=shift;
bcopy(&b->bytes[offset],&b->bytes[offset+shift],b->position-offset);
b->position+=shift;
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){
// 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;
@ -334,13 +407,13 @@ int ob_patch_rfs(overlay_buffer *b,int l)
new_size,b->var_length_bytes,shift);
dump("before indel",
&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 (debug&DEBUG_PACKETCONSTRUCTION) {
dump("after indel",
&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) {
dump("after patch",
&b->bytes[b->var_length_offset],
b->length-b->var_length_offset);
b->position-b->var_length_offset);
}
return 0;
@ -364,10 +437,10 @@ int asprintable(int 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);
dump(NULL, b->bytes, b->length);
DEBUGF("overlay_buffer '%s' at %p : length=%d", desc, b, b->position);
dump(NULL, b->bytes, b->position);
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 "serval.h"
#include "strbuf.h"
#include "overlay_buffer.h"
#ifdef HAVE_IFADDRS_H
#include <ifaddrs.h>
@ -52,7 +53,7 @@ struct profile_total sock_any_stats;
struct outgoing_packet{
overlay_interface *interface;
int i;
overlay_buffer *buffer;
struct overlay_buffer *buffer;
};
struct sched_ent next_packet;
@ -925,7 +926,7 @@ static void
overlay_init_packet(struct outgoing_packet *packet, int interface) {
packet->i = interface;
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_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){
// send the packet
if (packet->buffer->length>=HEADERFIELDS_LEN){
if (packet->buffer->position>=HEADERFIELDS_LEN){
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)
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);
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 "strbuf.h"
#include "subscribers.h"
#include "overlay_buffer.h"
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();
*len=f->payload->length;
*len=f->payload->sizeLimit;
unsigned char *b = NULL;
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:
/* get payload */
b=&f->payload->bytes[0];
*len=f->payload->length;
*len=f->payload->sizeLimit;
mdp->packetTypeAndFlags|=MDP_NOCRYPT|MDP_NOSIGN;
break;
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 */
b=&f->payload->bytes[0];
*len=f->payload->length-crypto_sign_edwards25519sha512batch_BYTES;
*len=f->payload->sizeLimit-crypto_sign_edwards25519sha512batch_BYTES;
/* get hash */
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");
RETURN(NULL); }
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);
if (0) {
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.
*/
overlay_mdp_frame mdp;
int len=f->payload->length;
int len=f->payload->sizeLimit;
/* Get source and destination addresses */
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) */
frame->modifiers=OF_CRYPTO_SIGNED|OF_CRYPTO_CIPHERED;
/* Prepare payload */
frame->payload=ob_new(1 /* frame type (MDP) */
+1 /* MDP version */
+4 /* dst port */
+4 /* src port */
+crypto_box_curve25519xsalsa20poly1305_NONCEBYTES
+crypto_box_curve25519xsalsa20poly1305_ZEROBYTES
+mdp->out.payload_length);
frame->payload=ob_new();
/*length should be;
1 - frame type (MDP)
+1 - MDP version
+4 - dst port
+4 - src port
+crypto_box_curve25519xsalsa20poly1305_NONCEBYTES
+crypto_box_curve25519xsalsa20poly1305_ZEROBYTES
+mdp->out.payload_length*/
{
/* write cryptobox nonce */
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);
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 */
int cipher_offset=frame->payload->length;
int cipher_offset=frame->payload->position;
unsigned char *cipher_text=ob_append_space(frame->payload,cipher_len);
if (fe||(!cipher_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
uses. */
bcopy(&cipher_text[16],&cipher_text[0],cipher_len-16);
frame->payload->length-=16;
frame->payload->position-=16;
if (0) {
DEBUG("authcrypted mdp frame");
dump("nm bytes",k,crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES);
dump("nonce",nonce,crypto_box_curve25519xsalsa20poly1305_NONCEBYTES);
dump("plain text",&plain[16],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],
frame->payload->length);
frame->payload->position);
}
}
break;
@ -838,12 +841,15 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
*/
frame->modifiers=OF_CRYPTO_SIGNED;
/* Prepare payload */
frame->payload=ob_new(1 /* frame type (MDP) */
+1 /* MDP version */
+4 /* dst port */
+4 /* src port */
+crypto_sign_edwards25519sha512batch_BYTES
+mdp->out.payload_length);
frame->payload=ob_new();
/* Length should be;
1 - frame type (MDP)
+1 - MDP version
+4 - dst port
+4 - src port
+crypto_sign_edwards25519sha512batch_BYTES
+mdp->out.payload_length
*/
{
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")); }
@ -893,17 +899,20 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
case MDP_NOSIGN|MDP_NOCRYPT: /* clear text and no signature */
frame->modifiers=0;
/* Copy payload body in */
frame->payload=ob_new(1 /* frame type (MDP) */
+1 /* MDP version */
+4 /* dst port */
+4 /* src port */
+mdp->out.payload_length);
frame->payload=ob_new();
/* Length should be;
1 - frame type (MDP)
+1 - MDP version
+4 - dst port
+4 - src port
+mdp->out.payload_length
*/
/* MDP version 1 */
ob_append_byte(frame->payload,0x01);
ob_append_byte(frame->payload,0x01);
/* Destination port */
ob_append_int(frame->payload,mdp->out.src.port);
ob_append_int(frame->payload,mdp->out.dst.port);
ob_append_ui32(frame->payload,mdp->out.src.port);
ob_append_ui32(frame->payload,mdp->out.dst.port);
ob_append_bytes(frame->payload,mdp->out.payload,mdp->out.payload_length);
break;
}

View File

@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "serval.h"
#include "strbuf.h"
#include "overlay_buffer.h"
struct sockaddr_in loopback = {
.sin_family=0,
@ -236,12 +237,10 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
ensemble */
if (f.type==OF_TYPE_SELFANNOUNCE)
overlay_abbreviate_set_current_sender(f.source);
// TODO refactor all packet parsing to only allocate additional memory for the payload
// if it needs to be queued for forwarding.
/* Create an overlay buffer, wrapping around this static packet */
f.payload = ob_static(&packet[ofs], nextPayload - ofs);
ob_setlength(f.payload, nextPayload - ofs);
ob_limitsize(f.payload, nextPayload - ofs);
/* Finally process the frame */
overlay_frame_process(interface,&f);
@ -257,7 +256,7 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
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
@ -351,9 +350,9 @@ int overlay_add_selfannouncement(int interface,overlay_buffer *b)
// number: one millisecond ago.
if (last_ms == -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");
if (ob_append_int(b, now))
if (ob_append_ui32(b, now))
return WHY("Could not add high sequence number to self-announcement");
if (debug&DEBUG_OVERLAYINTERFACES)
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 "overlay_buffer.h"
int overlay_payload_verify(overlay_frame *p)
{
@ -27,7 +28,7 @@ int overlay_payload_verify(overlay_frame *p)
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];
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.
Assumes that any encryption etc has already been done.
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");
@ -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
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)
DEBUGF("Appending RFS for max_len=%d\n",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 */
overlay_abbreviate_append_address(headers,p->nexthop);
overlay_abbreviate_append_address(headers,p->destination);
overlay_abbreviate_append_address(headers,p->source);
int addrs_len=headers->length-addrs_start;
int actual_len=addrs_len+p->payload->length;
int addrs_len=headers->position-addrs_start;
int actual_len=addrs_len+p->payload->position;
if (debug&DEBUG_PACKETCONSTRUCTION)
DEBUGF("Patching RFS for actual_len=%d\n",actual_len);
ob_patch_rfs(headers,actual_len);
/* 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 */
if (debug&DEBUG_PACKETFORMATS)
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 */
if (ob_append_bytes(b,headers->bytes,headers->length)) {
if (ob_append_bytes(b,headers->bytes,headers->position)) {
WHY("could not append header");
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");
goto cleanup;
}
@ -156,13 +157,6 @@ cleanup:
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)
{
overlay_txqueue *qq=&overlay_tx[q];
@ -191,7 +185,7 @@ int dump_payload(overlay_frame *p,char *message)
message?message:"");
DEBUGF(" next hop is %s",alloca_tohex_sid(p->nexthop));
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;
}
@ -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.
*/
if (0)
WHYF("Enqueuing packet for %s* (q[%d]length = %d)",
if (debug&DEBUG_PACKETTX)
DEBUGF("Enqueuing packet for %s* (q[%d]length = %d)",
alloca_tohex(p->destination, 7),
q,overlay_tx[q].length);
@ -274,16 +268,8 @@ overlay_frame *op_dup(overlay_frame *in)
/* copy main data structure */
bcopy(in,out,sizeof(overlay_frame));
out->payload=ob_new(in->payload->length);
if (!out->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");
}
out->payload=ob_dup(in->payload);
return out;
}

View File

@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "serval.h"
#include "strbuf.h"
#include "subscribers.h"
#include "overlay_buffer.h"
/*
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)) {
/* no open path, so convert to broadcast */
overlay_frame_set_broadcast_as_destination(out);
out->isBroadcast = 1;
out->ttl=2;
if (debug&DEBUG_OVERLAYROUTING)
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.
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
avoid a realloc() if possible */
out->payload=ob_new();
/* XXX - we should merge contiguous observation reports so that packet loss
on the return path doesn't count against the link. */
ob_append_int(out->payload,s1);
ob_append_int(out->payload,s2);
ob_append_ui32(out->payload,s1);
ob_append_ui32(out->payload,s2);
/* The ack needs to contain the per-interface scores that we have built up
for this neighbour.
@ -552,9 +553,9 @@ int overlay_route_saw_selfannounce(overlay_frame *f, time_ms_t now)
RETURN(-1);
}
s1=ob_get_int(f->payload, 0);
s2=ob_get_int(f->payload, 4);
sender_interface=ob_getbyte(f->payload, 8);
s1=ob_get_ui32(f->payload);
s2=ob_get_ui32(f->payload);
sender_interface=ob_get(f->payload);
if (debug&DEBUG_OVERLAYROUTING)
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();
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"));
unsigned int s1=ob_get_int(f->payload,0);
unsigned int s2=ob_get_int(f->payload,4);
int iface=ob_getbyte(f->payload,8);
unsigned int s1=ob_get_ui32(f->payload);
unsigned int s2=ob_get_ui32(f->payload);
int iface=ob_get(f->payload);
// Call something like the following for each link
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 "rhizome.h"
#include <assert.h>
#include "overlay_buffer.h"
#include <stdlib.h>
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 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();
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); }
int pass;
int bytes=e->sizeLimit-e->length;
int bytes=e->sizeLimit-e->position;
int overhead=1+11+1+2+2; /* maximum overhead */
int slots=(bytes-overhead)/RHIZOME_BAR_BYTES;
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;
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"));
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) */
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);
/* 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 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;
for(pass=skipmanifests;pass<2;pass++) {
ob_checkpoint(e);
switch(pass) {
case 0: /* Full manifests */
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)
RETURN(WHY("Could not prepare sql statement for fetching BARs for advertisement"));
while( bytes_used < bytes_available
&& sqlite_step_retry(&retry, statement) == SQLITE_ROW
&& e->length + RHIZOME_BAR_BYTES <= e->sizeLimit
while( sqlite_step_retry(&retry, statement) == SQLITE_ROW
&& e->position+RHIZOME_BAR_BYTES<=e->sizeLimit
) {
int column_type=sqlite3_column_type(statement, 0);
switch(column_type) {
@ -214,77 +212,37 @@ int overlay_rhizome_add_advertisements(int interface_number,overlay_buffer *e)
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 frameFull=0;
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)) {
if (0||debug&DEBUG_RHIZOME) {
rhizome_manifest *m=rhizome_new_manifest();
char mdata[blob_bytes]; mdata[0]=0; mdata[1]=0;
sqlite3_blob_read(blob,&mdata[0],blob_bytes,0);
rhizome_read_manifest_file(m,mdata, blob_bytes);
long long version = rhizome_manifest_get_ll(m, "version");
DEBUGF("Stop cramming %s advertisements: not enough space for %s*:v%lld (%d bytes, size limit=%d, used=%d)",
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);
/* make sure there's enough room for the blob, its length,
the 0xFF end marker and 1 spare for the rfs length to increase */
if (ob_makespace(e,overhead+blob_bytes+2))
goto stopStuffing;
if (!pass) {
/* include manifest length field */
ob_append_ui16(e, blob_bytes);
}
if (frameFull) {
sqlite3_blob_close(blob);
blob=NULL;
unsigned char *dest=ob_append_space(e, blob_bytes);
if (!dest){
WHY("Reading blob will overflow overlay_buffer");
goto stopStuffing;
}
if (e->length+overhead+blob_bytes>=e->allocSize) {
WHY("Reading blob will overflow overlay_buffer");
sqlite3_blob_close(blob);
blob=NULL;
continue;
}
if (sqlite3_blob_read(blob,&e->bytes[e->length+overhead],blob_bytes,0) != SQLITE_OK) {
if (sqlite3_blob_read(blob,dest,blob_bytes,0) != SQLITE_OK) {
WHYF("sqlite3_blob_read() failed, %s", sqlite3_errmsg(rhizome_db));
sqlite3_blob_close(blob);
blob=NULL;
continue;
goto stopStuffing;
}
/* 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++;
bundle_offset[pass]++;
sqlite3_blob_close(blob);
blob=NULL;
ob_checkpoint(e);
}
}
stopStuffing:
@ -294,23 +252,16 @@ int overlay_rhizome_add_advertisements(int interface_number,overlay_buffer *e)
if (statement)
sqlite3_finalize(statement);
statement = NULL;
ob_rewind(e);
if (!pass) {
/* Mark end of whole manifests by writing 0xff, which is more than the MSB
of a manifest's length is allowed to be. */
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);
RETURN(0);
@ -320,8 +271,7 @@ int overlay_rhizome_saw_advertisements(int i,overlay_frame *f, long long now)
{
IN();
if (!f) { RETURN(-1); }
int ofs=0;
int ad_frame_type=f->payload->bytes[ofs++];
int ad_frame_type=ob_get(f->payload);
struct sockaddr_in httpaddr = *(struct sockaddr_in *)f->recvaddr;
httpaddr.sin_port = htons(RHIZOME_HTTP_PORT);
int manifest_length;
@ -331,26 +281,26 @@ int overlay_rhizome_saw_advertisements(int i,overlay_frame *f, long long now)
switch (ad_frame_type) {
case 3:
/* 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]);
ofs += 2;
httpaddr.sin_port = htons(ob_get_ui16(f->payload));
// FALL THROUGH ...
case 1:
/* Extract whole manifests */
while(ofs<f->payload->length) {
manifest_length=(f->payload->bytes[ofs]<<8)+f->payload->bytes[ofs+1];
if (manifest_length>=0xff00) {
ofs++;
while(f->payload->position < f->payload->sizeLimit) {
if (ob_getbyte(f->payload, f->payload->position)==0xff){
f->payload->position++;
break;
}
if (manifest_length>f->payload->length - ofs) {
assert(inet_ntop(AF_INET, &httpaddr.sin_addr, httpaddrtxt, sizeof(httpaddrtxt)) != NULL);
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;
manifest_length=ob_get_ui16(f->payload);
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
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");
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");
rhizome_manifest_free(m);
RETURN(0);
}
char manifest_id_prefix[RHIZOME_MANIFEST_ID_STRLEN + 1];
if (rhizome_manifest_get(m, "id", manifest_id_prefix, sizeof manifest_id_prefix) == NULL) {
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);
RETURN(0);
}
int importManifest=0;
if (rhizome_ignore_manifest_check(m, &httpaddr))
{
/* 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)) {
/* We already have this version or newer */
if (debug & DEBUG_RHIZOME_RX) DEBUG("We already have that manifest or newer.");
importManifest=0;
} else {
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
@ -420,42 +373,10 @@ int overlay_rhizome_saw_advertisements(int i,overlay_frame *f, long long now)
a minute. */
rhizome_queue_ignore_manifest(m, &httpaddr, 60000);
}
if (m) rhizome_manifest_free(m);
if (m)
rhizome_manifest_free(m);
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;
}

View File

@ -454,22 +454,6 @@ typedef struct overlay_peer {
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 {
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_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);
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))
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_get_nexthop(unsigned char *d,unsigned char *nexthop,int *interface);
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_address_is_local(unsigned char *s);
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];
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_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 int s1,unsigned int s2,int score,int gateways_en_route);
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 overlay_abbreviate_set_current_sender(unsigned char *in);