From: victor Date: Wed, 7 Oct 2009 11:20:22 +0000 (+0000) Subject: in progress X-Git-Url: http://p2p-next.cs.pub.ro/gitweb/?a=commitdiff_plain;h=8f35dae460cf3cb65e99b746bd4d7a893079a0d7;p=swift-upb.git in progress git-svn-id: https://ttuki.vtt.fi/svn/p2p-next/TUD/p2tp/trunk@393 e16421f0-f15b-0410-abcd-98678b794739 --- diff --git a/bin64.h b/bin64.h index da45678..e619468 100644 --- a/bin64.h +++ b/bin64.h @@ -22,6 +22,9 @@ struct bin64_t { operator uint64_t () const { return v; } bool operator == (bin64_t& b) const { return v==b.v; } + static bin64_t none () { return NONE; } + static bin64_t all () { return ALL; } + uint64_t tail_bits () const { return v ^ (v+1); } @@ -30,6 +33,10 @@ struct bin64_t { return (tail_bits()+1)>>1; } + bin64_t sibling () const { + // if (v==ALL) return NONE; + return bin64_t(v^(tail_bit()<<1)); + } int layer () const { int r = 0; @@ -49,22 +56,44 @@ struct bin64_t { } uint64_t base_offset () const { - return v&~(tail_bits()); + return (v&~(tail_bits()))>>1; } uint64_t offset () const { return v >> (layer()+1); } + bin64_t to (bool right) const { + if (!(v&1)) + return NONE; + uint64_t tb = tail_bit()>>1; + if (right) + tb |= (tb<<1); + return bin64_t(v^tb); + } + bin64_t left () const { - assert(layer()); - return bin64_t( v ^ (tail_bit()>>1) ); + return to(false); } bin64_t right () const { - assert(layer()); - uint64_t tb = tail_bit(); - return bin64_t( v ^ (tb|(tb>>1)) ); + return to(true); + } + + bool within (bin64_t maybe_asc) { + uint64_t short_tail = maybe_asc.tail_bits(); + if (tail_bits()>short_tail) + return false; + return (v&~short_tail) == (maybe_asc.v&~short_tail) ; + } + + bin64_t towards (bin64_t desc) const { + if (!desc.within(*this)) + return NONE; + if (desc.within(left())) + return left(); + else + return right(); } bin64_t parent () const { @@ -76,6 +105,7 @@ struct bin64_t { uint64_t tb = tail_bit(); return !(v&(tb<<1)); } + bool is_right() const { return !is_left(); } /** The array must have 64 cells, as it is the max number of peaks possible (and there are no reason @@ -96,3 +126,18 @@ struct bin64_t { #endif + +/** + 00111 + 0011 1011 + 001 101 1001 1101 +0 10 100 110 1000 1010 1100 1110 + + 7 + 3 11 + 1 5 9 13 +0 2 4 6 8 10 12 14 + +once we have peak hashes, this struture is more natural than bin-v1 + +*/ diff --git a/bins.cpp b/bins.cpp index 4dd1e3d..e6d580f 100644 --- a/bins.cpp +++ b/bins.cpp @@ -7,17 +7,284 @@ * */ #include "bins.h" +#include -uint16_t bins::SPLIT[256]; -uint8_t bins::JOIN[256]; -uint16_t bins::MASK1000[32]; - -bin64_t bins::find (bin64_t range, int layer) { - // fall to left border - // do - // if up && has 0 success - // if lower && range-shift-trick - // success - // while (next && within range) - // return fail +// make it work piece by piece + +const uint8_t bins::SPLIT[16] = +{0, 3, 12, 15, 48, 51, 60, 63, 192, 195, 204, 207, 240, 243, 252, 255}; +const uint8_t bins::JOIN[16] = +{0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15}; +const int bins::NOJOIN = 0x10000; + + +void bins::extend () { + uint16_t nblocks = blocks_allocated ? (blocks_allocated<<1) : 1; + size_t had_bytes = blocks_allocated<<6; + size_t need_bytes = nblocks<<6; + cells = (uint32_t*) realloc(cells,need_bytes); + memset(((char*)cells)+had_bytes,0,need_bytes-had_bytes); + for(int b=blocks_allocated; b29 ) + printf("|%x ",halves[i]); + else if (deep(i)) + printf(">%i ",halves[i]); + else + printf("%x ",halves[i]); + if (i&1) + printf(" "); + } + printf("\n"); +} + +uint32_t bins::split16to32(uint16_t halfval) { + uint32_t nval = 0; + for(int i=0; i<4; i++) { + nval >>= 8; + nval |= (SPLIT[halfval&0xf])<<24; + halfval >>= 4; + } + return nval; +} + + +int bins::join32to16(uint32_t cval) { + union { uint32_t i; uint8_t a[4]; } uvar; + uvar.i = cval & (cval>>1) & 0x55555555; + if ( (uvar.i|(uvar.i<<1)) != cval ) + return NOJOIN; + uvar.i = (uvar.i&0x05050505) | ((uvar.i&0x50505050U)>>3); + uint16_t res = 0; + for(int i=3; i>=0; i--) { + res <<= 4; + res |= JOIN[uvar.a[i]]; + } + return res; +} + + +void bins::split (uint32_t half) { + if (deep(half)) + return; + uint32_t cell = alloc_cell(), left=cell<<1, right=left+1; + mark(half); //cells[(half>>1)|0xf] |= 1<<(half&0x1f); + uint16_t halfval = halves[half]; + uint32_t nval = split16to32(halfval); + halves[left] = nval&0xffff; + halves[right] = nval>>16; + halves[half] = cell; +} + + +bool bins::join (uint32_t half) { + uint32_t cellno = halves[half]; + int left = cellno<<1, right=left+1; + if (deep(left) || deep(right)) + return false; + int res = join32to16(cells[cellno]); + if (res>0xffff) + return false; + halves[half] = (uint16_t)res; + unmark(half); + free_cell(cellno); + //cells[(half>>1)|0xf] &= ~(1<<(half&0x1f)); + //(*childdeepcell) &= 0xffff>>1; // clean the full bit + return true; +} + +void bins::free_cell (uint16_t cell) { + cells[cell] = 0; + int left = cell<<1, right=left+1; + mark(left); + unmark(right); + if (ap==cell+1) + ap--; + cells_allocated--; +} + +/** Get a free cell. */ +uint16_t bins::alloc_cell () { + uint16_t ap1 = ap; + cells_allocated++; + for(; ap<(blocks_allocated<<4); ap++) { + if ((ap&0xf)==0xf) + continue; + if (!cells[ap] && deep(ap<<1)) { + unmark(ap<<1); + return ap++; + } + } + if (ap1) + ap = 0; + else + extend(); + cells_allocated--; + return alloc_cell(); +} + + +bin64_t iterator::next (bool need_solid) { + assert(!deep()); + while (pos.is_right()) + parent(); + //parent(); + //if (need_solid ? !solid() : deep()) + // right(); + sibling(); + while (need_solid ? !solid() : deep()) + left(); + return pos; +} + + +iterator::iterator(bins* host_, bin64_t start, bool split) { + host = host_; + half = 0; + for(int i=0; i<64; i++) + history[i] = 1; + pos = bin64_t(host->height,0); + while (!start.within(pos)) + parent(); + while (pos!=start && (deep() || split)) + towards(start); +} + + +iterator::~iterator () { + while (half>1 && !deep()) + parent(); + // PROBLEM: may hang in the air if two iters + // exist simultaneously + // FIX: iterators are not exposed (protected) +} + + +void iterator::to (bool right) { + if (!deep()) + host->split(half); + history[pos.layer()] = half; // FIXME + pos = pos.to(right); + half = (host->halves[half]<<1) + right; + //host->dump("/\\ "); +} + + +void bins::extend_range () { + assert(height<62); + height++; + uint16_t newroot = alloc_cell(); + int left = newroot<<1, right = left+1; + cells[newroot] = cells[0]; + halves[0] = newroot; + halves[1] = 0; + if (deep(0)) + mark(left); + else + mark(0); + if (deep(1)) { + mark(right); + unmark(1); + } +} + +void iterator::parent () { + if (!half) { + host->extend_range(); + history[pos.layer()+1] = 0; + } + pos = pos.parent(); + half = history[pos.layer()]; + host->join(half); + //host->dump("| "); +} + + +bin64_t bins::find (const bin64_t range, const uint8_t layer) { + iterator i(this,range,true); + while (true) { + while ( i.bin().layer()>layer && (i.deep() || *i!=FILLED) ) + i.left(); + if (i.bin().layer()==layer && !i.deep() && *i==EMPTY) + return i.bin(); + while (i.bin().is_right() && i.bin()!=range) + i.parent(); + if (i.bin()==range) + break; + i.parent(); + i.right(); + } + return bin64_t::NONE; +} + + +uint16_t bins::get (bin64_t bin) { + iterator i(this,bin,true); + //while ( i.pos!=bin && + // (i.deep() || (*i!=BIN_FULL && *i!=BIN_EMPTY)) ) + // i.towards(bin); + //printf("at %i ",i.half); + //dump("get made"); + return *i; // deep cell is never 0xffff or 0x0000 +} + + +void bins::set (bin64_t bin, fill_t val) { + assert(val==FILLED || val==EMPTY); + iterator i(this,bin,false); + while (i.bin()!=bin && (i.deep() || *i!=val)) + i.towards(bin); + if (!i.deep() && *i==val) + return; + while (i.deep()) + i.left(); + do { + *i = val; + i.next(); + } while (i.bin().within(bin)); + // dump("just set"); +} + + +uint64_t* bins::get_stripes (int& count) { + int size = 32; + uint64_t *stripes = (uint64_t*) malloc(32*8); + count = 0; + uint16_t cur = bins::EMPTY; + stripes[count++] = 0; + iterator i(this,0,false); + while (!i.solid()) + i.left(); + + while (!i.end()) { + + if (cur!=*i) { // new stripe + cur = *i; + stripes[count++] = i.bin().base_offset(); + if (count==size) { + size <<= 1; + stripes = (uint64_t*) realloc(stripes,size*8); + } + } + + i.next(true); + + } + + if ( !(count&1) ) + stripes[count++] = i.bin().base_offset(); + + return stripes; } diff --git a/bins.h b/bins.h index d95406f..ca226df 100644 --- a/bins.h +++ b/bins.h @@ -6,86 +6,121 @@ * Copyright 2009 Delft Technical University. All rights reserved. * */ -#ifndef SERP_SBIT_H -#define SERP_SBIT_H +#ifndef BINS_H +#define BINS_H #include "bin64.h" +#include -class bins64 { +/** A binmap covering 2^64 range. Complexity limit: 100+200LoC */ +class bins { + +public: + typedef enum { FILLED=0xffff, EMPTY=0x0000 } fill_t; + static const int NOJOIN; + + bins(); + + uint16_t get (bin64_t bin); + + void set (bin64_t bin, fill_t val=FILLED); + + bin64_t find (const bin64_t range, const uint8_t layer) ; + + void dump(const char* note); - private: + uint64_t* get_stripes (int& count); - uint32_t *bits; - uint32_t alloc_block; - - protected: - - bool join(uint32_t half) { - uint32_t cellno = bits[half]>>(half&1?16:0); - - if (deep(left) || deep(right)) // some half is deep - return false; - uint8_t b1=JOIN[cell&0xf], - b2=JOIN[(cell>>8)&0xf], - b3=JOIN[(cell>>16)&0xf], - b4=JOIN[cell>>24]; - if (b1==0xff || b2==0xff || b3==0xff || b4==0xff) - return false; - bits[half] = b1 | (b2<<4) | (b3<<8) | (b4<<12) ; - (*parentdeepcell) ^= 1<<(halfno&32); - (*childdeepcell) &= 0xffff>>1; // clean the full bit - } - - bool split(uint32_t half) { - if (deep(half)) - return false; - uint32_t cell = alloc_cell(), left=cell<<1, right=left+1; - bits[half|0xf] |= 1<<(half&0xf); - bits[left] = SPLIT[bits[half]>>8]; - bits[right] = SPLIT[bits[half&0xff]]; - bits[half] = cell; - return true; - } - - uint32_t alloc_cell () { - do{ - for(int block=alloc_block; bits[block]&(1<<32); block+=32); - for(int off=0; bits[block+off]==0 && off<31; off++); - if (off==31) - bits[block] |= 1<<32; - if (block&(1<<31)) { - bits = realloc(bits,block*2); - memset(); - } - } while (off==31); - alloc_block = block; - return block+off; - } - - public: - - class iterator { - bins64_t *host; - uint32_t back[32]; - uint32_t half; - bin64_t top; - bin64_t focus; - bin16_t mask; - public: - void left(); - void right(); - void parent(); - bin64_t next(); - bool defined(); - uint16_t& operator* (); - }; - friend class iterator; - - bool get (uint64_t bin); - - void set (uint64_t bin); - - bin64_t find (bin64_t range, int layer); + uint32_t size() { return cells_allocated; } + // TODO: bitwise operators + +private: + + /** Every 16th uint32 is a flag field denoting whether + previous 30 halves (in 15 cells) are deep or not. + The last bit is used as a fill-flag. + Free cells have a value of 0; neither deep nor flat + cell could have a value of 0 except for the root + cell in case the binmap is all-0. */ + union { + uint32_t *cells; + uint16_t *halves; + }; + uint32_t blocks_allocated; + uint32_t cells_allocated; + int height; + uint32_t ap; + + void extend(); + + static const uint8_t SPLIT[16]; + static const uint8_t JOIN[16]; + + bool deep(uint32_t half) const { + return cells[(half>>1)|0xf] & (1<<(half&0x1f)); + } + void mark(uint32_t half) { + cells[(half>>1)|0xf] |= (1<<(half&0x1f)); + } + void unmark(uint32_t half) { + cells[(half>>1)|0xf] &= ~(1<<(half&0x1f)); + } + + void extend_range(); + + uint16_t alloc_cell (); + void free_cell (uint16_t cell); + + /** Join the cell this half is pointing to + (in other words, flatten the half). */ + bool join(uint32_t half) ; + + /** Make the half deep. */ + void split(uint32_t half) ; + + static uint32_t split16to32(uint16_t half); + static int join32to16(uint32_t cell); + + friend class iterator; + FRIEND_TEST(BinsTest,Routines); +}; - // TODO: bitwise operators +/** Iterates over bins; for deep halves, bin==half. + For flat halves, bin is a range of bits in a half. + Iterator may split cells if needed. + Value is either undefined (deep cell, mixed cell) + or FILLED/EMPTY. */ +class iterator { +public: // rm this + bins *host; + uint32_t history[64]; + uint32_t half; + bin64_t pos; // TODO: half[] layer bin +public: + iterator(bins* host, bin64_t start=0, bool split=false); + ~iterator(); + bool deep () { return host->deep(half); } + bool solid () { + return !deep() && (host->halves[half]==bins::FILLED || + host->halves[half]==bins::EMPTY); + } + void sibling () { half^=1; pos=pos.sibling(); } + bool end () { return half==1; } + void to (bool right); + void left() {to(0);} + void right() {to(1);} + /** Move to the next defined (non-deep, flat) cell. + If solid==true, move to a solid (0xffff/0x0) cell. */ + bin64_t next (bool solid=false); + bin64_t bin() { return pos; } + void towards(bin64_t bin) { + bin64_t next = pos.towards(bin); + assert(next!=bin64_t::NONE); + to(next.is_right()); + } + void parent() ; + bool defined() { return !host->deep(half); } + uint16_t& operator* () { return host->halves[half]; } }; + +#endif diff --git a/collisions.cpp b/collisions.cpp deleted file mode 100644 index 24c3173..0000000 --- a/collisions.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * collisions.cpp - * serp++ - * - * Created by Victor Grishchenko on 3/15/09. - * Copyright 2009 Delft Technical University. All rights reserved. - * - */ -#include "bin.h" -#include "sbit.h" -#include -#include - -using namespace std; - -#define NUMPEERS 40 -#define QUEUE_LEN 32 -#define WIDTH 20 -#define TOP (bin(WIDTH,0)) - -sbit bigpic; // common knowledge - -struct Peer { - deque packets; // packets in flight & unacknowledged - feye map; - int peerno; - bin focus; - Peer () : map(bigpic,bin(0,rand()%(1<6) - map.refocus(focus); - if (labs(map.focus-focus)>=129) - printf("bred!\n"); - map |= focus; - // sanity check - if (bigpic.get(focus)) - printf("zhopa: peer %i redid %x after jumped %i\n", - peerno,focus.offset(),oldfoc.commonParent(focus).layer()); - assert(focus.layer()==0 && focus=QUEUE_LEN) { // round trip, acks reach senders - bin packet = peers[i].packets.front(); - peers[i].packets.pop_front(); - if (packet==0) continue; - bool collision = bigpic.get(packet); - bin round = bigpic.set(packet); - printf("peer %i arrived %x filled %i coll %i\n", - i,packet.offset(),round.layer(),collision); - for(int j=0; j - -using namespace p2tp; - -CongestionControl::CongestionControl () { - state_ = SLOW_START_STATE; - cwnd_ = 1; - cainc_ = 0; - ssthresh_ = 100; - rtt_avg_ = 0; - dev_avg_ = 0; - peer_cwnd_ = 0; - data_ins_ = 0; - last_arrival_ = 0; - rate_ = TINT_1SEC/10; -} - - -void CongestionControl::RttSample (tint rtt) { - if (rtt_avg_>0) { - rtt_avg_ = (rtt_avg_*7 + rtt) >> 3; // affected by reordering - dev_avg_ = (dev_avg_*7 + ::abs(rtt-rtt_avg_)) >> 3; - } else { - rtt_avg_ = rtt; - dev_avg_ = rtt>>3; - } - DLOG(INFO)<<"sample "<=ssthresh_) - state_ = CONG_AVOID_STATE; - } else if (state_==CONG_AVOID_STATE) { - cainc_++; - if (cainc_>=cwnd_) { - cainc_ = 0; - cwnd_++; - } - } - break; - case DATA_EV: - tint interarrival = last_arrival_ ? - Datagram::now - last_arrival_ : - rtt_avg_; // starting est. corresp. cwnd==1 - last_arrival_ = Datagram::now; - if (rate_) - rate_ = ( rate_*3 + interarrival ) / 4; - else - rate_ = interarrival; - break; - } - DLOG(INFO)<<"peer irr "< rate_/2 ) // too many / - pc++; - return pc; -} - -int CongestionControl::peer_bps () const { - return 1024 * TINT_1SEC / rate_; -} diff --git a/ledbat_controller.cpp b/ledbat_controller.cpp new file mode 100644 index 0000000..87a705d --- /dev/null +++ b/ledbat_controller.cpp @@ -0,0 +1,35 @@ +/* + * ledbat_controller.cpp + * p2tp + * + * Created by Victor Grishchenko on 10/6/09. + * Copyright 2009 Delft Technical University. All rights reserved. + * + */ + +#include "p2tp.h" + +using namespace p2tp; + +class LedbatController : public CongestionController { +public: + /*tint rtt_avg; + tint dev_avg; + int cwnd; + int peer_cwnd;*/ + virtual void OnTimeout () { + } + + virtual void OnDataSent(bin64_t b) { + } + + virtual void OnDataRecvd(bin64_t b) { + } + + virtual void OnAckRcvd(bin64_t b, tint peer_stamp) { + } + + virtual ~CongestionControl() { + } + +}; diff --git a/p2tp.h b/p2tp.h index 45a2ea6..a5ac644 100644 --- a/p2tp.h +++ b/p2tp.h @@ -17,14 +17,15 @@ Messages initial handshake packet also has the root hash (a HASH message). - DATA 01, bin, buffer + DATA 01, bin_32, buffer 1K of data. - ACK 02, bin + ACK 02, bin_32 + ACKTS 08, bin_32, timestamp_32 Confirms successfull delivery of data. Used for congestion control, as well. - - HINT 03, bin + + HINT 03, bin_32 Practical value of "hints" is to avoid overlap, mostly. Hints might be lost in the network or ignored. Peer might send out data without a hint. @@ -33,153 +34,156 @@ Messages As peers cant pick randomly kilobyte here and there, they send out "long hints" for non-base bins. - HASH 04, bin, sha1hash + HASH 04, bin_32, sha1hash SHA1 hash tree hashes for data verification. The connection to a fresh peer starts with bootstrapping him with peak hashes. Later, before sending out any data, a peer sends the necessary uncle hashes. - PEX+/PEX- 05/06, ip, port + PEX+/PEX- 05/06, ipv4 addr, port Peer exchange messages; reports all connected and disconected peers. Might has special meaning (as in the case with swarm supervisors). - --8X---- maybe (give2get) - - CRED 07, scrchid - Communicated the public channel id at the sender - side. Any grandchildren's credits will go to this - channel. - - CRED1/2 08/09, ip, port, scrchid - Second-step and trird-step credits. - - ACK1/2 10/11, scrchid, packets - Grandchildren's acknowledgements of data being - received from a child; the public channel id - is mentioned. - */ #ifndef P2TP_H #define P2TP_H #include -#include #include #include -#include "bin.h" -#include "sbit.h" +#include "bin64.h" +#include "bins.h" #include "datagram.h" #include "hashtree.h" namespace p2tp { - /* 64-bit time counter, microseconds since epoch - typedef int64_t tint; - static const tint TINT_1SEC = 1000000; - static const tint TINT_1MSEC = 1000; - static const tint TINT_INFINITY = 0x7fffffffffffffffULL; - */ - struct tintbin { - tint time; - bin pos; - tintbin(tint t, bin p) : time(t), pos(p) {} - }; - typedef std::deque tbinvec; + typedef std::pair tintbin; + + typedef std::deque tbqueue; + typedef std::deque binqueue; typedef enum { P2TP_HANDSHAKE = 0, P2TP_DATA = 1, P2TP_ACK = 2, + P2TP_ACKTS = 8, P2TP_HINT = 3, P2TP_HASH = 4, P2TP_PEX_ADD = 5, P2TP_PEX_RM = 6, P2TP_MESSAGE_COUNT = 7 } messageid_t; + + class PiecePicker; + class CongestionController; + class PeerSelector; - struct File { - - typedef enum {EMPTY,IN_PROGRESS,DONE} status_t; - - static std::vector files; + class FileTransfer { - /** File descriptor. */ - int fd; - /** Whether the file is completely downloaded. */ - status_t status_; - - // A map for all packets obtained and succesfully checked. - bins ack_out; - // Hinted packets. - bins hint_out; + public: - HashTree hashes; - // History of bin retrieval. - bin::vec history; + /** Offer a hash; returns true if it verified; false otherwise. + Once it cannot be verified (no sibling or parent), the hash + is remembered, while returning false. */ + bool OfferHash (bin64_t pos, const Sha1Hash& hash); + /** Offer data; the behavior is the same as with a hash: + accept or remember or drop. */ + bool OfferData (bin64_t bin, uint8_t* data); + + const Sha1Hash& root_hash () const { return *root_hash; } + + size_t size () const; + size_t packet_size () const; + size_t size_complete () const; + size_t packets_complete () const; - // TBD - uint64_t options; + static FileTransfer* find (const Sha1Hash& hash); + static FileTransfer* file (int fd) { return fd files; + + /** Open/submit/retrieve a file. */ + FileTransfer (Sha1Hash hash, char* file_name); /** Close everything. */ - ~File(); + ~FileTransfer(); - bool OfferHash (bin pos, const Sha1Hash& hash); - const Sha1Hash& root_hash () const { return hashes.root; } - size_t size () const { return hashes.data_size()<<10; } - size_t packet_size () const { return hashes.data_size(); } - status_t status () const { return status_; } - - static File* find (const Sha1Hash& hash); - static File* file (int fd) { return fd channels; - static int* sockets_; - static int sock_count_; - static tint last_tick; - //static int socket; + static Channel* channel(int i) {return i channels; + static tint last_tick; + }; - //int connect (int fd, const struct sockaddr_in& addr, uint32_t peerch=0) ; - void Loop (tint time=0) ; - int Init (int portno) ; - void Shutdown (int portno); - - uint32_t Width (const tbinvec& v); + //uint32_t Width (const tbinvec& v); } #define RETLOG(str) { LOG(WARNING)<ack_out); + } + + virtual bin64_t Pick (bins& from, uint8_t layer) { + bins may_pick = ~ file->ack_out; + may_pick &= from; + may_pick -= hint_out; + bin64_t pick = may_pick.find(file->top,bins::FILLED); + if ( pick==bin64_t::NONE || pick.right_foot() > file->size() ) + if (layer) + return Pick(from,layer-1); + else + return bin64_t::NONE; + return pick; + } + + virtual void Received (bin64_t b) { + diho.set(b,bins::FILLED); + } + + virtual void Snubbed (bin64_t b) { + diho.set(b,bins::EMPTY); + } + +}; \ No newline at end of file diff --git a/simple_selector.cpp b/simple_selector.cpp new file mode 100644 index 0000000..e0d54e8 --- /dev/null +++ b/simple_selector.cpp @@ -0,0 +1,34 @@ +/* + * simple_selector.cpp + * p2tp + * + * Created by Victor Grishchenko on 10/6/09. + * Copyright 2009 Delft Technical University. All rights reserved. + * + */ + +#include "p2tp.h" + +using namespace p2tp; + +class SimpleSelector : public PeerSelector { + typedef std::pair memo_t; + std::queue peers; +public: + virtual void PeerKnown (const Sha1Hash& root, struct sockaddr_in& addr) { + peers.push_front(memo_t(addr,root.fingerprint())); + } + virtual sockaddr_in GetPeer (const Sha1Hash& for_root) { + uint32_t fp = for_root.fingerprint(); + for(std::queue::iterator i=peers.begin(); i!=peers.end(); i++) + if (i->second==fp) { + i->second = 0; + sockaddr_in ret = i->first; + while (peers.begin()->second==0) + peers.pop_front(); + return ret; + } + } +}; + +static Channel::peer_selector = new SimpleSelector(); \ No newline at end of file diff --git a/tests/SConscript b/tests/SConscript index 9bce647..8a64f7f 100644 --- a/tests/SConscript +++ b/tests/SConscript @@ -42,6 +42,13 @@ env.Program( LIBS=['p2tp','stdc++','gtest','glog','crypto'], LIBPATH='..' ) +env.Program( + target='freemap', + source=['freemap.cpp'], + CPPPATH=['..'], + LIBS=['p2tp','stdc++','gtest','glog'], + LIBPATH='..' ) + env.Program( target='bin64test', source=['bin64test.cpp','../bin64.h'], diff --git a/tests/freemap.cpp b/tests/freemap.cpp new file mode 100755 index 0000000..f98b33a --- /dev/null +++ b/tests/freemap.cpp @@ -0,0 +1,74 @@ +/* + * binstest.cpp + * serp++ + * + * Created by Victor Grishchenko on 3/22/09. + * Copyright 2009 Delft Technical University. All rights reserved. + * + */ +#include +#include +#include +#include "bins.h" + +int bins_stripe_count (bins& b) { + int stripe_count; + uint64_t * stripes = b.get_stripes(stripe_count); + free(stripes); + return stripe_count; +} + +uint8_t rand_norm (uint8_t lim) { + long rnd = random() & ((1<>= 1; + } + return bits; +} + +TEST(FreemapTest,Freemap) { + bins space; + const bin64_t top(30,0); + space.set(top,bins::EMPTY); + typedef std::pair timebin_t; + typedef std::set ts_t; + ts_t to_free; + for (int t=0; t<1000000; t++) { + if (t<500000 || t>504000) { + uint8_t lr = rand_norm(28); + bin64_t alloc = space.find(top,lr); + ASSERT_NE(0ULL,~alloc); + EXPECT_EQ(bins::EMPTY, space.get(alloc)); + space.set(alloc,bins::FILLED); + long dealloc_time = 1<first<=t) { + bin64_t freebin = to_free.begin()->second; + to_free.erase(to_free.begin()); + space.set(freebin,bins::EMPTY); + printf("freed at %lli\n", + (uint64_t)freebin); + } + // log: space taken, gaps, binmap cells, tree cells + int cells = space.size(); + int intervals = bins_stripe_count(space); + printf("time %i cells used %i intervals %i blocks %i\n", + t,cells,intervals,(int)to_free.size()); + //space.dump("space"); + } + for(ts_t::iterator i=to_free.begin(); i!=to_free.end(); i++) + space.set(i->second,bins::EMPTY); + EXPECT_EQ(bins::EMPTY,space.get(top)); +} + +int main (int argc, char** argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/transfer.cpp b/transfer.cpp new file mode 100644 index 0000000..f268f84 --- /dev/null +++ b/transfer.cpp @@ -0,0 +1,188 @@ +/* + * transfer.cpp + * p2tp + * + * Created by Victor Grishchenko on 10/6/09. + * Copyright 2009 Delft Technical University. All rights reserved. + * + */ + +#include "p2tp.h" + + +File::File (int _fd) : fd(_fd), status_(DONE), hashes(_fd) +{ + bin::vec peaks = bin::peaks(hashes.data_size()); + history.insert(history.end(),peaks.begin(),peaks.end()); + for(bin::vec::iterator i=peaks.begin(); i!=peaks.end(); i++) + ack_out.set(*i); +} + +File::File (Sha1Hash hash, int _fd) : hashes(hash), fd(_fd), status_(EMPTY) { + // TODO resubmit data +} + +File::~File() { + if (fd>0) ::close(fd); +} + + +bool File::OfferHash (bin pos, const Sha1Hash& hash) { + HashTree::hashres_t res = hashes.offer(pos,hash); + if (res==HashTree::PEAK_ACCEPT) { // file size is finally known + ftruncate(fd, size()); + LOG(INFO)<::iterator i=files.begin(); i!=files.end(); i++) + if (*i && (*i)->hashes.root==hash) + return *i; + return NULL; +} + + +int p2tp::Open (const char* filename) { + int fd = ::open(filename,O_RDONLY); + if (fd<0) + return -1; + if (File::files.size()size(); } + +void p2tp::Close (int fid) { + if (!File::files[fid]) + return; + delete File::files[fid]; + File::files[fid] = NULL; +} + + +Sha1Hash HashTree::deriveRoot () { + int i = peak_count-1; + bin64_t p = peaks[i].first; + Sha1Hash hash = peak_hashes[i].second; + i--; + while (pmass) + return REJECT; + if (status[pos]) + return bits[pos]==hash ? ACCEPT : REJECT; + bits[pos] = hash; + // walk to the nearest proven hash + if (bits[pos.sibling()]==Sha1Hash::ZERO) + return DUNNO; + bin p = pos.parent(); + while (!status[p]) { + bits[p] = Sha1Hash(bits[p.left()],bits[p.right()]); + p = p.parent(); + } + if ( bits[p] == Sha1Hash(bits[p.left()],bits[p.right()]) ) { + for(bin i=pos; i