From: victor Date: Thu, 17 Sep 2009 10:53:44 +0000 (+0000) Subject: import X-Git-Url: http://p2p-next.cs.pub.ro/gitweb/?a=commitdiff_plain;h=10fa06b998e30051431bd577ae36757cce7be200;p=swift-upb.git import git-svn-id: https://ttuki.vtt.fi/svn/p2p-next/p2tp@380 e16421f0-f15b-0410-abcd-98678b794739 --- 10fa06b998e30051431bd577ae36757cce7be200 diff --git a/.sconsign.dblite b/.sconsign.dblite new file mode 100644 index 0000000..fa060ce Binary files /dev/null and b/.sconsign.dblite differ diff --git a/SConstruct b/SConstruct new file mode 100644 index 0000000..f1d6cfe --- /dev/null +++ b/SConstruct @@ -0,0 +1,14 @@ +import os +import re + +TestDir='tests' + +env = Environment(CPPPATH = ['.']) + +env.SharedLibrary ( + target='p2tp', + source = [ 'bin.cpp','hashtree.cpp','datagram.cpp', + 'sbit.cpp' ], + LIBS=['stdc++','gtest','glog','crypto'] ) + +SConscript('tests/SConscript') diff --git a/bin.cpp b/bin.cpp new file mode 100644 index 0000000..187dde4 --- /dev/null +++ b/bin.cpp @@ -0,0 +1,59 @@ +/* + * bin.cpp + * serp++ + * + * Created by Victor Grishchenko on 3/6/09. + * Copyright 2009 Delft Technical University. All rights reserved. + * + */ + +#include "bin.h" +#include + +bin bin::NONE = 0; +bin bin::ALL = 0x7fffffff; +uint8_t bin::BC[256] = {}; +uint8_t bin::T0[256] = {}; + +void bin::init () { + for(int i=0; i<256; i++) { + int bc=0, bit; + for(bit=0; bit<8; bit++) + if ((i>>bit)&1) bc++; + BC[i] = bc; + for(bit=0; bit<8 && ((i>>bit)&1)==0; bit++); + T0[i] = bit; + } +} + +bin::vec bin::peaks (uint32_t len) { + bin::vec pks; + uint32_t i=len, run=0; + while (i) { + uint32_t bit = bin::highbit(i); + i^=bit; + run |= bit; + pks.push_back(lenpeak(run)); + } + return pks; +} + +void bin::order (vec* vv) { + vec& v = *vv; + std::sort(v.begin(),v.end()); + std::reverse(v.begin(),v.end()); + vec::iterator pw=v.begin(), pr=v.begin(); + while (pr!=v.end()) { + *pw = *pr; + while (pw!=v.begin() && (pw-1)->sibling()==*pw) { + pw--; + *pw = pw->parent(); + } + bin skipto = *pw - pw->mass(); + while (pr!=v.end() && *pr>skipto) { + pr++; + } + pw++; + } + v.resize(pw-v.begin()); +} diff --git a/bin.h b/bin.h new file mode 100644 index 0000000..3742b88 --- /dev/null +++ b/bin.h @@ -0,0 +1,234 @@ +/* + * bin.h + * serp++ + * + * Created by Victor Grishchenko on 3/6/09. + * Copyright 2009 Delft Technical University. All rights reserved. + * + */ +#ifndef BIN_H +#define BIN_H +#include +#include +#include + +struct bin { + uint32_t b; + + static bin NONE; + static bin ALL; + static uint8_t BC[256]; + static uint8_t T0[256]; + + bin() : b(0) {} + bin(const bin& b_) : b(b_.b) {} + bin(uint32_t b_) : b(b_) {} + + bin(uint8_t layer_, uint32_t offset) { + b = lenpeak((offset+1)<>=16; + if ( (i&0xff)==0 ) + ret +=8, i>>=8; + return ret+T0[i&0xff]; + } + + static uint8_t bitcount (uint32_t i) { + //uint8_t* p = (uint8_t*) &i; + //return BC[p[0]] + BC[p[1]] + BC[p[2]] + BC[p[3]]; + return BC[i&0xff] + + BC[(i>>8)&0xff] + + BC[(i>>16)&0xff] + + BC[i>>24]; + } + + static uint32_t blackout (uint32_t i) { + return i|=(i|=(i|=(i|=(i|=i>>1)>>2)>>4)>>8)>>16; + } + + static uint32_t highbit (uint32_t i) { + return (blackout(i)+1)>>1; + } + + static bool all1 (uint32_t a) { + return !(a&(a+1)); + } + + static bin lenpeak (uint32_t length) { + return (length<<1) - bitcount(length); + } + + static uint8_t lenlayer (uint32_t len) { + return tailzeros(len); + } + + static bin layermass (uint8_t layer) { + return (2< vec; + static vec peaks (uint32_t len); + + static void order (vec* v); + + operator uint32_t() const { return b; } + + bin operator ++ () { return b++; } + bin operator -- () { return b--; } + bin operator ++ (int) { return ++b; } + bin operator -- (int) { return --b; } + + uint32_t mlat() const { + return 0; + } + + bin left() const { + return bin(b-(mass()>>1)-1); + } + + bin right() const { + return bin(b-1); + } + + bin right_foot() const { + return bin(b-layer()); + } + + bin left_foot() const { + return bin(b-mass()+1); + } + + uint32_t length() const { + //assert(*this<=ALL); + uint32_t apx = (b>>1) + 16; //if (b<=ALL-32) apx = ALL>>1; + uint32_t next = apx-8; + next = apx = lenpeak(next)>=b ? next : apx; + next -= 4; + next = apx = lenpeak(next)>=b ? next : apx; + next -= 2; + next = apx = lenpeak(next)>=b ? next : apx; + next -= 1; + next = apx = lenpeak(next)>=b ? next : apx; + return apx; + } + + uint32_t mass() const { + return layermass(layer()); + } + + uint8_t layer() const { + uint32_t len = length(); + uint8_t topeak = lenpeak(len) - b; + return lenlayer(len) - topeak; + } + + uint32_t width () const { + return 1<>ls) +1; + uint8_t newlr = std::max(0,layer()-ls); + return lenpeak(newlen) - lenlayer(newlen) + newlr; + } + + uint32_t offset () const { + return length() - width(); + } + + bin modulo (uint8_t ls) const { + if (layer()>=ls) + return layermass(ls); + bin blockleft = lenpeak(((length()-1) & ~((1<b-mass(); + } + + bin commonParent (bin other) const { + uint8_t maxlayer = std::max(layer(),other.layer()); + uint32_t myoff = offset()>>maxlayer, othoff = other.offset()>>maxlayer; + uint32_t diff = blackout(myoff^othoff); + uint8_t toshift = bitcount(diff); + return bin(maxlayer+toshift,myoff>>toshift); + } + + bin child (bin dir) const { + return left().contains(dir) ? left() : right(); + } + + bin parent (uint8_t g=1) const { + uint32_t l = length(); + uint8_t h2b = layer()+g; + uint32_t pbit = 1<parent()==b+1; + } + + bool is_left () const { + return !is_right(); + } + + bin sibling () const { + return is_left() ? bin(b+mass()) : bin(b-mass()); + } + + bin scoped (bin top, uint8_t height) const { + assert(layer()<=top.layer()); // TERRIBLE + assert(top.layer()>=height); + uint8_t rel_layer; + if (layer()+height>=top.layer()) + rel_layer = layer()+height-top.layer(); + else + rel_layer = 0;//top.layer() - height; + uint32_t rel_offset = (offset()-top.offset()) >> (top.layer()-height+rel_layer); + return bin(rel_layer,rel_offset); + } + + bin unscoped (bin top, uint8_t height) const { + uint32_t undermass = layermass(top.layer()-height); + uint32_t pad = (1<b) + pad - undermass*pad; + } + +} ; + + +uint8_t bitcount (uint32_t num); + +/*bin l=b>a.b?a.b:b, g=b>a.b?b:a.b; + while (!g.contains(l)) + g = g.parent(); + return g;*/ + +#endif +//20 mln ops per second diff --git a/bin64.h b/bin64.h new file mode 100644 index 0000000..da45678 --- /dev/null +++ b/bin64.h @@ -0,0 +1,98 @@ +#ifndef BIN64_H +#define BIN64_H +#include +#include + +#include + +/** Bin numbers in the tail111 encoding: meaningless + bits in the tail are set to 0111...11, while the + head denotes the offset. Thus, 1101 is the bin + at layer 1, offset 3 (i.e. fourth). */ +struct bin64_t { + uint64_t v; + static const uint64_t NONE = 0xffffffffffffffffULL; + static const uint64_t ALL = 0x7fffffffffffffffULL; + + bin64_t() : v(NONE) {} + bin64_t(const bin64_t&b) : v(b.v) {} + bin64_t(const uint64_t val) : v(val) {} + bin64_t(uint8_t layer, uint64_t offset) : + v( (offset<<(layer+1)) | ((1ULL<>1; + } + + + int layer () const { + int r = 0; + uint64_t tail = ((v^(v+1))+1)>>1; + if (tail>0xffffffffULL) { + r = 32; + tail>>=32; + } + // courtesy of Sean Eron Anderson + // http://graphics.stanford.edu/~seander/bithacks.html + static const int DeBRUIJN[32] = { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + r += DeBRUIJN[((uint32_t)(tail*0x077CB531U))>>27]; + return r; + } + + uint64_t base_offset () const { + return v&~(tail_bits()); + } + + uint64_t offset () const { + return v >> (layer()+1); + } + + bin64_t left () const { + assert(layer()); + return bin64_t( v ^ (tail_bit()>>1) ); + } + + bin64_t right () const { + assert(layer()); + uint64_t tb = tail_bit(); + return bin64_t( v ^ (tb|(tb>>1)) ); + } + + bin64_t parent () const { + uint64_t tbs = tail_bits(), ntbs = (tbs+1)|tbs; + return bin64_t( (v&~ntbs) | tbs ); + } + + bool is_left () const { + uint64_t tb = tail_bit(); + return !(v&(tb<<1)); + } + + /** The array must have 64 cells, as it is the max + number of peaks possible (and there are no reason + to assume there will be less in any given case. */ + static void GetPeaks(uint64_t length, bin64_t* peaks) { + int pp=0; + uint8_t layer = 0; + while (length) { + if (length&1) + peaks[pp++] = bin64_t(layer,length^1); + length>>=1; + layer++; + } + peaks[pp] = NONE; + } + +}; + + +#endif diff --git a/bins.cpp b/bins.cpp new file mode 100644 index 0000000..4dd1e3d --- /dev/null +++ b/bins.cpp @@ -0,0 +1,23 @@ +/* + * sbit.cpp + * serp++ + * + * Created by Victor Grishchenko on 4/1/09. + * Copyright 2009 Delft Technical University. All rights reserved. + * + */ +#include "bins.h" + +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 +} diff --git a/bins.h b/bins.h new file mode 100644 index 0000000..d95406f --- /dev/null +++ b/bins.h @@ -0,0 +1,91 @@ +/* + * sbit.cpp + * serp++ + * + * Created by Victor Grishchenko on 3/28/09. + * Copyright 2009 Delft Technical University. All rights reserved. + * + */ +#ifndef SERP_SBIT_H +#define SERP_SBIT_H +#include "bin64.h" + +class bins64 { + + private: + + 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); + + // TODO: bitwise operators + +}; diff --git a/collisions.cpp b/collisions.cpp new file mode 100644 index 0000000..24c3173 --- /dev/null +++ b/collisions.cpp @@ -0,0 +1,145 @@ +/* + * 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/datagram.cpp b/datagram.cpp new file mode 100644 index 0000000..3c2794a --- /dev/null +++ b/datagram.cpp @@ -0,0 +1,127 @@ +/* + * datagram.cpp + * serp++ + * + * Created by Victor Grishchenko on 3/9/09. + * Copyright 2009 Delft Technical University. All rights reserved. + * + */ +#include +#include +#include "datagram.h" + +namespace p2tp { + +tint Datagram::now = Datagram::Time(); + +int Datagram::Send () { + int r = sendto(sock,buf+offset,length-offset,0, + (struct sockaddr*)&(addr),sizeof(struct sockaddr_in)); + offset=0; + length=0; + now = Time(); + return r; +} + +int Datagram::Recv () { + socklen_t addrlen = sizeof(struct sockaddr_in); + offset = 0; + length = recvfrom (sock, buf, MAXDGRAMSZ, 0, + (struct sockaddr*)&(addr), &addrlen); + if (length<0) + PLOG(ERROR)<<"on recv"; + now = Time(); + return length; +} + + +int Datagram::Wait (int sockcnt, int* sockets, tint usec) { + LOG(INFO)<<"waiting for "<max_sock_fd) + max_sock_fd = sockets[i]; + } + int sel = select(max_sock_fd+1, &bases, NULL, &err, &timeout); + if (sel>0) { + for (int i=0; i<=sockcnt; i++) + if (FD_ISSET(sockets[i],&bases)) + return sockets[i]; + } else if (sel<0) + PLOG(ERROR)<<"select fails"; + return -1; +} + +tint Datagram::Time () { + struct timeval t; + gettimeofday(&t,NULL); + tint ret; + ret = t.tv_sec; + ret *= 1000000; + ret += t.tv_usec; + //DLOG(INFO)<<"now is "< +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include "hashtree.h" + +namespace p2tp { + +typedef int64_t tint; +#define SEC ((tint)1000000) +#define MSEC ((tint)1000) +#define uSEC ((tint)1) +#define NEVER ((tint)0x7fffffffffffffffLL) +#define MAXDGRAMSZ 1400 + +struct Datagram { + struct sockaddr_in addr; + int sock; + int offset, length; + uint8_t buf[MAXDGRAMSZ]; + + static int Bind(int port); + static void Close(int port); + static tint Time(); + static int Wait (int sockcnt, int* sockets, tint usec=0); + static tint now; + + Datagram (int socket, struct sockaddr_in& addr_) : addr(addr_), offset(0), + length(0), sock(socket) {} + Datagram (int socket) : offset(0), length(0), sock(socket) { + memset(&addr,0,sizeof(struct sockaddr_in)); + } + + int space () const { return MAXDGRAMSZ-length; } + int size() const { return length-offset; } + std::string str() const { return std::string((char*)buf+offset,size()); } + + int Push (const uint8_t* data, int l) { // scatter-gather one day + int toc = l>32)); + *(uint32_t*)(buf+length+4) = htonl((uint32_t)(l&0xffffffff)); + length+=8; + } + void PushHash (const Sha1Hash& hash) { + Push(hash.bits, Sha1Hash::SIZE); + } + + uint8_t Pull8() { + if (size()<1) return 0; + return buf[offset++]; + } + uint16_t Pull16() { + if (size()<2) return 0; + offset+=2; + return ntohs(*(uint16_t*)(buf+offset-2)); + } + uint32_t Pull32() { + if (size()<4) return 0; + uint32_t i = ntohl(*(uint32_t*)(buf+offset)); + offset+=4; + return i; + } + uint64_t Pull64() { + if (size()<8) return 0; + uint64_t l = ntohl(*(uint32_t*)(buf+offset)); + l<<=32; + l |= ntohl(*(uint32_t*)(buf+offset+4)); + offset+=8; + return l; + } + Sha1Hash PullHash() { + if (size()