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;
- }
+ 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;
+ 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());
+ 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());
}
#include <deque>
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)<<layer_);
- b -= layer() - layer_;
- }
-
- static void init ();
-
- static uint8_t tailzeros (uint32_t i) {
- uint8_t ret = 0;
- if ( (i&0xffff)==0 )
- ret = 16, i>>=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<<layer)-1;
- }
-
- static uint32_t lastbiton (uint32_t i) {
- return (~i+1)&i;
- }
-
- typedef std::deque<bin> 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<<layer();
- }
-
- bin peak() const {
- return lenpeak(length());
- }
-
- bin divide (uint8_t ls) const {
- uint32_t newlen = ((length()-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<<ls)-1)) + 1);
- return b - blockleft + 1;
- }
-
- bin multiply (uint8_t ls) const {
- return b + length()*(layermass(ls)-1);
- }
-
- bool contains (bin c) const {
- return c.b<=b && c.b>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<<h2b;
- uint32_t l2b = l & ~(pbit-1);
- if (l2b!=l)
- l2b += pbit;
- return lenpeak(l2b) - lenlayer(l2b) + h2b;
- //length()==bin(b+1).length() ? b+1 : b+mass()+1;
- }
-
- bool is_right () const {
- return this->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<<height) - length();
- uint32_t peak = (1<<(height+1))-1;
- return top - (peak-this->b) + pad - undermass*pad;
- }
+ 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)<<layer_);
+ b -= layer() - layer_;
+ }
+
+ static void init ();
+
+ static uint8_t tailzeros (uint32_t i) {
+ uint8_t ret = 0;
+ if ( (i&0xffff)==0 )
+ ret = 16, i>>=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<<layer)-1;
+ }
+
+ static uint32_t lastbiton (uint32_t i) {
+ return (~i+1)&i;
+ }
+
+ typedef std::deque<bin> 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<<layer();
+ }
+
+ bin peak() const {
+ return lenpeak(length());
+ }
+
+ bin divide (uint8_t ls) const {
+ uint32_t newlen = ((length()-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<<ls)-1)) + 1);
+ return b - blockleft + 1;
+ }
+
+ bin multiply (uint8_t ls) const {
+ return b + length()*(layermass(ls)-1);
+ }
+
+ bool contains (bin c) const {
+ return c.b<=b && c.b>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<<h2b;
+ uint32_t l2b = l & ~(pbit-1);
+ if (l2b!=l)
+ l2b += pbit;
+ return lenpeak(l2b) - lenlayer(l2b) + h2b;
+ //length()==bin(b+1).length() ? b+1 : b+mass()+1;
+ }
+
+ bool is_right () const {
+ return this->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<<height) - length();
+ uint32_t peak = (1<<(height+1))-1;
+ return top - (peak-this->b) + pad - undermass*pad;
+ }
} ;
-uint8_t bitcount (uint32_t num);
+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))
// make it work piece by piece
-const uint8_t bins::SPLIT[16] =
+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};
#ifndef _WIN32
return lseek(fd,offset,SEEK_SET);
#else
- return _lseek(fd,offset,SEEK_SET);
+ return _lseek(fd,offset,SEEK_SET);
#endif
}
0,
0,
NULL );
- if (maphandle == NULL)
+ if (maphandle == NULL)
return NULL;
map_handles[fd] = maphandle;
munmap(mapping,size);
close(fd);
#else
- UnmapViewOfFile(mapping);
- CloseHandle(map_handles[fd]);
+ UnmapViewOfFile(mapping);
+ CloseHandle(map_handles[fd]);
#endif
}
tint usec_time(void)
{
- HiResTimeOfDay* tod = HiResTimeOfDay::Instance();
- return tod->getTimeUSec();
+ HiResTimeOfDay* tod = HiResTimeOfDay::Instance();
+ return tod->getTimeUSec();
}
tint usec_time(void)
{
struct timeval t;
- gettimeofday(&t,NULL);
- tint ret;
- ret = t.tv_sec;
- ret *= 1000000;
- ret += t.tv_usec;
- return ret;
+ gettimeofday(&t,NULL);
+ tint ret;
+ ret = t.tv_sec;
+ ret *= 1000000;
+ ret += t.tv_usec;
+ return ret;
}
#endif
#include <stdlib.h>
#ifdef _WIN32
-#define open(a,b,c) _open(a,b,c)
+#define open(a,b,c) _open(a,b,c)
#define S_IRUSR _S_IREAD
-#define S_IWUSR _S_IWRITE
+#define S_IWUSR _S_IWRITE
#define S_IRGRP _S_IREAD
#define S_IROTH _S_IREAD
#endif
void Address::set_ipv4 (const char* ip_str) {
struct hostent *h = gethostbyname(ip_str);
if (h == NULL) {
- print_error("cannot lookup address");
- return;
+ print_error("cannot lookup address");
+ return;
} else {
addr.sin_addr.s_addr = *(u_long *) h->h_addr_list[0];
}
int Datagram::Send () {
- int r = sendto(sock,(const char *)buf+offset,length-offset,0,
- (struct sockaddr*)&(addr.addr),sizeof(struct sockaddr_in));
+ int r = sendto(sock,(const char *)buf+offset,length-offset,0,
+ (struct sockaddr*)&(addr.addr),sizeof(struct sockaddr_in));
if (r<0)
perror("can't send");
- //offset=0;
- //length=0;
+ //offset=0;
+ //length=0;
dgrams_up++;
bytes_up+=size();
- Time();
- return r;
+ Time();
+ return r;
}
int Datagram::Recv () {
- socklen_t addrlen = sizeof(struct sockaddr_in);
- offset = 0;
- length = recvfrom (sock, (char *)buf, MAXDGRAMSZ, 0,
- (struct sockaddr*)&(addr.addr), &addrlen);
- if (length<0) {
+ socklen_t addrlen = sizeof(struct sockaddr_in);
+ offset = 0;
+ length = recvfrom (sock, (char *)buf, MAXDGRAMSZ, 0,
+ (struct sockaddr*)&(addr.addr), &addrlen);
+ if (length<0) {
length = 0;
print_error("error on recv");
}
dgrams_down++;
bytes_down+=length;
- Time();
- return length;
+ Time();
+ return length;
}
SOCKET Datagram::Wait (int sockcnt, SOCKET* sockets, tint usec) {
- struct timeval timeout;
- timeout.tv_sec = usec/TINT_SEC;
- timeout.tv_usec = usec%TINT_SEC;
- int max_sock_fd = 0;
- fd_set bases, err;
- FD_ZERO(&bases);
- FD_ZERO(&err);
- for(int i=0; i<sockcnt; i++) {
- FD_SET(sockets[i],&bases);
- FD_SET(sockets[i],&err);
- if (sockets[i]>max_sock_fd)
- max_sock_fd = sockets[i];
- }
- int sel = select(max_sock_fd+1, &bases, NULL, &err, &timeout);
+ struct timeval timeout;
+ timeout.tv_sec = usec/TINT_SEC;
+ timeout.tv_usec = usec%TINT_SEC;
+ int max_sock_fd = 0;
+ fd_set bases, err;
+ FD_ZERO(&bases);
+ FD_ZERO(&err);
+ for(int i=0; i<sockcnt; i++) {
+ FD_SET(sockets[i],&bases);
+ FD_SET(sockets[i],&err);
+ if (sockets[i]>max_sock_fd)
+ max_sock_fd = sockets[i];
+ }
+ int sel = select(max_sock_fd+1, &bases, NULL, &err, &timeout);
Time();
- if (sel>0) {
- for (int i=0; i<=sockcnt; i++)
- if (FD_ISSET(sockets[i],&bases))
- return sockets[i];
- } else if (sel<0) {
- print_error("select fails");
+ if (sel>0) {
+ for (int i=0; i<=sockcnt; i++)
+ if (FD_ISSET(sockets[i],&bases))
+ return sockets[i];
+ } else if (sel<0) {
+ print_error("select fails");
}
return INVALID_SOCKET;
}
tint Datagram::Time () {
- //HiResTimeOfDay* tod = HiResTimeOfDay::Instance();
- //tint ret = tod->getTimeUSec();
- //DLOG(INFO)<<"now is "<<ret;
- return now = usec_time();
+ //HiResTimeOfDay* tod = HiResTimeOfDay::Instance();
+ //tint ret = tod->getTimeUSec();
+ //DLOG(INFO)<<"now is "<<ret;
+ return now = usec_time();
}
SOCKET Datagram::Bind (Address addr_) {
struct sockaddr_in addr = addr_;
- SOCKET fd;
- int len = sizeof(struct sockaddr_in), sndbuf=1<<20, rcvbuf=1<<20;
- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- print_error("socket() fails");
+ SOCKET fd;
+ int len = sizeof(struct sockaddr_in), sndbuf=1<<20, rcvbuf=1<<20;
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ print_error("socket() fails");
return INVALID_SOCKET;
}
#ifdef _WIN32
- u_long enable = 1;
- ioctlsocket(fd, FIONBIO, &enable);
- if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char *)&sndbuf, sizeof(int)) != 0 ) {
+ u_long enable = 1;
+ ioctlsocket(fd, FIONBIO, &enable);
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char *)&sndbuf, sizeof(int)) != 0 ) {
print_error("setsockopt fails");
return INVALID_SOCKET;
}
- if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char *)&rcvbuf, sizeof(int)) != 0 ) {
+ if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char *)&rcvbuf, sizeof(int)) != 0 ) {
print_error("setsockopt2 fails");
return INVALID_SOCKET;
}
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&enable, sizeof(int));
#else
int enable=1;
- if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
- return INVALID_SOCKET;
- if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(int)) < 0 ) {
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
+ return INVALID_SOCKET;
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(int)) < 0 ) {
print_error("setsockopt fails");
return INVALID_SOCKET;
}
- if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(int)) < 0 ) {
+ if ( setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(int)) < 0 ) {
print_error("setsockopt2 fails");
return INVALID_SOCKET;
}
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
#endif
dprintf("socket buffers: %i send %i recv\n",sndbuf,rcvbuf);
- if (::bind(fd, (sockaddr*)&addr, len) != 0) {
+ if (::bind(fd, (sockaddr*)&addr, len) != 0) {
print_error("bind fails");
return INVALID_SOCKET;
}
- return fd;
+ return fd;
}
void Datagram::Close (int sock) { // remove from fd_set
#ifdef _WIN32
- if (closesocket(sock)!=0)
+ if (closesocket(sock)!=0)
#else
- if (::close(sock)!=0)
+ if (::close(sock)!=0)
#endif
- print_error("on closing a socket");
+ print_error("on closing a socket");
}
std::string sock2str (struct sockaddr_in addr) {
- char ipch[32];
+ char ipch[32];
#ifdef _WIN32
- //Vista only: InetNtop(AF_INET,&(addr.sin_addr),ipch,32);
- // IPv4 only:
- struct in_addr inaddr;
- memcpy(&inaddr, &(addr.sin_addr), sizeof(inaddr));
- strncpy(ipch, inet_ntoa(inaddr),32);
+ //Vista only: InetNtop(AF_INET,&(addr.sin_addr),ipch,32);
+ // IPv4 only:
+ struct in_addr inaddr;
+ memcpy(&inaddr, &(addr.sin_addr), sizeof(inaddr));
+ strncpy(ipch, inet_ntoa(inaddr),32);
#else
- inet_ntop(AF_INET,&(addr.sin_addr),ipch,32);
+ inet_ntop(AF_INET,&(addr.sin_addr),ipch,32);
#endif
- sprintf(ipch+strlen(ipch),":%i",ntohs(addr.sin_port));
- return std::string(ipch);
+ sprintf(ipch+strlen(ipch),":%i",ntohs(addr.sin_port));
+ return std::string(ipch);
}
/*
std::string Datagram::to_string () const { // TODO: pretty-print P2TP
- std::string addrs = sock2str(addr);
- char hex[MAXDGRAMSZ*2];
- for(int i=offset; i<length; i++)
- sprintf(hex+i*2,"%02x",buf[i]);
- std::string hexs(hex+offset*2,(length-offset)*2);
- return addrs + '\t' + hexs;
+ std::string addrs = sock2str(addr);
+ char hex[MAXDGRAMSZ*2];
+ for(int i=offset; i<length; i++)
+ sprintf(hex+i*2,"%02x",buf[i]);
+ std::string hexs(hex+offset*2,(length-offset)*2);
+ return addrs + '\t' + hexs;
}*/
}
#include <stdint.h>
#endif
#ifdef _WIN32
- #include <winsock2.h>
- #include "compat.h"
+ #include <winsock2.h>
+ #include "compat.h"
#else
typedef int SOCKET;
struct Datagram {
- Address addr;
- SOCKET sock;
- int offset, length;
- uint8_t buf[MAXDGRAMSZ*2];
+ Address addr;
+ SOCKET sock;
+ int offset, length;
+ uint8_t buf[MAXDGRAMSZ*2];
- static SOCKET Bind(Address address);
- static void Close(int port);
- static tint Time();
- static SOCKET Wait (int sockcnt, SOCKET* sockets, tint usec=0);
- static tint now, epoch, start;
+ static SOCKET Bind(Address address);
+ static void Close(int port);
+ static tint Time();
+ static SOCKET Wait (int sockcnt, SOCKET* sockets, tint usec=0);
+ static tint now, epoch, start;
static uint64_t dgrams_up, dgrams_down, bytes_up, bytes_down;
- Datagram (SOCKET socket, const Address addr_) : addr(addr_), offset(0),
- length(0), sock(socket) {}
- Datagram (SOCKET socket) : offset(0), length(0), sock(socket) {
- }
+ Datagram (SOCKET socket, const Address addr_) : addr(addr_), offset(0),
+ length(0), sock(socket) {}
+ Datagram (SOCKET socket) : offset(0), length(0), sock(socket) {
+ }
- int space () const { return MAXDGRAMSZ-length; }
- int size() const { return length-offset; }
- std::string str() const { return std::string((char*)buf+offset,size()); }
+ int space () const { return MAXDGRAMSZ-length; }
+ int size() const { return length-offset; }
+ std::string str() const { return std::string((char*)buf+offset,size()); }
const uint8_t* operator * () const { return buf+offset; }
- int Push (const uint8_t* data, int l) { // scatter-gather one day
- int toc = l<space() ? l : space();
- memcpy(buf+length,data,toc);
- length += toc;
- return toc;
- }
- int Pull (uint8_t** data, int l) {
- int toc = l<size() ? l : size();
- //memcpy(data,buf+offset,toc);
- *data = buf+offset;
- offset += toc;
- return toc;
- }
-
- int Send ();
- int Recv ();
- const Address& address() const { return addr; }
+ int Push (const uint8_t* data, int l) { // scatter-gather one day
+ int toc = l<space() ? l : space();
+ memcpy(buf+length,data,toc);
+ length += toc;
+ return toc;
+ }
+ int Pull (uint8_t** data, int l) {
+ int toc = l<size() ? l : size();
+ //memcpy(data,buf+offset,toc);
+ *data = buf+offset;
+ offset += toc;
+ return toc;
+ }
+
+ int Send ();
+ int Recv ();
+ const Address& address() const { return addr; }
void Clear() { offset=length=0; }
- void PushString (std::string str) {
- Push((uint8_t*)str.c_str(),str.size());
- }
- void Push8 (uint8_t b) {
- buf[length++] = b;
- }
- void Push16 (uint16_t w) {
- *(uint16_t*)(buf+length) = htons(w);
- length+=2;
- }
- void Push32 (uint32_t i) {
- *(uint32_t*)(buf+length) = htonl(i);
- length+=4;
- }
- void Push64 (uint64_t l) {
- *(uint32_t*)(buf+length) = htonl((uint32_t)(l>>32));
- *(uint32_t*)(buf+length+4) = htonl((uint32_t)(l&0xffffffff));
- length+=8;
- }
- void PushHash (const Sha1Hash& hash) {
- Push((uint8_t*)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()<Sha1Hash::SIZE) return Sha1Hash::ZERO;
- offset += Sha1Hash::SIZE;
- return Sha1Hash(false,(char*)buf+offset-Sha1Hash::SIZE);
- }
- //std::string to_string () const ;
+ void PushString (std::string str) {
+ Push((uint8_t*)str.c_str(),str.size());
+ }
+ void Push8 (uint8_t b) {
+ buf[length++] = b;
+ }
+ void Push16 (uint16_t w) {
+ *(uint16_t*)(buf+length) = htons(w);
+ length+=2;
+ }
+ void Push32 (uint32_t i) {
+ *(uint32_t*)(buf+length) = htonl(i);
+ length+=4;
+ }
+ void Push64 (uint64_t l) {
+ *(uint32_t*)(buf+length) = htonl((uint32_t)(l>>32));
+ *(uint32_t*)(buf+length+4) = htonl((uint32_t)(l&0xffffffff));
+ length+=8;
+ }
+ void PushHash (const Sha1Hash& hash) {
+ Push((uint8_t*)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()<Sha1Hash::SIZE) return Sha1Hash::ZERO;
+ offset += Sha1Hash::SIZE;
+ return Sha1Hash(false,(char*)buf+offset-Sha1Hash::SIZE);
+ }
+ //std::string to_string () const ;
};
#include "compat.h"
#ifdef _WIN32
-#define OPENFLAGS O_RDWR|O_CREAT|_O_BINARY
+#define OPENFLAGS O_RDWR|O_CREAT|_O_BINARY
#else
-#define OPENFLAGS O_RDWR|O_CREAT
+#define OPENFLAGS O_RDWR|O_CREAT
#endif
}
Sha1Hash::Sha1Hash(const Sha1Hash& left, const Sha1Hash& right) {
- char data[HASHSZ*2];
- memcpy(data,left.bits,SIZE);
- memcpy(data+SIZE,right.bits,SIZE);
- SHA1((unsigned char*)data,SIZE*2,bits);
+ char data[HASHSZ*2];
+ memcpy(data,left.bits,SIZE);
+ memcpy(data+SIZE,right.bits,SIZE);
+ SHA1((unsigned char*)data,SIZE*2,bits);
}
Sha1Hash::Sha1Hash(const char* data, size_t length) {
if (length==-1)
length = strlen(data);
- SHA1((unsigned char*)data,length,bits);
+ SHA1((unsigned char*)data,length,bits);
}
Sha1Hash::Sha1Hash(const uint8_t* data, size_t length) {
- SHA1(data,length,bits);
+ SHA1(data,length,bits);
}
Sha1Hash::Sha1Hash(bool hex, const char* hash) {
- if (hex) {
+ if (hex) {
char hx[3]; hx[2]=0;
int val;
for(int i=0; i<SIZE; i++) {
memcpy(bits,hash,SIZE);
}
-std::string Sha1Hash::hex() const {
- char hex[HASHSZ*2+1];
- for(int i=0; i<HASHSZ; i++)
- sprintf(hex+i*2, "%02x", (int)(unsigned char)bits[i]);
- return std::string(hex,HASHSZ*2);
+std::string Sha1Hash::hex() const {
+ char hex[HASHSZ*2+1];
+ for(int i=0; i<HASHSZ; i++)
+ sprintf(hex+i*2, "%02x", (int)(unsigned char)bits[i]);
+ return std::string(hex,HASHSZ*2);
}
peak_count_(0), hashes_(NULL), size_(0), sizek_(0),
complete_(0), completek_(0)
{
- fd_ = open(filename,OPENFLAGS,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
- if (fd_<0) {
+ fd_ = open(filename,OPENFLAGS,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (fd_<0) {
fd_ = 0;
print_error("cannot open the file");
return;
void HashTree::Submit () {
size_ = file_size(fd_);
- sizek_ = (size_ + 1023) >> 10;
+ sizek_ = (size_ + 1023) >> 10;
peak_count_ = bin64_t::peaks(sizek_,peaks_);
int hashes_size = Sha1Hash::SIZE*sizek_*2;
file_resize(hash_fd_,hashes_size);
for some optimizations. */
void HashTree::RecoverProgress () {
size_t size = file_size(fd_);
- size_t sizek = (size + 1023) >> 10;
+ size_t sizek = (size + 1023) >> 10;
bin64_t peaks[64];
int peak_count = bin64_t::peaks(sizek,peaks);
for(int i=0; i<peak_count; i++) {
size_ = sizek_<<10;
completek_ = complete_ = 0;
- sizek_ = (size_ + 1023) >> 10;
+ sizek_ = (size_ + 1023) >> 10;
size_t cur_size = file_size(fd_);
if ( cur_size<=(sizek_-1)<<10 || cur_size>sizek_<<10 )
Sha1Hash HashTree::DeriveRoot () {
- int c = peak_count_-1;
- bin64_t p = peaks_[c];
- Sha1Hash hash = peak_hashes_[c];
- c--;
- while (p!=bin64_t::ALL) {
- if (p.is_left()) {
- p = p.parent();
- hash = Sha1Hash(hash,Sha1Hash::ZERO);
- } else {
- if (c<0 || peaks_[c]!=p.sibling())
- return Sha1Hash::ZERO;
- hash = Sha1Hash(peak_hashes_[c],hash);
- p = p.parent();
- c--;
- }
+ int c = peak_count_-1;
+ bin64_t p = peaks_[c];
+ Sha1Hash hash = peak_hashes_[c];
+ c--;
+ while (p!=bin64_t::ALL) {
+ if (p.is_left()) {
+ p = p.parent();
+ hash = Sha1Hash(hash,Sha1Hash::ZERO);
+ } else {
+ if (c<0 || peaks_[c]!=p.sibling())
+ return Sha1Hash::ZERO;
+ hash = Sha1Hash(peak_hashes_[c],hash);
+ p = p.parent();
+ c--;
+ }
//dprintf("p %lli %s\n",(uint64_t)p,hash.hex().c_str());
- }
+ }
return hash;
}
bool HashTree::OfferHash (bin64_t pos, const Sha1Hash& hash) {
- if (!size_) // only peak hashes are accepted at this point
- return OfferPeakHash(pos,hash);
+ if (!size_) // only peak hashes are accepted at this point
+ return OfferPeakHash(pos,hash);
bin64_t peak = peak_for(pos);
if (peak==bin64_t::NONE)
return false;
return hash == hashes_[pos];
if (ack_out_.get(pos.parent())!=bins::EMPTY)
return hash==hashes_[pos]; // have this hash already, even accptd data
- hashes_[pos] = hash;
+ hashes_[pos] = hash;
if (!pos.is_base())
return false; // who cares?
bin64_t p = pos;
struct Sha1Hash {
- uint8_t bits[20];
+ uint8_t bits[20];
- Sha1Hash() { memset(bits,0,20); }
- Sha1Hash(const Sha1Hash& left, const Sha1Hash& right);
- Sha1Hash(const char* str, size_t length=-1);
- Sha1Hash(const uint8_t* data, size_t length);
- Sha1Hash(bool hex, const char* hash);
-
- std::string hex() const;
- bool operator == (const Sha1Hash& b) const
- { return 0==memcmp(bits,b.bits,SIZE); }
- bool operator != (const Sha1Hash& b) const { return !(*this==b); }
+ Sha1Hash() { memset(bits,0,20); }
+ Sha1Hash(const Sha1Hash& left, const Sha1Hash& right);
+ Sha1Hash(const char* str, size_t length=-1);
+ Sha1Hash(const uint8_t* data, size_t length);
+ Sha1Hash(bool hex, const char* hash);
+
+ std::string hex() const;
+ bool operator == (const Sha1Hash& b) const
+ { return 0==memcmp(bits,b.bits,SIZE); }
+ bool operator != (const Sha1Hash& b) const { return !(*this==b); }
const char* operator * () const { return (char*) bits; }
-
- const static Sha1Hash ZERO;
- const static size_t SIZE;
+
+ const static Sha1Hash ZERO;
+ const static size_t SIZE;
};
class HashTree {
/** Merkle hash tree: root */
- Sha1Hash root_hash_;
+ Sha1Hash root_hash_;
Sha1Hash *hashes_;
/** Merkle hash tree: peak hashes */
Sha1Hash peak_hashes_[64];
bin64_t peaks_[64];
int peak_count_;
/** File descriptor to put hashes to */
- int fd_;
+ int fd_;
int hash_fd_;
/** Whether to re-hash files. */
bool data_recheck_;
/** Base size, as derived from the hashes. */
size_t size_;
size_t sizek_;
- /** Part of the tree currently checked. */
+ /** Part of the tree currently checked. */
size_t complete_;
size_t completek_;
bins ack_out_;
bool OfferPeakHash (bin64_t pos, const Sha1Hash& hash);
public:
-
- HashTree (const char* file_name, const Sha1Hash& root=Sha1Hash::ZERO,
+
+ HashTree (const char* file_name, const Sha1Hash& root=Sha1Hash::ZERO,
const char* hash_filename=NULL);
/** Offer a hash; returns true if it verified; false otherwise.
bool is_complete ()
{ return size_ && complete_==size_; }
bins& ack_out () { return ack_out_; }
-
- ~HashTree ();
+
+ ~HashTree ();
-
+
};
}
#include "ext/simple_selector.cpp"
PeerSelector* Channel::peer_selector = new SimpleSelector();
-Channel::Channel (FileTransfer* transfer, int socket, Address peer_addr) :
- transfer_(transfer), peer_(peer_addr), peer_channel_id_(0), pex_out_(0),
+Channel::Channel (FileTransfer* transfer, int socket, Address peer_addr) :
+ transfer_(transfer), peer_(peer_addr), peer_channel_id_(0), pex_out_(0),
socket_(socket==-1?sockets[0]:socket), // FIXME
data_out_cap_(bin64_t::ALL), last_send_data_time_(0), last_recv_data_time_(0),
own_id_mentioned_(false), next_send_time_(0), last_send_time_(0),
{
if (peer_==Address())
peer_ = tracker;
- this->id = channels.size();
- channels.push_back(this);
+ this->id = channels.size();
+ channels.push_back(this);
cc_ = new PingPongController(this);
dprintf("%s #%i init %s\n",tintstr(),id,peer_.str());
Schedule(NOW); // FIXME ugly
Channel::~Channel () {
- channels[id] = NULL;
+ channels[id] = NULL;
delete cc_;
}
int Channel::DecodeID(int scrambled) {
- return scrambled ^ (int)Datagram::start;
+ return scrambled ^ (int)Datagram::start;
}
int Channel::EncodeID(int unscrambled) {
- return unscrambled ^ (int)Datagram::start;
+ return unscrambled ^ (int)Datagram::start;
}
}
-void p2tp::Close (int fd) {
+void p2tp::Close (int fd) {
// FIXME delete all channels
if (fd>FileTransfer::files.size() && FileTransfer::files[fd])
delete FileTransfer::files[fd];
}
-/** <h2> P2TP handshake </h2>
+/** <h2> P2TP handshake </h2>
Basic rules:
<ul>
- <li> to send a datagram, a channel must be created
+ <li> to send a datagram, a channel must be created
(channels are cheap and easily recycled)
- <li> a datagram must contain either the receiving
+ <li> a datagram must contain either the receiving
channel id (scrambled) or the root hash
- <li> initially, the control structure (p2tp_channel)
+ <li> initially, the control structure (p2tp_channel)
is mostly zeroed; intialization happens as
conversation progresses
</ul>
Messages
- HANDSHAKE 00, channelid
+ HANDSHAKE 00, channelid
Communicates the channel id of the sender. The
initial handshake packet also has the root hash
(a HASH message).
- DATA 01, bin_32, buffer
+ DATA 01, bin_32, buffer
1K of data.
- ACK 02, bin_32
+ ACK 02, bin_32
ACKTS 08, bin_32, timestamp_32
Confirms successfull delivery of data. Used for
congestion control, as well.
- HINT 03, bin_32
+ 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.
As peers cant pick randomly kilobyte here and there,
they send out "long hints" for non-base bins.
- HASH 04, bin_32, 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, ipv4 addr, 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).
{ return !(*this==b); }
};
- typedef std::deque<tintbin> tbqueue;
+ typedef std::deque<tintbin> tbqueue;
typedef std::deque<bin64_t> binqueue;
typedef Address Address;
}
};
- typedef enum {
- P2TP_HANDSHAKE = 0,
- P2TP_DATA = 1,
- P2TP_ACK = 2,
- P2TP_TS = 8,
- P2TP_HINT = 3,
- P2TP_HASH = 4,
- P2TP_PEX_ADD = 5,
- P2TP_PEX_RM = 6,
- P2TP_MESSAGE_COUNT = 7
- } messageid_t;
+ typedef enum {
+ P2TP_HANDSHAKE = 0,
+ P2TP_DATA = 1,
+ P2TP_ACK = 2,
+ P2TP_TS = 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;
- class FileTransfer {
+ class FileTransfer {
public:
- /** Open/submit/retrieve a file. */
+ /** Open/submit/retrieve a file. */
FileTransfer(const char *file_name, const Sha1Hash& _root_hash=Sha1Hash::ZERO);
- /** Close everything. */
- ~FileTransfer();
+ /** Close everything. */
+ ~FileTransfer();
/** While we need to feed ACKs to every peer, we try (1) avoid
int RevealChannel (int& i);
static FileTransfer* Find (const Sha1Hash& hash);
- static FileTransfer* file (int fd) {
+ static FileTransfer* file (int fd) {
return fd<files.size() ? files[fd] : NULL;
}
private:
- static std::vector<FileTransfer*> files;
+ static std::vector<FileTransfer*> files;
HashTree file_;
void OnDataIn (bin64_t pos);
void OnPexIn (const Address& addr);
- friend class Channel;
+ friend class Channel;
friend uint64_t Size (int fdes);
friend bool IsComplete (int fdes);
friend uint64_t Complete (int fdes);
friend uint64_t SeqComplete (int fdes);
friend int Open (const char* filename, const Sha1Hash& hash) ;
friend void Close (int fd) ;
- };
+ };
#include "ext/send_control.h"
};
- /** P2TP channel's "control block"; channels loosely correspond to TCP
+ /** P2TP channel's "control block"; channels loosely correspond to TCP
connections or FTP sessions; one channel is created for one file
being transferred between two peers. As we don't need buffers and
lots of other TCP stuff, sizeof(Channel+members) must be below 1K.
(There was a seductive idea to remove channels, just put the root
hash or a fragment of it into every datagram.) */
- struct Channel { // normally, API users do not deal with the structure
+ struct Channel { // normally, API users do not deal with the structure
- Channel (FileTransfer* file, int socket=-1, Address peer=Address());
- ~Channel();
+ Channel (FileTransfer* file, int socket=-1, Address peer=Address());
+ ~Channel();
- static void RecvDatagram (int socket);
+ static void RecvDatagram (int socket);
static void Loop (tint till);
- void Recv (Datagram& dgram);
- void Send ();
-
- void OnAck (Datagram& dgram);
- void OnTs (Datagram& dgram);
- bin64_t OnData (Datagram& dgram);
- void OnHint (Datagram& dgram);
- void OnHash (Datagram& dgram);
- void OnPex (Datagram& dgram);
- void OnHandshake (Datagram& dgram);
- void AddHandshake (Datagram& dgram);
- bin64_t AddData (Datagram& dgram);
- void AddAck (Datagram& dgram);
- void AddTs (Datagram& dgram);
- void AddHint (Datagram& dgram);
- void AddUncleHashes (Datagram& dgram, bin64_t pos);
- void AddPeakHashes (Datagram& dgram);
- void AddPex (Datagram& dgram);
+ void Recv (Datagram& dgram);
+ void Send ();
+
+ void OnAck (Datagram& dgram);
+ void OnTs (Datagram& dgram);
+ bin64_t OnData (Datagram& dgram);
+ void OnHint (Datagram& dgram);
+ void OnHash (Datagram& dgram);
+ void OnPex (Datagram& dgram);
+ void OnHandshake (Datagram& dgram);
+ void AddHandshake (Datagram& dgram);
+ bin64_t AddData (Datagram& dgram);
+ void AddAck (Datagram& dgram);
+ void AddTs (Datagram& dgram);
+ void AddHint (Datagram& dgram);
+ void AddUncleHashes (Datagram& dgram, bin64_t pos);
+ void AddPeakHashes (Datagram& dgram);
+ void AddPex (Datagram& dgram);
const std::string id_string () const;
/** A channel is "established" if had already sent and received packets. */
HashTree& file () { return transfer_->file(); }
const Address& peer() const { return peer_; }
- static int DecodeID(int scrambled);
- static int EncodeID(int unscrambled);
- static Channel* channel(int i) {
+ static int DecodeID(int scrambled);
+ static int EncodeID(int unscrambled);
+ static Channel* channel(int i) {
return i<channels.size()?channels[i]:NULL;
}
- /** Channel id: index in the channel array. */
- uint32_t id;
- /** Socket address of the peer. */
- Address peer_;
- /** The UDP socket fd. */
- int socket_;
- /** Descriptor of the file in question. */
- FileTransfer* transfer_;
- /** Peer channel id; zero if we are trying to open a channel. */
- uint32_t peer_channel_id_;
+ /** Channel id: index in the channel array. */
+ uint32_t id;
+ /** Socket address of the peer. */
+ Address peer_;
+ /** The UDP socket fd. */
+ int socket_;
+ /** Descriptor of the file in question. */
+ FileTransfer* transfer_;
+ /** Peer channel id; zero if we are trying to open a channel. */
+ uint32_t peer_channel_id_;
bool own_id_mentioned_;
- /** Peer's progress, based on acknowledgements. */
- bins ack_in_;
- /** Last data received; needs to be acked immediately. */
- tintbin data_in_;
+ /** Peer's progress, based on acknowledgements. */
+ bins ack_in_;
+ /** Last data received; needs to be acked immediately. */
+ tintbin data_in_;
bin64_t data_in_dbl_;
/** The history of data sent and still unacknowledged. */
tbqueue data_out_;
bin64_t data_out_cap_;
/** Index in the history array. */
- bins ack_out_;
- /** Transmit schedule: in most cases filled with the peer's hints */
- tbqueue hint_in_;
- /** Hints sent (to detect and reschedule ignored hints). */
+ bins ack_out_;
+ /** Transmit schedule: in most cases filled with the peer's hints */
+ tbqueue hint_in_;
+ /** Hints sent (to detect and reschedule ignored hints). */
tbqueue hint_out_;
uint64_t hint_out_size_;
- /** The congestion control strategy. */
- SendController *cc_;
+ /** The congestion control strategy. */
+ SendController *cc_;
/** Types of messages the peer accepts. */
uint64_t cap_in_;
/** For repeats. */
- //tint last_send_time, last_recv_time;
+ //tint last_send_time, last_recv_time;
/** PEX progress */
int pex_out_;
/** Smoothed averages for RTT, RTT deviation and data interarrival periods. */
return TINT_SEC / dip_avg_ * 1024;
}
/** Get a request for one packet from the queue of peer's requests. */
- bin64_t DequeueHint();
+ bin64_t DequeueHint();
void CleanDataOut (bin64_t acks_pos=bin64_t::NONE);
void CleanStaleHintOut();
void CleanHintOut(bin64_t pos);
static PeerSelector* peer_selector;
- static int MAX_REORDERING;
- static tint TIMEOUT;
+ static int MAX_REORDERING;
+ static tint TIMEOUT;
static SOCKET sockets[8];
static int socket_count;
- static tint last_tick;
+ static tint last_tick;
static Address tracker;
- static std::vector<Channel*> channels;
+ static std::vector<Channel*> channels;
friend int Listen (Address addr);
friend void Shutdown (int sock_des);
friend class FileTransfer; // FIXME!!!
friend class SendController; // FIXME!!!
- };
+ };
/** Get the root hash for the transmission. */
const Sha1Hash& RootMerkleHash (int file) ;
/** Close a file and a transmission. */
- void Close (int fd) ;
+ void Close (int fd) ;
/** Add a possible peer which participares in a given transmission. In the case
root hash is zero, the peer might be talked to regarding any transmission
(likely, a tracker, cache or an archive). */
uint64_t SeqComplete (int fdes);
- //uint32_t Width (const tbinvec& v);
+ //uint32_t Width (const tbinvec& v);
- /** Must be called by any client using the library */
- void LibraryInit(void);
+ /** Must be called by any client using the library */
+ void LibraryInit(void);
} // namespace end
*/
-char* Rarest1st::on_event (P2Channel& ch) {
- if (!ch.peer_has)
- return "nothing is known - cannot choose";
- feye i_need (ch.file->have,ch.peer_has->focus);
- i_need.invert();
- i_need &= ch.peer_has;
- if (i_need.clean())
- return "the peer has nothing we don't have";
- feye ladder[20];
- for(int i=P2TP_CHANNELS.begin(); i!=P2TP_CHANNELS.end(); i++) {
- p2tp_channel* c = *i;
- if (!c || !c->peer_has)
- continue;
- feye x = feye_and(c->peer_has,i_need);
- for(int j=0; j<20 && !x.clean(); j++) {
- feye xx(x);
- x &= ladder[j];
- ladder[j] ^= xx;
- }
- }
- feye not_rare (ch.peer_has->focus);
- for(int i=20-1; i>0; i--) {
- not_rare |= ladder[i];
- ladder[i-1] -= not_rare;
- }
- int pickfrom = 0;
- while (ladder[pickfrom].clean() && pickfrom<20)
- pickfrom++;
- assert(pickfrom<20);
- mlat spot = ladder[pickfrom].randomBit();
- ch->i_ackd.refocus(spot);
- return NULL;
+char* Rarest1st::on_event (P2Channel& ch) {
+ if (!ch.peer_has)
+ return "nothing is known - cannot choose";
+ feye i_need (ch.file->have,ch.peer_has->focus);
+ i_need.invert();
+ i_need &= ch.peer_has;
+ if (i_need.clean())
+ return "the peer has nothing we don't have";
+ feye ladder[20];
+ for(int i=P2TP_CHANNELS.begin(); i!=P2TP_CHANNELS.end(); i++) {
+ p2tp_channel* c = *i;
+ if (!c || !c->peer_has)
+ continue;
+ feye x = feye_and(c->peer_has,i_need);
+ for(int j=0; j<20 && !x.clean(); j++) {
+ feye xx(x);
+ x &= ladder[j];
+ ladder[j] ^= xx;
+ }
+ }
+ feye not_rare (ch.peer_has->focus);
+ for(int i=20-1; i>0; i--) {
+ not_rare |= ladder[i];
+ ladder[i-1] -= not_rare;
+ }
+ int pickfrom = 0;
+ while (ladder[pickfrom].clean() && pickfrom<20)
+ pickfrom++;
+ assert(pickfrom<20);
+ mlat spot = ladder[pickfrom].randomBit();
+ ch->i_ackd.refocus(spot);
+ return NULL;
}
*/
#include "sbit.h"
-uint16_t bins::SPLIT[256];
-uint8_t bins::JOIN[256];
-uint16_t bins::OFFMASK[32];
+uint16_t bins::SPLIT[256];
+uint8_t bins::JOIN[256];
+uint16_t bins::OFFMASK[32];
static uint16_t NO_PARENT = 0xffff;
bins::bins () : peak(31), bits(32,0), deep(32,false), prnt(16,NO_PARENT),
- allocp(1), rescan_flag(true) {
- prnt[0] = 0;
- deep[1] = true;
+ allocp(1), rescan_flag(true) {
+ prnt[0] = 0;
+ deep[1] = true;
}
bins::bins(const bins& b) : peak(b.peak), allocp(b.allocp),
- bits(b.bits), prnt(b.prnt), deep(b.deep), rescan_flag(b.rescan_flag)
+ bits(b.bits), prnt(b.prnt), deep(b.deep), rescan_flag(b.rescan_flag)
{
}
-void bins::init () {
- for(int i=0; i<256; i++)
- JOIN[i] = 0xff;
- for(int i=0; i<256; i++) {
- int split = 0;
- for(int b=0; b<8; b++)
- if (i&(1<<b))
- split |= (1<<(2*b)) | (1<<(2*b+1));
- SPLIT[i] = split;
- JOIN[split&0xff] = i&0xf;
- }
- for(bin i=0; i<32; i++) {
- int m = 0;
- for(int j=i.offset(); j<i.length(); j++)
- m |= 1<<j;
- OFFMASK[i] = m;
- }
+void bins::init () {
+ for(int i=0; i<256; i++)
+ JOIN[i] = 0xff;
+ for(int i=0; i<256; i++) {
+ int split = 0;
+ for(int b=0; b<8; b++)
+ if (i&(1<<b))
+ split |= (1<<(2*b)) | (1<<(2*b+1));
+ SPLIT[i] = split;
+ JOIN[split&0xff] = i&0xf;
+ }
+ for(bin i=0; i<32; i++) {
+ int m = 0;
+ for(int j=i.offset(); j<i.length(); j++)
+ m |= 1<<j;
+ OFFMASK[i] = m;
+ }
}
-void bins::unlink (int half) {
- int s[32], sp=0;
- s[sp++] = half;
- while (sp) {
- int h = s[--sp];
- if (deep[h]) {
- int c=bits[h], l=c<<1, r=l+1;
- prnt[c] = NO_PARENT;
- deep[h]=false;
- s[sp++] = l;
- s[sp++] = r;
- }
- }
+void bins::unlink (int half) {
+ int s[32], sp=0;
+ s[sp++] = half;
+ while (sp) {
+ int h = s[--sp];
+ if (deep[h]) {
+ int c=bits[h], l=c<<1, r=l+1;
+ prnt[c] = NO_PARENT;
+ deep[h]=false;
+ s[sp++] = l;
+ s[sp++] = r;
+ }
+ }
}
-bool bins::get(bin pos) const {
- if (pos>peak)
- return false;
- chunk_iterator i(const_cast<bins*>(this));
- while (i.deep() && i.chunk_top()>pos)
- i.to(pos);
- if (i.deep())
- return false;
- int l = OFFMASK[pos.scoped(i.chunk_top(),4)];
- return (*i & l) == l;
+bool bins::get(bin pos) const {
+ if (pos>peak)
+ return false;
+ chunk_iterator i(const_cast<bins*>(this));
+ while (i.deep() && i.chunk_top()>pos)
+ i.to(pos);
+ if (i.deep())
+ return false;
+ int l = OFFMASK[pos.scoped(i.chunk_top(),4)];
+ return (*i & l) == l;
}
-bool bins::clean(bin pos) const {
- if (pos>peak)
- return bin::all1(pos) ? clean(peak) : true;
- chunk_iterator i(const_cast<bins*>(this));
- while (i.deep() && i.chunk_top()>pos)
- i.to(pos);
- if (i.deep())
- return false;
- int l = OFFMASK[pos.scoped(i.chunk_top(),4)];
- return (*i & l) == 0;
+bool bins::clean(bin pos) const {
+ if (pos>peak)
+ return bin::all1(pos) ? clean(peak) : true;
+ chunk_iterator i(const_cast<bins*>(this));
+ while (i.deep() && i.chunk_top()>pos)
+ i.to(pos);
+ if (i.deep())
+ return false;
+ int l = OFFMASK[pos.scoped(i.chunk_top(),4)];
+ return (*i & l) == 0;
}
-void bins::expand () {
- int oldrootcell = cell_alloc();
- if (deep[0])
- prnt[bits[0]] = oldrootcell;
- prnt[oldrootcell] = 0;
- int orl = oldrootcell<<1, orr = orl+1;
- bits[orl] = bits[0];
- bits[orr] = 0;
- bits[0] = oldrootcell;
- deep[orl] = deep[0];
- deep[orr] = false;
- deep[0] = true;
- peak = peak.parent();
- compact(0);
+void bins::expand () {
+ int oldrootcell = cell_alloc();
+ if (deep[0])
+ prnt[bits[0]] = oldrootcell;
+ prnt[oldrootcell] = 0;
+ int orl = oldrootcell<<1, orr = orl+1;
+ bits[orl] = bits[0];
+ bits[orr] = 0;
+ bits[0] = oldrootcell;
+ deep[orl] = deep[0];
+ deep[orr] = false;
+ deep[0] = true;
+ peak = peak.parent();
+ compact(0);
}
-void bins::set (bin pos, bool to) {
- if (!pos)
- return;
- while (pos>peak)
- expand();
- chunk_iterator i(this);
- while (i.chunk_top().layer()>pos.layer()+4)
- i.to(pos);
- while (i.deep() && i.chunk_top().layer()>pos.layer())
- i.to(pos);
- if (i.deep())
- unlink(i.half);
- int mask = OFFMASK[pos.scoped(i.chunk_top(),4)];
- if (to)
- *i |= mask;
- else
- *i &= ~mask;
- while(i.up()); //compact
+void bins::set (bin pos, bool to) {
+ if (!pos)
+ return;
+ while (pos>peak)
+ expand();
+ chunk_iterator i(this);
+ while (i.chunk_top().layer()>pos.layer()+4)
+ i.to(pos);
+ while (i.deep() && i.chunk_top().layer()>pos.layer())
+ i.to(pos);
+ if (i.deep())
+ unlink(i.half);
+ int mask = OFFMASK[pos.scoped(i.chunk_top(),4)];
+ if (to)
+ *i |= mask;
+ else
+ *i &= ~mask;
+ while(i.up()); //compact
}
-bool bins::compact (int half) {
- if (!deep[half])
- return false;
- int l = bits[half]<<1, r = l+1;
- if (deep[l] || deep[r])
- return false;
- int l1 = JOIN[bits[l]&0xff], l2 = JOIN[bits[l]>>8];
- if (l1==0xff || l2==0xff)
- return false;
- int r1 = JOIN[bits[r]&0xff], r2 = JOIN[bits[r]>>8];
- if (r1==0xff || r2==0xff)
- return false;
- deep[half] = false;
- prnt[bits[half]] = NO_PARENT;
- deep[l] = deep[r] = false;//coward
- bits[half] = (l1) | (l2<<4) | (r1<<8) | (r2<<12);
- return true;
+bool bins::compact (int half) {
+ if (!deep[half])
+ return false;
+ int l = bits[half]<<1, r = l+1;
+ if (deep[l] || deep[r])
+ return false;
+ int l1 = JOIN[bits[l]&0xff], l2 = JOIN[bits[l]>>8];
+ if (l1==0xff || l2==0xff)
+ return false;
+ int r1 = JOIN[bits[r]&0xff], r2 = JOIN[bits[r]>>8];
+ if (r1==0xff || r2==0xff)
+ return false;
+ deep[half] = false;
+ prnt[bits[half]] = NO_PARENT;
+ deep[l] = deep[r] = false;//coward
+ bits[half] = (l1) | (l2<<4) | (r1<<8) | (r2<<12);
+ return true;
}
-void bins::split (int half) {
- if (!deep[half]) {
- int newcell = cell_alloc(), oldcell=half>>1;
- int l = newcell<<1, r = l+1;
- bits[l] = SPLIT[bits[half]&0xff];
- bits[r] = SPLIT[bits[half]>>8];
- deep[half] = true;
- bits[half] = newcell;
- prnt[newcell] = oldcell;
- }
+void bins::split (int half) {
+ if (!deep[half]) {
+ int newcell = cell_alloc(), oldcell=half>>1;
+ int l = newcell<<1, r = l+1;
+ bits[l] = SPLIT[bits[half]&0xff];
+ bits[r] = SPLIT[bits[half]>>8];
+ deep[half] = true;
+ bits[half] = newcell;
+ prnt[newcell] = oldcell;
+ }
}
-void bins::doop (bins& b, int op) {
- while (b.peak<peak)
- b.expand();
- while (b.peak>peak)
- expand();
- chunk_iterator i(this), j(&b);
- do {
- while (i.deep() || j.deep()) {
- i.left();
- j.left();
- }
- switch (op) {
- case OR_OP: (*i) |= *j; break;
- case AND_OP: (*i) &= *j; break;
- case SUB_OP: (*i) &= ~*j; break;
- }
- while (i.chunk_top().is_right()) {
- i.up();
- j.up();
- }
- i.up();
- j.up();
- i.right();
- j.right();
- } while (!i.end());
+void bins::doop (bins& b, int op) {
+ while (b.peak<peak)
+ b.expand();
+ while (b.peak>peak)
+ expand();
+ chunk_iterator i(this), j(&b);
+ do {
+ while (i.deep() || j.deep()) {
+ i.left();
+ j.left();
+ }
+ switch (op) {
+ case OR_OP: (*i) |= *j; break;
+ case AND_OP: (*i) &= *j; break;
+ case SUB_OP: (*i) &= ~*j; break;
+ }
+ while (i.chunk_top().is_right()) {
+ i.up();
+ j.up();
+ }
+ i.up();
+ j.up();
+ i.right();
+ j.right();
+ } while (!i.end());
}
-void bins::operator |= (bins& b) {
- doop(b,OR_OP);
+void bins::operator |= (bins& b) {
+ doop(b,OR_OP);
}
-void bins::operator &= (bins& b) {
- doop(b,AND_OP);
+void bins::operator &= (bins& b) {
+ doop(b,AND_OP);
}
-void bins::operator -= (bins& b) {
- doop(b,SUB_OP);
+void bins::operator -= (bins& b) {
+ doop(b,SUB_OP);
}
-int bins::cell_alloc () { // FIXME: 0xffff size too big
- while (allocp<prnt.size() && prnt[allocp]!=NO_PARENT)
- allocp++;
- if (allocp==prnt.size()) {
- if (rescan_flag) {
- rescan_flag = false;
- allocp=0;
- return cell_alloc();
- } else {
- rescan_flag = true;
- bits.resize(allocp*4,0);
- prnt.resize(allocp*2,NO_PARENT);
- deep.resize(allocp*4,false);
- }
- }
- deep[allocp*2] = false;
- deep[allocp*2+1] = false;
- prnt[allocp] = NO_PARENT;
- return allocp;
+int bins::cell_alloc () { // FIXME: 0xffff size too big
+ while (allocp<prnt.size() && prnt[allocp]!=NO_PARENT)
+ allocp++;
+ if (allocp==prnt.size()) {
+ if (rescan_flag) {
+ rescan_flag = false;
+ allocp=0;
+ return cell_alloc();
+ } else {
+ rescan_flag = true;
+ bits.resize(allocp*4,0);
+ prnt.resize(allocp*2,NO_PARENT);
+ deep.resize(allocp*4,false);
+ }
+ }
+ deep[allocp*2] = false;
+ deep[allocp*2+1] = false;
+ prnt[allocp] = NO_PARENT;
+ return allocp;
}
-/*void bins::make_space () { WAY TOO SMART, DO LATER
+/*void bins::make_space () { WAY TOO SMART, DO LATER
std::vector<int> renames(allocp), irenames(allocp);
int newcellsize=0;
for(int i=0; i<allocp; i++)
public:
- class bin_iterator;
-
- /** Traverses 16-bit chunks. */
- class chunk_iterator {
- bins* host;
- bin top;
- int half;
-
- bool up() {
- top=top.parent();
- int cell = half>>1;
- half=host->prnt[cell]<<1;
- if (!host->deep[half] || host->bits[half]!=cell)
- half++;
- assert(host->deep[half] && host->bits[half]==cell);
- return host->compact(half);
- }
- void left() {
- assert(top.layer()>4);
- top = top.left();
- if (!deep())
- host->split(half);
- half = host->bits[half]<<1;
- }
- void right() {
- assert(top.layer()>4);
- top = top.right();
- if (!deep())
- host->split(half);
- half = (host->bits[half]<<1)+1;
- }
- void to(bin target) {
- assert(top.layer()>4);
- bin next = top.child(target);
- if (next.is_left())
- left();
- else
- right();
- }
- int cell () const { return half>>1; }
- bool deep() const { return host->deep[half]; }
- bool is_right () const { return half&1; }
- bool end () const { return half==1; }
+ class bin_iterator;
+
+ /** Traverses 16-bit chunks. */
+ class chunk_iterator {
+ bins* host;
+ bin top;
+ int half;
+
+ bool up() {
+ top=top.parent();
+ int cell = half>>1;
+ half=host->prnt[cell]<<1;
+ if (!host->deep[half] || host->bits[half]!=cell)
+ half++;
+ assert(host->deep[half] && host->bits[half]==cell);
+ return host->compact(half);
+ }
+ void left() {
+ assert(top.layer()>4);
+ top = top.left();
+ if (!deep())
+ host->split(half);
+ half = host->bits[half]<<1;
+ }
+ void right() {
+ assert(top.layer()>4);
+ top = top.right();
+ if (!deep())
+ host->split(half);
+ half = (host->bits[half]<<1)+1;
+ }
+ void to(bin target) {
+ assert(top.layer()>4);
+ bin next = top.child(target);
+ if (next.is_left())
+ left();
+ else
+ right();
+ }
+ int cell () const { return half>>1; }
+ bool deep() const { return host->deep[half]; }
+ bool is_right () const { return half&1; }
+ bool end () const { return half==1; }
- public:
- chunk_iterator(bins* h, int hlf=0) : host(h), top(h->peak), half(hlf) {
- //while (deep())
- // left();
- }
- void operator ++ () {
- while (is_right())
- up();
- up();
- right();
- while (deep() && !end())
- left();
- }
- uint16_t& operator * () {
- return host->bits[half];
- }
- bool operator == (const bins::chunk_iterator& b) const {
- return host==b.host && half==b.half;
- }
- bin chunk_top() const { return top; }
- friend class bins::bin_iterator;
- friend class bins;
- }; // chunk_iterator
-
-
- /** Traverses bins. */
- class bin_iterator {
- bins::chunk_iterator i;
- bin cur;
- public:
- bin_iterator(chunk_iterator ci, bin pos=0) : i(ci), cur(pos) {
- while (!i.end() && i.deep())
- i.left();
- ++(*this);
- }
- bin operator * () const {
- return cur.unscoped(i.top,4);
- }
- void operator ++ () {
- if (i.end())
- return;
- do {
- if (cur<bin(4,0)) {
- cur++;
- } else {
- cur = 1;
- ++i;
- }
- } while (!i.end() && (*i&OFFMASK[cur])!=OFFMASK[cur]);
- bin p=cur.parent();
- while (p<=bin(4,0) && (*i&OFFMASK[p])==OFFMASK[p]) {
- cur=p;
- p=cur.parent();
- }
- }
- bool operator == (const bins::chunk_iterator& b) const {return i==b;}
- bool operator == (const bins::bin_iterator& b) const {
- return i==b.i && cur==b.cur;
- }
- bool operator != (const bins::bin_iterator& b) const { return !(*this==b); }
- }; // bin_iterator
-
-
+ public:
+ chunk_iterator(bins* h, int hlf=0) : host(h), top(h->peak), half(hlf) {
+ //while (deep())
+ // left();
+ }
+ void operator ++ () {
+ while (is_right())
+ up();
+ up();
+ right();
+ while (deep() && !end())
+ left();
+ }
+ uint16_t& operator * () {
+ return host->bits[half];
+ }
+ bool operator == (const bins::chunk_iterator& b) const {
+ return host==b.host && half==b.half;
+ }
+ bin chunk_top() const { return top; }
+ friend class bins::bin_iterator;
+ friend class bins;
+ }; // chunk_iterator
+
+
+ /** Traverses bins. */
+ class bin_iterator {
+ bins::chunk_iterator i;
+ bin cur;
+ public:
+ bin_iterator(chunk_iterator ci, bin pos=0) : i(ci), cur(pos) {
+ while (!i.end() && i.deep())
+ i.left();
+ ++(*this);
+ }
+ bin operator * () const {
+ return cur.unscoped(i.top,4);
+ }
+ void operator ++ () {
+ if (i.end())
+ return;
+ do {
+ if (cur<bin(4,0)) {
+ cur++;
+ } else {
+ cur = 1;
+ ++i;
+ }
+ } while (!i.end() && (*i&OFFMASK[cur])!=OFFMASK[cur]);
+ bin p=cur.parent();
+ while (p<=bin(4,0) && (*i&OFFMASK[p])==OFFMASK[p]) {
+ cur=p;
+ p=cur.parent();
+ }
+ }
+ bool operator == (const bins::chunk_iterator& b) const {return i==b;}
+ bool operator == (const bins::bin_iterator& b) const {
+ return i==b.i && cur==b.cur;
+ }
+ bool operator != (const bins::bin_iterator& b) const { return !(*this==b); }
+ }; // bin_iterator
+
+
private:
- bin peak;
- std::vector<uint16_t> bits;
- std::vector<uint16_t> prnt; // BAD BAD BAD
- std::vector<bool> deep;
- int allocp;
- bool rescan_flag;
+ bin peak;
+ std::vector<uint16_t> bits;
+ std::vector<uint16_t> prnt; // BAD BAD BAD
+ std::vector<bool> deep;
+ int allocp;
+ bool rescan_flag;
-
+
private:
-
- void unlink (int half);
- void expand();
- void split(int half);
-
- //void make_space();
- int cell_alloc();
- bool compact (int cell);
-
- void doop (bins& b, int op);
-
- static uint16_t SPLIT[256];
- static uint8_t JOIN[256];
- static uint16_t OFFMASK[32];
- typedef enum { AND_OP, OR_OP, SUB_OP } ops_t;
-
+
+ void unlink (int half);
+ void expand();
+ void split(int half);
+
+ //void make_space();
+ int cell_alloc();
+ bool compact (int cell);
+
+ void doop (bins& b, int op);
+
+ static uint16_t SPLIT[256];
+ static uint8_t JOIN[256];
+ static uint16_t OFFMASK[32];
+ typedef enum { AND_OP, OR_OP, SUB_OP } ops_t;
+
public:
-
- bins();
- bins(const bins& orig);
-
- bool get(bin pos) const;
- bool clean(bin pos) const;
- bool contains(bin pos) const { return get(pos); }
- void set(bin pos, bool to=true);
- bool empty() const { return !deep[0] && !bits[0]; }
- bool operator [] (bin pos) const {return get(pos);}
- void operator |= (bin pos) { set(pos); }
- void operator -= (bin pos) { set(pos,false); }
- void operator |= (bins& b);
- void operator &= (bins& b);
- void operator -= (bins& b);
-
- bin_iterator begin() { return bin_iterator(chunk_iterator(this,0)); }
- bin_iterator end() { return bin_iterator(chunk_iterator(this,1),1); }
-
- static void init();
- friend class SbitTest;
+
+ bins();
+ bins(const bins& orig);
+
+ bool get(bin pos) const;
+ bool clean(bin pos) const;
+ bool contains(bin pos) const { return get(pos); }
+ void set(bin pos, bool to=true);
+ bool empty() const { return !deep[0] && !bits[0]; }
+ bool operator [] (bin pos) const {return get(pos);}
+ void operator |= (bin pos) { set(pos); }
+ void operator -= (bin pos) { set(pos,false); }
+ void operator |= (bins& b);
+ void operator &= (bins& b);
+ void operator -= (bins& b);
+
+ bin_iterator begin() { return bin_iterator(chunk_iterator(this,0)); }
+ bin_iterator end() { return bin_iterator(chunk_iterator(this,1),1); }
+
+ static void init();
+ friend class SbitTest;
};
- randomized testing of advanced ops (new testcase)
*/
-void Channel::AddPeakHashes (Datagram& dgram) {
- for(int i=0; i<file().peak_count(); i++) {
+void Channel::AddPeakHashes (Datagram& dgram) {
+ for(int i=0; i<file().peak_count(); i++) {
bin64_t peak = file().peak(i);
- dgram.Push8(P2TP_HASH);
- dgram.Push32((uint32_t)peak);
- dgram.PushHash(file().peak_hash(i));
+ dgram.Push8(P2TP_HASH);
+ dgram.Push32((uint32_t)peak);
+ dgram.PushHash(file().peak_hash(i));
//DLOG(INFO)<<"#"<<id<<" +pHASH"<<file().peak(i);
dprintf("%s #%i +phash %s\n",tintstr(),id,peak.str());
- }
+ }
}
-void Channel::AddUncleHashes (Datagram& dgram, bin64_t pos) {
+void Channel::AddUncleHashes (Datagram& dgram, bin64_t pos) {
bin64_t peak = file().peak_for(pos);
while (pos!=peak && ((NOW&7)==7 || !data_out_cap_.within(pos.parent())) &&
ack_in_.get(pos.parent())==bins::EMPTY) {
bin64_t uncle = pos.sibling();
- dgram.Push8(P2TP_HASH);
- dgram.Push32((uint32_t)uncle);
- dgram.PushHash( file().hash(uncle) );
+ dgram.Push8(P2TP_HASH);
+ dgram.Push32((uint32_t)uncle);
+ dgram.PushHash( file().hash(uncle) );
//DLOG(INFO)<<"#"<<id<<" +uHASH"<<uncle;
dprintf("%s #%i +hash %s\n",tintstr(),id,uncle.str());
pos = pos.parent();
}
-bin64_t Channel::DequeueHint () { // TODO: resilience
+bin64_t Channel::DequeueHint () { // TODO: resilience
bin64_t send = bin64_t::NONE;
while (!hint_in_.empty() && send==bin64_t::NONE) {
bin64_t hint = hint_in_.front().bin;
}
-void Channel::AddHandshake (Datagram& dgram) {
- if (!peer_channel_id_) { // initiating
- dgram.Push8(P2TP_HASH);
- dgram.Push32(bin64_t::ALL32);
- dgram.PushHash(file().root_hash());
+void Channel::AddHandshake (Datagram& dgram) {
+ if (!peer_channel_id_) { // initiating
+ dgram.Push8(P2TP_HASH);
+ dgram.Push32(bin64_t::ALL32);
+ dgram.PushHash(file().root_hash());
dprintf("%s #%i +hash ALL %s\n",
tintstr(),id,file().root_hash().hex().c_str());
- }
- dgram.Push8(P2TP_HANDSHAKE);
+ }
+ dgram.Push8(P2TP_HANDSHAKE);
int encoded = EncodeID(id);
- dgram.Push32(encoded);
+ dgram.Push32(encoded);
dprintf("%s #%i +hs %i\n",tintstr(),id,encoded);
ack_out_.clear();
AddAck(dgram);
}
-void Channel::Send () {
+void Channel::Send () {
Datagram dgram(socket_,peer());
dgram.Push32(peer_channel_id_);
bin64_t data = bin64_t::NONE;
}
-void Channel::AddHint (Datagram& dgram) {
+void Channel::AddHint (Datagram& dgram) {
tint timed_out = NOW - TINT_SEC*3/2;
- while ( !hint_out_.empty() && hint_out_.front().time < timed_out ) {
+ while ( !hint_out_.empty() && hint_out_.front().time < timed_out ) {
hint_out_size_ -= hint_out_.front().bin.width();
- hint_out_.pop_front();
- }
+ hint_out_.pop_front();
+ }
int peer_cwnd = (int)(rtt_avg_ / dip_avg_);
if (!peer_cwnd)
}
-bin64_t Channel::AddData (Datagram& dgram) {
-
+bin64_t Channel::AddData (Datagram& dgram) {
+
if (!file().size()) // know nothing
- return bin64_t::NONE;
+ return bin64_t::NONE;
- bin64_t tosend = bin64_t::NONE;
+ bin64_t tosend = bin64_t::NONE;
if (cc_->MaySendData()) {
tosend = DequeueHint();
if (tosend==bin64_t::NONE)
data_out_.push_back(tosend);
dprintf("%s #%i +data %s\n",tintstr(),id,tosend.str());
- return tosend;
+ return tosend;
}
-void Channel::AddTs (Datagram& dgram) {
+void Channel::AddTs (Datagram& dgram) {
dgram.Push8(P2TP_TS);
dgram.Push64(data_in_.time);
dprintf("%s #%i +ts %s\n",tintstr(),id,tintstr(data_in_.time));
}
-void Channel::AddAck (Datagram& dgram) {
+void Channel::AddAck (Datagram& dgram) {
if (data_in_dbl_!=bin64_t::NONE) {
- dgram.Push8(P2TP_ACK);
- dgram.Push32(data_in_dbl_);
+ dgram.Push8(P2TP_ACK);
+ dgram.Push32(data_in_dbl_);
data_in_dbl_=bin64_t::NONE;
}
- if (data_in_.bin!=bin64_t::NONE) {
+ if (data_in_.bin!=bin64_t::NONE) {
AddTs(dgram);
bin64_t pos = file().ack_out().cover(data_in_.bin);
- dgram.Push8(P2TP_ACK);
- dgram.Push32(pos);
- //dgram.Push64(data_in_.time);
+ dgram.Push8(P2TP_ACK);
+ dgram.Push32(pos);
+ //dgram.Push64(data_in_.time);
ack_out_.set(pos);
dprintf("%s #%i +ack %s %s\n",tintstr(),id,pos.str(),tintstr(data_in_.time));
data_in_ = tintbin(0,bin64_t::NONE);
if (pos.layer()>2)
data_in_dbl_ = pos;
- }
+ }
for(int count=0; count<4; count++) {
bin64_t ack = file().ack_out().find_filtered(ack_out_, bin64_t::ALL, bins::FILLED);
if (ack==bin64_t::NONE)
}
-void Channel::Recv (Datagram& dgram) {
+void Channel::Recv (Datagram& dgram) {
dprintf("%s #%i recvd %i\n",tintstr(),id,dgram.size()+4);
if (last_send_time_ && rtt_avg_==TINT_SEC && dev_avg_==0) {
rtt_avg_ = NOW - last_send_time_;
dprintf("%s #%i rtt init %lli\n",tintstr(),id,rtt_avg_);
}
bin64_t data = dgram.size() ? bin64_t::NONE : bin64_t::ALL;
- while (dgram.size()) {
- uint8_t type = dgram.Pull8();
- switch (type) {
+ while (dgram.size()) {
+ uint8_t type = dgram.Pull8();
+ switch (type) {
case P2TP_HANDSHAKE: OnHandshake(dgram); break;
- case P2TP_DATA: data=OnData(dgram); break;
- case P2TP_TS: OnTs(dgram); break;
- case P2TP_ACK: OnAck(dgram); break;
- case P2TP_HASH: OnHash(dgram); break;
- case P2TP_HINT: OnHint(dgram); break;
+ case P2TP_DATA: data=OnData(dgram); break;
+ case P2TP_TS: OnTs(dgram); break;
+ case P2TP_ACK: OnAck(dgram); break;
+ case P2TP_HASH: OnHash(dgram); break;
+ case P2TP_HINT: OnHint(dgram); break;
case P2TP_PEX_ADD: OnPex(dgram); break;
- default:
- eprintf("%s #%i ?msg id unknown %i\n",tintstr(),id,(int)type);
- return;
- }
- }
+ default:
+ eprintf("%s #%i ?msg id unknown %i\n",tintstr(),id,(int)type);
+ return;
+ }
+ }
cc_->OnDataRecvd(data);
last_recv_time_ = NOW;
}
-void Channel::OnHash (Datagram& dgram) {
- bin64_t pos = dgram.Pull32();
- Sha1Hash hash = dgram.PullHash();
- file().OfferHash(pos,hash);
+void Channel::OnHash (Datagram& dgram) {
+ bin64_t pos = dgram.Pull32();
+ Sha1Hash hash = dgram.PullHash();
+ file().OfferHash(pos,hash);
//DLOG(INFO)<<"#"<<id<<" .HASH"<<(int)pos;
dprintf("%s #%i -hash %s\n",tintstr(),id,pos.str());
}
bin64_t Channel::OnData (Datagram& dgram) {
- bin64_t pos = dgram.Pull32();
+ bin64_t pos = dgram.Pull32();
uint8_t *data;
int length = dgram.Pull(&data,1024);
bool ok = (pos==bin64_t::NONE) || file().OfferData(pos, (char*)data, length) ;
}
-void Channel::OnAck (Datagram& dgram) {
- bin64_t ackd_pos = dgram.Pull32();
+void Channel::OnAck (Datagram& dgram) {
+ bin64_t ackd_pos = dgram.Pull32();
if (ackd_pos!=bin64_t::NONE && file().size() && ackd_pos.base_offset()>=file().packet_size()) {
eprintf("invalid ack: %s\n",ackd_pos.str());
return;
}
-void Channel::OnHint (Datagram& dgram) {
- bin64_t hint = dgram.Pull32();
- hint_in_.push_back(hint);
+void Channel::OnHint (Datagram& dgram) {
+ bin64_t hint = dgram.Pull32();
+ hint_in_.push_back(hint);
//ack_in_.set(hint,bins::EMPTY);
//RequeueSend(cc_->OnHintRecvd(hint));
dprintf("%s #%i -hint %s\n",tintstr(),id,hint.str());
}
-void Channel::RecvDatagram (int socket) {
- Datagram data(socket);
- data.Recv();
+void Channel::RecvDatagram (int socket) {
+ Datagram data(socket);
+ data.Recv();
Address& addr = data.addr;
#define return_log(...) { eprintf(__VA_ARGS__); return; }
- if (data.size()<4)
- return_log("datagram shorter than 4 bytes %s\n",addr.str());
- uint32_t mych = data.Pull32();
- Sha1Hash hash;
- Channel* channel = NULL;
- if (!mych) { // handshake initiated
- if (data.size()<1+4+1+4+Sha1Hash::SIZE)
- return_log ("incorrect size %i initial handshake packet %s\n",data.size(),addr.str());
- uint8_t hashid = data.Pull8();
- if (hashid!=P2TP_HASH)
- return_log ("no hash in the initial handshake %s\n",addr.str());
- bin64_t pos = data.Pull32();
- if (pos!=bin64_t::ALL)
- return_log ("that is not the root hash %s\n",addr.str());
- hash = data.PullHash();
- FileTransfer* file = FileTransfer::Find(hash);
- if (!file)
- return_log ("hash %s unknown, no such file %s\n",hash.hex().c_str(),addr.str());
+ if (data.size()<4)
+ return_log("datagram shorter than 4 bytes %s\n",addr.str());
+ uint32_t mych = data.Pull32();
+ Sha1Hash hash;
+ Channel* channel = NULL;
+ if (!mych) { // handshake initiated
+ if (data.size()<1+4+1+4+Sha1Hash::SIZE)
+ return_log ("incorrect size %i initial handshake packet %s\n",data.size(),addr.str());
+ uint8_t hashid = data.Pull8();
+ if (hashid!=P2TP_HASH)
+ return_log ("no hash in the initial handshake %s\n",addr.str());
+ bin64_t pos = data.Pull32();
+ if (pos!=bin64_t::ALL)
+ return_log ("that is not the root hash %s\n",addr.str());
+ hash = data.PullHash();
+ FileTransfer* file = FileTransfer::Find(hash);
+ if (!file)
+ return_log ("hash %s unknown, no such file %s\n",hash.hex().c_str(),addr.str());
dprintf("%s #0 -hash ALL %s\n",tintstr(),hash.hex().c_str());
for(binqueue::iterator i=file->hs_in_.begin(); i!=file->hs_in_.end(); i++)
if (channels[*i] && channels[*i]->peer_==data.addr &&
channels[*i]->last_recv_time_>NOW-TINT_SEC*2)
return_log("have a channel already to %s\n",addr.str());
- channel = new Channel(file, socket, data.address());
- } else {
- mych = DecodeID(mych);
- if (mych>=channels.size())
+ channel = new Channel(file, socket, data.address());
+ } else {
+ mych = DecodeID(mych);
+ if (mych>=channels.size())
return_log("invalid channel #%i, %s\n",mych,addr.str());
- channel = channels[mych];
- if (!channel)
- return_log ("channel #%i is already closed\n",mych,addr.str());
- if (channel->peer() != addr)
- return_log ("invalid peer address #%i %s!=%s\n",mych,channel->peer().str(),addr.str());
+ channel = channels[mych];
+ if (!channel)
+ return_log ("channel #%i is already closed\n",mych,addr.str());
+ if (channel->peer() != addr)
+ return_log ("invalid peer address #%i %s!=%s\n",mych,channel->peer().str(),addr.str());
channel->own_id_mentioned_ = true;
- }
+ }
//dprintf("recvd %i bytes for %i\n",data.size(),channel->id);
channel->Recv(data);
}
void Channel::Loop (tint howlong) {
-
+
tint limit = Datagram::Time() + howlong;
do {
}
} while (Datagram::Time()<limit);
-
+
}
*/
#define SHA_ASM(op, x, n) ({ unsigned int __res; __asm__(op " %1,%0":"=r" (__res):"i" (n), "0" (x)); __res; })
-#define SHA_ROL(x,n) SHA_ASM("rol", x, n)
-#define SHA_ROR(x,n) SHA_ASM("ror", x, n)
+#define SHA_ROL(x,n) SHA_ASM("rol", x, n)
+#define SHA_ROR(x,n) SHA_ASM("ror", x, n)
#else
-#define SHA_ROT(X,l,r) (((X) << (l)) | ((X) >> (r)))
-#define SHA_ROL(X,n) SHA_ROT(X,n,32-(n))
-#define SHA_ROR(X,n) SHA_ROT(X,32-(n),n)
+#define SHA_ROT(X,l,r) (((X) << (l)) | ((X) >> (r)))
+#define SHA_ROL(X,n) SHA_ROT(X,n,32-(n))
+#define SHA_ROR(X,n) SHA_ROT(X,32-(n),n)
#endif
defined(__powerpc__) || defined(__powerpc64__) || \
defined(__s390__) || defined(__s390x__)
-#define get_be32(p) ntohl(*(unsigned int *)(p))
-#define put_be32(p, v) do { *(unsigned int *)(p) = htonl(v); } while (0)
+#define get_be32(p) ntohl(*(unsigned int *)(p))
+#define put_be32(p, v) do { *(unsigned int *)(p) = htonl(v); } while (0)
#else
-#define get_be32(p) ( \
- (*((unsigned char *)(p) + 0) << 24) | \
- (*((unsigned char *)(p) + 1) << 16) | \
- (*((unsigned char *)(p) + 2) << 8) | \
- (*((unsigned char *)(p) + 3) << 0) )
-#define put_be32(p, v) do { \
- unsigned int __v = (v); \
- *((unsigned char *)(p) + 0) = __v >> 24; \
- *((unsigned char *)(p) + 1) = __v >> 16; \
- *((unsigned char *)(p) + 2) = __v >> 8; \
- *((unsigned char *)(p) + 3) = __v >> 0; } while (0)
+#define get_be32(p) ( \
+ (*((unsigned char *)(p) + 0) << 24) | \
+ (*((unsigned char *)(p) + 1) << 16) | \
+ (*((unsigned char *)(p) + 2) << 8) | \
+ (*((unsigned char *)(p) + 3) << 0) )
+#define put_be32(p, v) do { \
+ unsigned int __v = (v); \
+ *((unsigned char *)(p) + 0) = __v >> 24; \
+ *((unsigned char *)(p) + 1) = __v >> 16; \
+ *((unsigned char *)(p) + 2) = __v >> 8; \
+ *((unsigned char *)(p) + 3) = __v >> 0; } while (0)
#endif
#define SHA_MIX(t) SHA_ROL(W(t+13) ^ W(t+8) ^ W(t+2) ^ W(t), 1)
#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \
- unsigned int TEMP = input(t); setW(t, TEMP); \
- E += TEMP + SHA_ROL(A,5) + (fn) + (constant); \
- B = SHA_ROR(B, 2); } while (0)
+ unsigned int TEMP = input(t); setW(t, TEMP); \
+ E += TEMP + SHA_ROL(A,5) + (fn) + (constant); \
+ B = SHA_ROR(B, 2); } while (0)
#define T_0_15(t, A, B, C, D, E) SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
static void blk_SHA1_Block(blk_SHA_CTX *ctx, const unsigned int *data)
{
- unsigned int A,B,C,D,E;
- unsigned int array[16];
-
- A = ctx->H[0];
- B = ctx->H[1];
- C = ctx->H[2];
- D = ctx->H[3];
- E = ctx->H[4];
-
- /* Round 1 - iterations 0-16 take their input from 'data' */
- T_0_15( 0, A, B, C, D, E);
- T_0_15( 1, E, A, B, C, D);
- T_0_15( 2, D, E, A, B, C);
- T_0_15( 3, C, D, E, A, B);
- T_0_15( 4, B, C, D, E, A);
- T_0_15( 5, A, B, C, D, E);
- T_0_15( 6, E, A, B, C, D);
- T_0_15( 7, D, E, A, B, C);
- T_0_15( 8, C, D, E, A, B);
- T_0_15( 9, B, C, D, E, A);
- T_0_15(10, A, B, C, D, E);
- T_0_15(11, E, A, B, C, D);
- T_0_15(12, D, E, A, B, C);
- T_0_15(13, C, D, E, A, B);
- T_0_15(14, B, C, D, E, A);
- T_0_15(15, A, B, C, D, E);
-
- /* Round 1 - tail. Input from 512-bit mixing array */
- T_16_19(16, E, A, B, C, D);
- T_16_19(17, D, E, A, B, C);
- T_16_19(18, C, D, E, A, B);
- T_16_19(19, B, C, D, E, A);
-
- /* Round 2 */
- T_20_39(20, A, B, C, D, E);
- T_20_39(21, E, A, B, C, D);
- T_20_39(22, D, E, A, B, C);
- T_20_39(23, C, D, E, A, B);
- T_20_39(24, B, C, D, E, A);
- T_20_39(25, A, B, C, D, E);
- T_20_39(26, E, A, B, C, D);
- T_20_39(27, D, E, A, B, C);
- T_20_39(28, C, D, E, A, B);
- T_20_39(29, B, C, D, E, A);
- T_20_39(30, A, B, C, D, E);
- T_20_39(31, E, A, B, C, D);
- T_20_39(32, D, E, A, B, C);
- T_20_39(33, C, D, E, A, B);
- T_20_39(34, B, C, D, E, A);
- T_20_39(35, A, B, C, D, E);
- T_20_39(36, E, A, B, C, D);
- T_20_39(37, D, E, A, B, C);
- T_20_39(38, C, D, E, A, B);
- T_20_39(39, B, C, D, E, A);
-
- /* Round 3 */
- T_40_59(40, A, B, C, D, E);
- T_40_59(41, E, A, B, C, D);
- T_40_59(42, D, E, A, B, C);
- T_40_59(43, C, D, E, A, B);
- T_40_59(44, B, C, D, E, A);
- T_40_59(45, A, B, C, D, E);
- T_40_59(46, E, A, B, C, D);
- T_40_59(47, D, E, A, B, C);
- T_40_59(48, C, D, E, A, B);
- T_40_59(49, B, C, D, E, A);
- T_40_59(50, A, B, C, D, E);
- T_40_59(51, E, A, B, C, D);
- T_40_59(52, D, E, A, B, C);
- T_40_59(53, C, D, E, A, B);
- T_40_59(54, B, C, D, E, A);
- T_40_59(55, A, B, C, D, E);
- T_40_59(56, E, A, B, C, D);
- T_40_59(57, D, E, A, B, C);
- T_40_59(58, C, D, E, A, B);
- T_40_59(59, B, C, D, E, A);
-
- /* Round 4 */
- T_60_79(60, A, B, C, D, E);
- T_60_79(61, E, A, B, C, D);
- T_60_79(62, D, E, A, B, C);
- T_60_79(63, C, D, E, A, B);
- T_60_79(64, B, C, D, E, A);
- T_60_79(65, A, B, C, D, E);
- T_60_79(66, E, A, B, C, D);
- T_60_79(67, D, E, A, B, C);
- T_60_79(68, C, D, E, A, B);
- T_60_79(69, B, C, D, E, A);
- T_60_79(70, A, B, C, D, E);
- T_60_79(71, E, A, B, C, D);
- T_60_79(72, D, E, A, B, C);
- T_60_79(73, C, D, E, A, B);
- T_60_79(74, B, C, D, E, A);
- T_60_79(75, A, B, C, D, E);
- T_60_79(76, E, A, B, C, D);
- T_60_79(77, D, E, A, B, C);
- T_60_79(78, C, D, E, A, B);
- T_60_79(79, B, C, D, E, A);
-
- ctx->H[0] += A;
- ctx->H[1] += B;
- ctx->H[2] += C;
- ctx->H[3] += D;
- ctx->H[4] += E;
+ unsigned int A,B,C,D,E;
+ unsigned int array[16];
+
+ A = ctx->H[0];
+ B = ctx->H[1];
+ C = ctx->H[2];
+ D = ctx->H[3];
+ E = ctx->H[4];
+
+ /* Round 1 - iterations 0-16 take their input from 'data' */
+ T_0_15( 0, A, B, C, D, E);
+ T_0_15( 1, E, A, B, C, D);
+ T_0_15( 2, D, E, A, B, C);
+ T_0_15( 3, C, D, E, A, B);
+ T_0_15( 4, B, C, D, E, A);
+ T_0_15( 5, A, B, C, D, E);
+ T_0_15( 6, E, A, B, C, D);
+ T_0_15( 7, D, E, A, B, C);
+ T_0_15( 8, C, D, E, A, B);
+ T_0_15( 9, B, C, D, E, A);
+ T_0_15(10, A, B, C, D, E);
+ T_0_15(11, E, A, B, C, D);
+ T_0_15(12, D, E, A, B, C);
+ T_0_15(13, C, D, E, A, B);
+ T_0_15(14, B, C, D, E, A);
+ T_0_15(15, A, B, C, D, E);
+
+ /* Round 1 - tail. Input from 512-bit mixing array */
+ T_16_19(16, E, A, B, C, D);
+ T_16_19(17, D, E, A, B, C);
+ T_16_19(18, C, D, E, A, B);
+ T_16_19(19, B, C, D, E, A);
+
+ /* Round 2 */
+ T_20_39(20, A, B, C, D, E);
+ T_20_39(21, E, A, B, C, D);
+ T_20_39(22, D, E, A, B, C);
+ T_20_39(23, C, D, E, A, B);
+ T_20_39(24, B, C, D, E, A);
+ T_20_39(25, A, B, C, D, E);
+ T_20_39(26, E, A, B, C, D);
+ T_20_39(27, D, E, A, B, C);
+ T_20_39(28, C, D, E, A, B);
+ T_20_39(29, B, C, D, E, A);
+ T_20_39(30, A, B, C, D, E);
+ T_20_39(31, E, A, B, C, D);
+ T_20_39(32, D, E, A, B, C);
+ T_20_39(33, C, D, E, A, B);
+ T_20_39(34, B, C, D, E, A);
+ T_20_39(35, A, B, C, D, E);
+ T_20_39(36, E, A, B, C, D);
+ T_20_39(37, D, E, A, B, C);
+ T_20_39(38, C, D, E, A, B);
+ T_20_39(39, B, C, D, E, A);
+
+ /* Round 3 */
+ T_40_59(40, A, B, C, D, E);
+ T_40_59(41, E, A, B, C, D);
+ T_40_59(42, D, E, A, B, C);
+ T_40_59(43, C, D, E, A, B);
+ T_40_59(44, B, C, D, E, A);
+ T_40_59(45, A, B, C, D, E);
+ T_40_59(46, E, A, B, C, D);
+ T_40_59(47, D, E, A, B, C);
+ T_40_59(48, C, D, E, A, B);
+ T_40_59(49, B, C, D, E, A);
+ T_40_59(50, A, B, C, D, E);
+ T_40_59(51, E, A, B, C, D);
+ T_40_59(52, D, E, A, B, C);
+ T_40_59(53, C, D, E, A, B);
+ T_40_59(54, B, C, D, E, A);
+ T_40_59(55, A, B, C, D, E);
+ T_40_59(56, E, A, B, C, D);
+ T_40_59(57, D, E, A, B, C);
+ T_40_59(58, C, D, E, A, B);
+ T_40_59(59, B, C, D, E, A);
+
+ /* Round 4 */
+ T_60_79(60, A, B, C, D, E);
+ T_60_79(61, E, A, B, C, D);
+ T_60_79(62, D, E, A, B, C);
+ T_60_79(63, C, D, E, A, B);
+ T_60_79(64, B, C, D, E, A);
+ T_60_79(65, A, B, C, D, E);
+ T_60_79(66, E, A, B, C, D);
+ T_60_79(67, D, E, A, B, C);
+ T_60_79(68, C, D, E, A, B);
+ T_60_79(69, B, C, D, E, A);
+ T_60_79(70, A, B, C, D, E);
+ T_60_79(71, E, A, B, C, D);
+ T_60_79(72, D, E, A, B, C);
+ T_60_79(73, C, D, E, A, B);
+ T_60_79(74, B, C, D, E, A);
+ T_60_79(75, A, B, C, D, E);
+ T_60_79(76, E, A, B, C, D);
+ T_60_79(77, D, E, A, B, C);
+ T_60_79(78, C, D, E, A, B);
+ T_60_79(79, B, C, D, E, A);
+
+ ctx->H[0] += A;
+ ctx->H[1] += B;
+ ctx->H[2] += C;
+ ctx->H[3] += D;
+ ctx->H[4] += E;
}
void blk_SHA1_Init(blk_SHA_CTX *ctx)
{
- ctx->size = 0;
-
- /* Initialize H with the magic constants (see FIPS180 for constants) */
- ctx->H[0] = 0x67452301;
- ctx->H[1] = 0xefcdab89;
- ctx->H[2] = 0x98badcfe;
- ctx->H[3] = 0x10325476;
- ctx->H[4] = 0xc3d2e1f0;
+ ctx->size = 0;
+
+ /* Initialize H with the magic constants (see FIPS180 for constants) */
+ ctx->H[0] = 0x67452301;
+ ctx->H[1] = 0xefcdab89;
+ ctx->H[2] = 0x98badcfe;
+ ctx->H[3] = 0x10325476;
+ ctx->H[4] = 0xc3d2e1f0;
}
void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *data, unsigned long len)
{
- int lenW = ctx->size & 63;
-
- ctx->size += len;
-
- /* Read the data into W and process blocks as they get full */
- if (lenW) {
- int left = 64 - lenW;
- if (len < left)
- left = len;
- memcpy(lenW + (char *)ctx->W, data, left);
- lenW = (lenW + left) & 63;
- len -= left;
- data = ((const char *)data + left);
- if (lenW)
- return;
- blk_SHA1_Block(ctx, ctx->W);
- }
- while (len >= 64) {
- blk_SHA1_Block(ctx, (const unsigned int*)data);
- data = ((const char *)data + 64);
- len -= 64;
- }
- if (len)
- memcpy(ctx->W, data, len);
+ int lenW = ctx->size & 63;
+
+ ctx->size += len;
+
+ /* Read the data into W and process blocks as they get full */
+ if (lenW) {
+ int left = 64 - lenW;
+ if (len < left)
+ left = len;
+ memcpy(lenW + (char *)ctx->W, data, left);
+ lenW = (lenW + left) & 63;
+ len -= left;
+ data = ((const char *)data + left);
+ if (lenW)
+ return;
+ blk_SHA1_Block(ctx, ctx->W);
+ }
+ while (len >= 64) {
+ blk_SHA1_Block(ctx, (const unsigned int*)data);
+ data = ((const char *)data + 64);
+ len -= 64;
+ }
+ if (len)
+ memcpy(ctx->W, data, len);
}
void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx)
{
- static const unsigned char pad[64] = { 0x80 };
- unsigned int padlen[2];
- int i;
+ static const unsigned char pad[64] = { 0x80 };
+ unsigned int padlen[2];
+ int i;
- /* Pad with a binary 1 (ie 0x80), then zeroes, then length */
- padlen[0] = htonl(ctx->size >> 29);
- padlen[1] = htonl(ctx->size << 3);
+ /* Pad with a binary 1 (ie 0x80), then zeroes, then length */
+ padlen[0] = htonl(ctx->size >> 29);
+ padlen[1] = htonl(ctx->size << 3);
- i = ctx->size & 63;
- blk_SHA1_Update(ctx, pad, 1+ (63 & (55 - i)));
- blk_SHA1_Update(ctx, padlen, 8);
+ i = ctx->size & 63;
+ blk_SHA1_Update(ctx, pad, 1+ (63 & (55 - i)));
+ blk_SHA1_Update(ctx, padlen, 8);
- /* Output hash */
- for (i = 0; i < 5; i++)
- put_be32(hashout + i*4, ctx->H[i]);
+ /* Output hash */
+ for (i = 0; i < 5; i++)
+ put_be32(hashout + i*4, ctx->H[i]);
}
#define GIT_SHA1
typedef struct {
- unsigned long long size;
- unsigned int H[5];
- unsigned int W[16];
+ unsigned long long size;
+ unsigned int H[5];
+ unsigned int W[16];
} blk_SHA_CTX;
void blk_SHA1_Init(blk_SHA_CTX *ctx);