From: arno Date: Tue, 20 Oct 2009 12:16:52 +0000 (+0000) Subject: - Result of svn merge -x --ignore-eol-style -r 424:458 https://ttuki.vtt.fi/svn/p2p... X-Git-Url: http://p2p-next.cs.pub.ro/gitweb/?a=commitdiff_plain;h=5c147b8255f7102678a5d2a222bef1b9c6115898;p=swift-upb.git - Result of svn merge -x --ignore-eol-style -r 424:458 https://ttuki.vtt.fi/svn/p2p-next/TUD/p2tp/branches/arno/d09-10-16-win32port-r424 i.e. merge of Win32 port onto trunk. TODO: test on Linux. git-svn-id: https://ttuki.vtt.fi/svn/p2p-next/TUD/p2tp/trunk@459 e16421f0-f15b-0410-abcd-98678b794739 --- diff --git a/SConstruct b/SConstruct index cc59e73..33970ee 100644 --- a/SConstruct +++ b/SConstruct @@ -1,14 +1,109 @@ +# Written by Victor Grishchenko, Arno Bakker +# see LICENSE.txt for license information +# +# Requirements: +# - scons: Cross-platform build system http://www.scons.org/ +# - googletest: Google C++ Test Framework http://code.google.com/p/googletest/ +# * Install in ..\gtest-1.4.0 +# - google-glog: Google Logging Library for C++ http://code.google.com/p/google-glog/ +# * Install in ..\glog-0.3.0 +# * I get ..\glog-0.3.0\src\windows\glog/log_severity.h(51) : error C2059: syntax error : +# 'constant' while running scons. Apparently the ERROR constant is already defined somewhere. +# #undef ERROR before the def allows include. +# +# - OpenSSL: http://www.slproweb.com/products/Win32OpenSSL.html +# * Install non-light Win32 binary in \openssl +# * Using a openssl-0.9.8k tar-ball doesn't work as the includes there +# are symbolic links which get turned into 0 length files by 7Zip. +# + import os import re +import sys + +DEBUG = True TestDir='tests' -env = Environment(CPPPATH = ['.']) +target = 'p2tp' +source = [ 'bin64.cpp','hashtree.cpp','datagram.cpp','bins.cpp', 'transfer.cpp', 'compat/hirestimeofday.cpp', 'compat/util.cpp'] + +env = Environment() +if sys.platform == "win32": + # "MSVC works out of the box". Sure. + # Make sure scons finds cl.exe, etc. + env.Append ( ENV = { 'PATH' : os.environ['PATH'] } ) + + # Make sure scons finds std MSVC include files + if not 'INCLUDE' in os.environ: + print "p2tp: Please run scons in a Visual Studio Command Prompt" + sys.exit(-1) + + include = os.environ['INCLUDE'] + include += '..\\gtest-1.4.0\\include;' + include += '..\\glog-0.3.0\\src\\windows;' # Funky + include += '\\openssl\\include;' + + env.Append ( ENV = { 'INCLUDE' : include } ) + + # Other compiler flags + env.Append(CPPPATH=".") + if DEBUG: + env.Append(CXXFLAGS="/Zi /Yd /MTd") + env.Append(LINKFLAGS="/DEBUG") + + # Add simulated pread/write + source += ['compat/unixio.cpp'] + + # Set libs to link to + libs = ['libglog','ws2_32'] + if DEBUG: + libs += ['gtestd','libeay32MTd'] + else: + libs += ['gtest','libeay32'] + + # Update lib search path + libpath = os.environ['LIBPATH'] + if DEBUG: + libpath += '\\build\\gtest-1.4.0\\msvc\\gtest\\Debug;' + libpath += '\\build\\glog-0.3.0\\vsprojects\\libglog\\Debug;' + libpath += '\\openssl\\lib\\VC\\static;' + else: + libpath += '\\build\\gtest-1.4.0\\msvc\\gtest\\Release;' + libpath += '\\build\\glog-0.3.0\\vsprojects\\libglog\\Release;' + libpath += '\\openssl\\lib;' + # Somehow linker can't find uuid.lib + libpath += 'C:\\Program Files\\Microsoft SDKs\\Windows\\v6.0A\\Lib;' + +else: + # Enable the user defining external includes + if 'CPPPATH' in os.environ: + cpppath = os.environ['CPPPATH'] + else: + cpppath = "" + print "To use external libs, set CPPPATH environment variable to list of colon-separated include dirs" + env.Append(CPPPATH=".:"+cpppath) + env.Append(LINKFLAGS="--static") + + #if DEBUG: + # env.Append(CXXFLAGS="-g") + + # Set libs to link to + libs = ['stdc++','gtest','glog','pthread','crypto'] + if 'LIBPATH' in os.environ: + libpath = os.environ['LIBPATH'] + else: + libpath = "" + print "To use external libs, set LIBPATH environment variable to list of colon-separated lib dirs" -env.SharedLibrary ( - target='p2tp', - source = [ 'bin64.cpp','hashtree.cpp','datagram.cpp', - 'bins.cpp', 'transfer.cpp' ], - LIBS=['stdc++','gtest','glog','crypto'] ) +env.StaticLibrary ( + target= target, + source = source, + LIBS=libs, + LIBPATH=libpath ) +Export("env") +Export("libs") +Export("libpath") +Export("DEBUG") SConscript('tests/SConscript') diff --git a/bin.cpp b/bin.cpp index 187dde4..0fa7996 100644 --- a/bin.cpp +++ b/bin.cpp @@ -3,7 +3,7 @@ * serp++ * * Created by Victor Grishchenko on 3/6/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ diff --git a/bin.h b/bin.h index 3742b88..ed02494 100644 --- a/bin.h +++ b/bin.h @@ -3,34 +3,41 @@ * serp++ * * Created by Victor Grishchenko on 3/6/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ #ifndef BIN_H #define BIN_H #include -#include +#ifdef _MSC_VER + // To avoid complaints about std::max. Appears to work in VS2008 + #undef min + #undef max + #include "compat/stdint.h" +#else + #include +#endif #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)<>=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]]; @@ -48,67 +55,67 @@ struct bin { 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; @@ -122,50 +129,50 @@ struct bin { 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; @@ -173,11 +180,11 @@ struct bin { 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; @@ -188,15 +195,15 @@ struct bin { 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()); } @@ -205,21 +212,21 @@ struct bin { assert(layer()<=top.layer()); // TERRIBLE assert(top.layer()>=height); uint8_t rel_layer; - if (layer()+height>=top.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; } - + } ; diff --git a/bin64.cpp b/bin64.cpp index 599c4df..10c4859 100644 --- a/bin64.cpp +++ b/bin64.cpp @@ -3,7 +3,7 @@ * p2tp * * Created by Victor Grishchenko on 10/10/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ #include "bin64.h" diff --git a/bin64.h b/bin64.h index f6b2bf3..16279a9 100644 --- a/bin64.h +++ b/bin64.h @@ -1,8 +1,11 @@ #ifndef BIN64_H #define BIN64_H #include -#include - +#ifdef _MSC_VER + #include "compat/stdint.h" +#else + #include +#endif /** Numbering for (aligned) logarithmical bins. @@ -23,7 +26,7 @@ struct bin64_t { 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) : + bin64_t(uint8_t layer, uint64_t offset) : v( (offset<<(layer+1)) | ((1ULL<>27]; @@ -118,24 +121,24 @@ struct bin64_t { bin64_t left_foot () const { return bin64_t(0,base_offset()); } - + /** Whether layer is 0. */ bool is_base () const { return !(v & 1); } - + /** Depth-first in-order binary tree traversal. */ bin64_t next_dfsio (uint8_t floor); - + bin64_t width () const { return (tail_bits()+1)>>1; } - + /** The array must have 64 cells, as it is the max number of peaks possible +1 (and there are no reason to assume there will be less in any given case. */ static int peaks (uint64_t length, bin64_t* peaks) ; - + }; diff --git a/bins.cpp b/bins.cpp index c1c7436..f546982 100644 --- a/bins.cpp +++ b/bins.cpp @@ -3,7 +3,7 @@ * serp++ * * Created by Victor Grishchenko on 4/1/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ #include "bins.h" diff --git a/bins.h b/bins.h index a2540a5..e1d9130 100644 --- a/bins.h +++ b/bins.h @@ -3,7 +3,7 @@ * serp++ * * Created by Victor Grishchenko on 3/28/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ #ifndef BINS_H diff --git a/compat/hirestimeofday.cpp b/compat/hirestimeofday.cpp new file mode 100644 index 0000000..d98380f --- /dev/null +++ b/compat/hirestimeofday.cpp @@ -0,0 +1,157 @@ +/* + * Inspired by + * - http://msdn.microsoft.com/en-us/library/ms644904%28VS.85%29.aspx + * - Python-2.6.3/Modules/timemodule.c + */ + +#include +#include "compat/hirestimeofday.h" + +#ifndef _MSC_VER +#include +#endif + +namespace p2tp { + +HiResTimeOfDay* HiResTimeOfDay::_instance = 0; + +HiResTimeOfDay* HiResTimeOfDay::Instance() +{ + if (_instance == 0) + _instance = new HiResTimeOfDay(); + return _instance; +} + + +#ifdef _MSC_VER +#include +#include + + +HiResTimeOfDay::HiResTimeOfDay(void) +{ + frequency = getFrequency(); + epochstart = getFTime(); + epochcounter = getCounter(); +} + + +tint HiResTimeOfDay::getTimeUSec(void) +{ + LARGE_INTEGER currentcounter; + tint currentstart; + + currentstart = getFTime(); + currentcounter = getCounter(); + + if (currentcounter.QuadPart < epochcounter.QuadPart) + { + + // Wrap around detected, reestablish baseline + epochstart = currentstart; + epochcounter = currentcounter; + } + return epochstart + (1000000*(currentcounter.QuadPart-epochcounter.QuadPart))/frequency.QuadPart; +} + + +// Private +tint HiResTimeOfDay::getFTime() +{ + struct timeb t; + ftime(&t); + tint usec; + usec = t.time * 1000000; + usec += t.millitm * 1000; + return usec; +} + + + +LARGE_INTEGER HiResTimeOfDay::getFrequency(void) +{ + LARGE_INTEGER proc_freq; + + if (!::QueryPerformanceFrequency(&proc_freq)) + std::cerr << "HiResTimeOfDay: QueryPerformanceFrequency() failed"; + + return proc_freq; +} + +LARGE_INTEGER HiResTimeOfDay::getCounter() +{ + LARGE_INTEGER counter; + + DWORD_PTR oldmask = ::SetThreadAffinityMask(::GetCurrentThread(), 0); + if (!::QueryPerformanceCounter(&counter)) + std::cerr << "HiResTimeOfDay: QueryPerformanceCounter() failed"; + ::SetThreadAffinityMask(::GetCurrentThread(), oldmask); + + return counter; +} + +#else + +HiResTimeOfDay::HiResTimeOfDay(void) +{ +} + + +tint HiResTimeOfDay::getTimeUSec(void) +{ + struct timeval t; + gettimeofday(&t,NULL); + tint ret; + ret = t.tv_sec; + ret *= 1000000; + ret += t.tv_usec; + return ret; +} +#endif + + + + +// ARNOTODO: move to p2tp.cpp + +#ifdef _MSC_VER +static WSADATA _WSAData; +#endif + +void LibraryInit(void) +{ +#ifdef _MSC_VER + // win32 requires you to initialize the Winsock DLL with the desired + // specification version + WORD wVersionRequested; + wVersionRequested = MAKEWORD(2, 2); + WSAStartup(wVersionRequested, &_WSAData); +#endif +} + + +} // end of namespace + + + + +#ifdef TEST +#include + +using namespace p2tp; + +int main() +{ + HiResTimeOfDay *t = HiResTimeOfDay::Instance(); + for (int i=0; i<100; i++) + { + tint st = t->getTimeUSec(); + Sleep(1000); + tint et = t->getTimeUSec(); + tint diff = et - st; + std::cout << "diffxTime is " << diff << "\n"; + } + return 0; +} +#endif + diff --git a/compat/hirestimeofday.h b/compat/hirestimeofday.h new file mode 100644 index 0000000..623a9f3 --- /dev/null +++ b/compat/hirestimeofday.h @@ -0,0 +1,51 @@ +/* + * Written by Arno Bakker + * see LICENSE.txt for license information + * + * Singleton class to retrieve a time-of-day in UTC in usec in a platform- + * independent manner. + */ +#ifndef HIRESTIMEOFDAY_H +#define HIRESTIMEOFDAY_H + +#ifdef _MSC_VER +#include "compat/stdint.h" +#include +#else +#include +#endif + + +namespace p2tp { + +typedef int64_t tint; +#define TINT_SEC ((tint)1000000) +#define TINT_MSEC ((tint)1000) +#define TINT_uSEC ((tint)1) +#define TINT_NEVER ((tint)0x7fffffffffffffffLL) + + +class HiResTimeOfDay +{ +public: + HiResTimeOfDay(void); + tint getTimeUSec(void); + static HiResTimeOfDay* Instance(); + +private: +#ifdef _MSC_VER + tint epochstart; // in usec + LARGE_INTEGER epochcounter; + LARGE_INTEGER last; + LARGE_INTEGER frequency; + + tint HiResTimeOfDay::getFTime(); + LARGE_INTEGER getFrequency(void); + LARGE_INTEGER getCounter(void); +#endif + + static HiResTimeOfDay* _instance; +}; + +}; +#endif diff --git a/compat/stdint.h b/compat/stdint.h new file mode 100644 index 0000000..4586324 --- /dev/null +++ b/compat/stdint.h @@ -0,0 +1,18 @@ +/* + * Written by Arno Bakker + * see LICENSE.txt for license information + */ + +#ifndef STDINT_H_ +#define STDINT_H_ + +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; + +#endif /* STDINT_H_ */ diff --git a/compat/unixio.cpp b/compat/unixio.cpp new file mode 100644 index 0000000..1c369a6 --- /dev/null +++ b/compat/unixio.cpp @@ -0,0 +1,28 @@ +/* + * Written by Arno Bakker + * see LICENSE.txt for license information + */ + +#include "compat/unixio.h" +#include +#include +#include + +size_t pread(int fildes, void *buf, size_t nbyte, long offset) +{ + _lseek(fildes,offset,SEEK_SET); + return read(fildes,buf,nbyte); +} + +size_t pwrite(int fildes, const void *buf, size_t nbyte, long offset) +{ + _lseek(fildes,offset,SEEK_SET); + return write(fildes,buf,nbyte); +} + + +int inet_aton(const char *cp, struct in_addr *inp) +{ + inp->S_un.S_addr = inet_addr(cp); + return 1; +} diff --git a/compat/unixio.h b/compat/unixio.h new file mode 100644 index 0000000..e36a1f1 --- /dev/null +++ b/compat/unixio.h @@ -0,0 +1,25 @@ +/* + * Written by Arno Bakker + * see LICENSE.txt for license information + * + * Defines UNIX like I/O calls and parameters for Win32 + */ + +#ifndef UNIXIO_H_ +#define UNIXIO_H_ + +#define open(a,b,c) _open(a,b,c) +#define S_IRUSR _S_IREAD +#define S_IWUSR _S_IWRITE +#define S_IRGRP _S_IREAD +#define S_IROTH _S_IREAD +#define ftruncate(a, b) _chsize(a,b) + +size_t pread(int fildes, void *buf, size_t nbyte, long offset); +/** UNIX pread approximation. Does change file pointer. Is not thread-safe */ +size_t pwrite(int fildes, const void *buf, size_t nbyte, long offset); +/** UNIX pwrite approximation. Does change file pointer. Is not thread-safe */ + +int inet_aton(const char *cp, struct in_addr *inp); + +#endif /* UNIXIO_H_ */ diff --git a/compat/util.cpp b/compat/util.cpp new file mode 100644 index 0000000..c352c5c --- /dev/null +++ b/compat/util.cpp @@ -0,0 +1,37 @@ +/* + * Written by Arno Bakker + * see LICENSE.txt for license information + */ + +#include "util.h" +#include + +#ifdef _MSC_VER +#include +#include +#endif + +namespace p2tp +{ + +std::string gettmpdir(void) +{ +#ifdef _MSC_VER + DWORD result = ::GetTempPath(0, _T("")); + if (result == 0) + throw std::runtime_error("Could not get system temp path"); + + std::vector tempPath(result + 1); + result = ::GetTempPath(static_cast(tempPath.size()), &tempPath[0]); + if((result == 0) || (result >= tempPath.size())) + throw std::runtime_error("Could not get system temp path"); + + return std::string(tempPath.begin(), tempPath.begin() + static_cast(result)); +#else + return std::string("/tmp/"); +#endif +} + + +}; // namespace + diff --git a/compat/util.h b/compat/util.h new file mode 100644 index 0000000..b4e542f --- /dev/null +++ b/compat/util.h @@ -0,0 +1,27 @@ +/* + * util.h + * + * Created on: 20-Oct-2009 + * Author: arno + */ + +#ifndef UTIL_H_ +#define UTIL_H_ + +#include + +namespace p2tp +{ + std::string gettmpdir(void); + /** + * Return path of temporary directory. + * + * From http://msdn.microsoft.com/en-us/library/aa364992%28VS.85%29.aspx + * + * TODO: Unicode... (gets hairy with open() call on Linux. Win32 has _wopen) + */ + + +}; + +#endif /* UTIL_H_ */ diff --git a/datagram.cpp b/datagram.cpp index daccd9a..c218e66 100644 --- a/datagram.cpp +++ b/datagram.cpp @@ -3,10 +3,17 @@ * serp++ * * Created by Victor Grishchenko on 3/9/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ -#include +#include + +#ifdef _MSC_VER + #include + typedef int socklen_t; +#else + #include +#endif #include #include "datagram.h" @@ -16,7 +23,7 @@ tint Datagram::now = Datagram::Time(); uint32_t Datagram::Address::LOCALHOST = INADDR_LOOPBACK; int Datagram::Send () { - int r = sendto(sock,buf+offset,length-offset,0, + int r = sendto(sock,(const char *)buf+offset,length-offset,0, (struct sockaddr*)&(addr.addr),sizeof(struct sockaddr_in)); offset=0; length=0; @@ -27,17 +34,24 @@ int Datagram::Send () { int Datagram::Recv () { socklen_t addrlen = sizeof(struct sockaddr_in); offset = 0; - length = recvfrom (sock, buf, MAXDGRAMSZ, 0, + length = recvfrom (sock, (char *)buf, MAXDGRAMSZ, 0, (struct sockaddr*)&(addr), &addrlen); if (length<0) +#ifdef _MSC_VER + PLOG(ERROR)<<"on recv" << WSAGetLastError() << "\n"; +#else PLOG(ERROR)<<"on recv"; +#endif now = Time(); return length; } -int Datagram::Wait (int sockcnt, int* sockets, tint usec) { - LOG(INFO)<<"waiting for "<getTimeUSec(); //DLOG(INFO)<<"now is "< + +#ifdef _MSC_VER + #include "compat/stdint.h" + #include + #include "compat/unixio.h" +#else + typedef int SOCKET; + #include + #include + #include + #include + #include + #include +#endif #include #include -#include #include -#include -#include -#include -#include -//#include #include -#include #include #include #include "hashtree.h" +#include "compat/hirestimeofday.h" + namespace p2tp { -typedef int64_t tint; -#define TINT_SEC ((tint)1000000) -#define TINT_MSEC ((tint)1000) -#define TINT_uSEC ((tint)1) -#define TINT_NEVER ((tint)0x7fffffffffffffffLL) #define MAXDGRAMSZ 1400 +#ifndef _MSC_VER #define INVALID_SOCKET -1 - - +#endif + struct Datagram { - + struct Address { struct sockaddr_in addr; static uint32_t LOCALHOST; void init(uint32_t ipv4=0, uint16_t port=0) { - memset(&addr,0,sizeof(struct sockaddr_in)); + memset(&addr,0,sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(ipv4); @@ -59,35 +63,35 @@ struct Datagram { } Address(const struct sockaddr_in& address) : addr(address) {} operator sockaddr_in () const {return addr;} - bool operator == (const Address& b) { + bool operator == (const Address& b) { return addr.sin_family==b.addr.sin_family && - addr.sin_port==b.addr.sin_port && + addr.sin_port==b.addr.sin_port && addr.sin_addr.s_addr==b.addr.sin_addr.s_addr; } bool operator != (const Address& b) { return !(*this==b); } }; - + Address addr; - int sock; + SOCKET sock; int offset, length; uint8_t buf[MAXDGRAMSZ*2]; - - static int Bind(Address address); + + static SOCKET Bind(Address address); static void Close(int port); static tint Time(); - static int Wait (int sockcnt, int* sockets, tint usec=0); + static SOCKET Wait (int sockcnt, SOCKET* sockets, tint usec=0); static tint now; - - Datagram (int socket, const Address addr_) : addr(addr_), offset(0), + + Datagram (SOCKET socket, const Address addr_) : addr(addr_), offset(0), length(0), sock(socket) {} - Datagram (int socket) : 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()); } const uint8_t* operator * () const { return buf+offset; } - + int Push (const uint8_t* data, int l) { // scatter-gather one day int toc = l #include +#ifndef _MSC_VER #include +#endif #include #include #include @@ -158,7 +160,7 @@ HashTree::hashres_t HashTree::offer (bin pos, const Sha1Hash& hash) { return ACCEPT; } else return REJECT; - + } */ diff --git a/hashtree.h b/hashtree.h index a25e6af..fe6aac6 100644 --- a/hashtree.h +++ b/hashtree.h @@ -3,7 +3,7 @@ * serp++ * * Created by Victor Grishchenko on 3/6/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ #ifndef P2TP_SHA1_HASH_TREE_H diff --git a/p2tp.cpp b/p2tp.cpp index c1b4cc0..bbc7aa7 100644 --- a/p2tp.cpp +++ b/p2tp.cpp @@ -3,7 +3,7 @@ * serp++ * * Created by Victor Grishchenko on 3/6/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ @@ -32,7 +32,7 @@ int Channel::socket_count = 0; Channel::Channel (FileTransfer* file, int socket, struct sockaddr_in peer_addr) : - file_(file), peer(peer_addr), peer_channel_id(0), + file_(file), peer(peer_addr), peer_channel_id(0), socket_(socket) // FIXME { this->id = channels.size(); @@ -71,8 +71,8 @@ void p2tp::Shutdown (int sock_des) { } -void p2tp::Loop (tint till) { - Channel::Loop(till); +void p2tp::Loop (tint till) { + Channel::Loop(till); } @@ -122,6 +122,5 @@ size_t p2tp::SeqComplete (int fdes) { is mostly zeroed; intialization happens as conversation progresses - Note: + Note: */ - diff --git a/p2tp.h b/p2tp.h index 8623285..5fc296a 100644 --- a/p2tp.h +++ b/p2tp.h @@ -3,28 +3,28 @@ * serp++ * * Created by Victor Grishchenko on 3/6/09. - * Copyright 2009 Delft Technical University. All rights reserved. - * + * Copyright 2009 Delft University of Technology. All rights reserved. + * */ -/* +/* The P2TP protocol - + Messages - + 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 1K of data. - + 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 Practical value of "hints" is to avoid overlap, mostly. Hints might be lost in the network or ignored. @@ -33,24 +33,30 @@ Messages is considered to be ignored. As peers cant pick randomly kilobyte here and there, they send out "long hints" for non-base bins. - + 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 Peer exchange messages; reports all connected and disconected peers. Might has special meaning (as in the case with swarm supervisors). - + */ #ifndef P2TP_H #define P2TP_H + +#ifdef _MSC_VER +#include "compat/stdint.h" +#else #include +#endif #include #include +#include #include "bin64.h" #include "bins.h" #include "datagram.h" @@ -65,38 +71,38 @@ namespace p2tp { tintbin() : time(0), bin(bin64_t::NONE) {} tintbin(tint time_, bin64_t bin_) : time(time_), bin(bin_) {} }; - + typedef std::deque tbqueue; typedef std::deque binqueue; typedef Datagram::Address Address; - typedef enum { - P2TP_HANDSHAKE = 0, - P2TP_DATA = 1, - P2TP_ACK = 2, - P2TP_ACK_TS = 8, - P2TP_HINT = 3, - P2TP_HASH = 4, + typedef enum { + P2TP_HANDSHAKE = 0, + P2TP_DATA = 1, + P2TP_ACK = 2, + P2TP_ACK_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 { - + public: - + /** Open/submit/retrieve a file. */ FileTransfer(const char *file_name, const Sha1Hash& _root_hash=Sha1Hash::ZERO); - + /** Close everything. */ ~FileTransfer(); - + /** Offer a hash; returns true if it verified; false otherwise. Once it cannot be verified (no sibling or parent), the hash is remembered, while returning false. */ @@ -104,17 +110,17 @@ namespace p2tp { /** Offer data; the behavior is the same as with a hash: accept or remember or drop. Returns true => ACK is sent. */ bool OfferData (bin64_t bin, const uint8_t* data, size_t length); - + static FileTransfer* Find (const Sha1Hash& hash); - static FileTransfer* file (int fd) { - return fd files; - static const char* HASH_FILE_TEMPLATE; - static const char* PEAK_FILE_TEMPLATE; - + static std::string GetTempFilename(Sha1Hash& root_hash, int instance, std::string postfix); + /** file descriptor. */ int fd_; /** File size, as derived from the hashes. */ @@ -154,6 +159,9 @@ namespace p2tp { PiecePicker* picker_; /** File for keeping the Merkle hash tree. */ int hashfd_; +#ifdef _MSC_VER + HANDLE hashmaphandle_; +#endif /** Merkle hash tree: root */ Sha1Hash root_hash_; /** Merkle hash tree: peak hashes */ @@ -166,7 +174,7 @@ namespace p2tp { bool dry_run_; /** Error encountered */ char* error_; - + protected: void SetSize(size_t bytes); void Submit(); @@ -183,7 +191,6 @@ namespace p2tp { friend int Open (const char* filename, const Sha1Hash& hash) ; friend void Close (int fd) ; }; - class CongestionController { public: @@ -198,27 +205,27 @@ namespace p2tp { virtual void OnAckRcvd(const tintbin& tsack) = 0; virtual ~CongestionController() = 0; }; - + class PiecePicker { public: virtual bin64_t Pick (bins& from, uint8_t layer) = 0; virtual void Received (bin64_t b) = 0; virtual void Snubbed (bin64_t b) = 0; }; - + class PeerSelector { public: virtual void AddPeer (const Datagram::Address& addr, const Sha1Hash& root) = 0; virtual Datagram::Address GetPeer (const Sha1Hash& for_root) = 0; }; - + class DataStorer { public: DataStorer (const Sha1Hash& id, size_t size); virtual size_t ReadData (bin64_t pos,uint8_t** buf) = 0; virtual size_t WriteData (bin64_t pos, uint8_t* buf, size_t len) = 0; }; - + /** P2TP channel's "control block"; channels loosely correspond to TCP connections or FTP sessions; one channel is created for one file @@ -230,10 +237,10 @@ namespace p2tp { public: Channel (FileTransfer* file, int socket, struct sockaddr_in peer); ~Channel(); - + static void Recv (int socket); static void Loop (tint till); - + void Recv (Datagram& dgram); tint Send (); @@ -244,7 +251,6 @@ namespace p2tp { 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); @@ -255,18 +261,17 @@ namespace p2tp { const std::string id_string () const; /** A channel is "established" if had already sent and received packets. */ bool is_established () { return peer_channel_id && own_id_mentioned; } - + static int DecodeID(int scrambled); static int EncodeID(int unscrambled); static Channel* channel(int i) { return i channels; static int sockets[8]; static int socket_count; static tint last_tick; - + friend int Listen (Datagram::Address addr); friend void Shutdown (int sock_des); friend void AddPeer (Datagram::Address address, const Sha1Hash& root); }; - + /*************** The top-level API ****************/ /** Start listening a port. Returns socket descriptor. */ @@ -334,16 +339,21 @@ namespace p2tp { /** Returns size of the file in bytes, 0 if unknown. Might be rounded up to a kilobyte before the transmission is complete. */ size_t Size (int fdes); - /** Returns the amount of retrieved and verified data, in bytes. + /** Returns the amount of retrieved and verified data, in bytes. A 100% complete transmission has Size()==Complete(). */ size_t Complete (int fdes); /** Returns the number of bytes that are complete sequentially, starting from the beginning, till the first not-yet-retrieved packet. */ size_t SeqComplete (int fdes); - + //uint32_t Width (const tbinvec& v); -} + + void LibraryInit(void); + /** Must be called by any client using the library */ + + +} // namespace end #define RETLOG(str) { LOG(WARNING)< diff --git a/tests/SConscript b/tests/SConscript index 31cf098..f7f8d0f 100644 --- a/tests/SConscript +++ b/tests/SConscript @@ -1,58 +1,81 @@ -env = Environment(CPPPATH = '.',CXXFLAGS="-g") +import sys + +Import("DEBUG") +Import("env") +Import("libs") +Import("libpath") + +cpppath = env["CPPPATH"] +libs = ['p2tp'] + libs # order is important, crypto needs to be last + +if sys.platform == "win32": + cpppath = ".." + libpath += '..;' + if DEBUG: + env.Append(CXXFLAGS="/Zi /Yd /MTd") +else: + cpppath = cpppath + ':..' + libpath += ':..' + if DEBUG: + env.Append(CXXFLAGS="-g") + +print "tests: libpath is",libpath env.Program( target='binstest2', source=['binstest2.cpp'], - CPPPATH=['..'], - LIBS=['p2tp','stdc++','gtest','glog'], - LIBPATH='..' ) + CPPPATH=cpppath, + LIBS=libs, + LIBPATH=libpath ) env.Program( target='dgramtest', source=['dgramtest.cpp'], - CPPPATH=['..'], - LIBS=['p2tp','stdc++','gtest','glog'], - LIBPATH='..' ) + CPPPATH=cpppath, + LIBS=libs, + LIBPATH=libpath ) env.Program( target='hashtest', source=['hashtest.cpp'], - CPPPATH=['..'], - LIBS=['p2tp','stdc++','gtest','glog','crypto'], - LIBPATH='..' ) + CPPPATH=cpppath, + LIBS=libs, + LIBPATH=libpath ) env.Program( target='ledbattest', source=['ledbattest.cpp'], - CPPPATH=['..'], - LIBS=['p2tp','stdc++','gtest','glog','crypto'], - LIBPATH='..' ) + CPPPATH=cpppath, + LIBS=libs, + LIBPATH=libpath ) -env.Program( - target='ledbattest2', - source=['ledbattest2.cpp'], - CPPPATH=['..'], - LIBS=['p2tp','stdc++','gtest','glog','crypto'], - LIBPATH='..' ) + +if sys.platform != "win32": + # Arno: Needs getopt + env.Program( + target='ledbattest2', + source=['ledbattest2.cpp'], + CPPPATH=cpppath, + LIBS=libs, + LIBPATH=libpath ) env.Program( target='freemap', source=['freemap.cpp'], - CPPPATH=['..'], - LIBS=['p2tp','stdc++','gtest','glog'], - LIBPATH='..' ) + CPPPATH=cpppath, + LIBS=libs, + LIBPATH=libpath ) env.Program( target='bin64test', source=['bin64test.cpp'], - CPPPATH=['..'], - LIBS=['p2tp','gtest'], - LIBPATH='..' ) + CPPPATH=cpppath, + LIBS=libs, + LIBPATH=libpath ) env.Program( target='transfertest', source=['transfertest.cpp'], - CPPPATH=['..'], - LIBS=['p2tp','gtest'], - LIBPATH='..' ) - + CPPPATH=cpppath, + LIBS=libs, + LIBPATH=libpath ) diff --git a/tests/bin64test.cpp b/tests/bin64test.cpp index 7f3c44d..157c447 100644 --- a/tests/bin64test.cpp +++ b/tests/bin64test.cpp @@ -3,7 +3,7 @@ * bin++ * * Created by Victor Grishchenko on 3/9/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ #include "bin64.h" @@ -36,7 +36,7 @@ TEST(Bin64Test,Navigation) { } TEST(Bin64Test,Overflows) { - + /*EXPECT_EQ(bin64_t::NONE.parent(),bin64_t::NONE); EXPECT_EQ(bin64_t::NONE.left(),bin64_t::NONE); EXPECT_EQ(bin64_t::NONE.right(),bin64_t::NONE); @@ -46,7 +46,7 @@ TEST(Bin64Test,Overflows) { } TEST(Bin64Test, Advanced) { - + EXPECT_EQ(4,bin64_t(2,3).width()); EXPECT_FALSE(bin64_t(1,1234).is_base()); EXPECT_TRUE(bin64_t(0,12345).is_base()); @@ -57,7 +57,7 @@ TEST(Bin64Test, Advanced) { EXPECT_EQ(bin64_t(2,0),peaks[0]); EXPECT_EQ(bin64_t(1,2),peaks[1]); EXPECT_EQ(bin64_t(0,6),peaks[2]); - + } TEST(Bin64Test, Iteration) { @@ -85,8 +85,8 @@ TEST(Bin64Test, Bits) { } int main (int argc, char** argv) { - + testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); - + } diff --git a/tests/binstest.cpp b/tests/binstest.cpp index caa51b3..91eb1f6 100644 --- a/tests/binstest.cpp +++ b/tests/binstest.cpp @@ -3,7 +3,7 @@ * serp++ * * Created by Victor Grishchenko on 3/22/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ #include diff --git a/tests/binstest2.cpp b/tests/binstest2.cpp index 9d76467..a3fadfb 100755 --- a/tests/binstest2.cpp +++ b/tests/binstest2.cpp @@ -3,7 +3,7 @@ * serp++ * * Created by Victor Grishchenko on 3/22/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ #include diff --git a/tests/bintest.cpp b/tests/bintest.cpp index 7f6dadc..cb5aeee 100644 --- a/tests/bintest.cpp +++ b/tests/bintest.cpp @@ -3,7 +3,7 @@ * bin++ * * Created by Victor Grishchenko on 3/9/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ #include "bin.h" diff --git a/tests/congctrltest.cpp b/tests/congctrltest.cpp index 769fec2..cec343c 100644 --- a/tests/congctrltest.cpp +++ b/tests/congctrltest.cpp @@ -3,7 +3,7 @@ * p2tp * * Created by Victor Grishchenko on 7/13/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ #include diff --git a/tests/connecttest.cpp b/tests/connecttest.cpp index 9cecd7a..258ccd2 100644 --- a/tests/connecttest.cpp +++ b/tests/connecttest.cpp @@ -3,7 +3,7 @@ * serp++ * * Created by Victor Grishchenko on 3/19/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ diff --git a/tests/dgramtest.cpp b/tests/dgramtest.cpp index 87d4313..4a58d8b 100644 --- a/tests/dgramtest.cpp +++ b/tests/dgramtest.cpp @@ -3,18 +3,19 @@ * serp++ * * Created by Victor Grishchenko on 3/13/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ #include #include #include "datagram.h" +#include "p2tp.h" // Arno: for LibraryInit using namespace p2tp; -TEST(Datagram, BinaryTest) { - int socket = Datagram::Bind(7001); +TEST(Datagram, BinaryTest) { + SOCKET socket = Datagram::Bind(7001); ASSERT_TRUE(socket>0); struct sockaddr_in addr; addr.sin_family = AF_INET; @@ -39,9 +40,11 @@ TEST(Datagram, BinaryTest) { EXPECT_STREQ("74657874ababcdabcdef01000abcdefabcdeff",buf); int datalen = strlen(text)+1+2+4+8; ASSERT_EQ(datalen,d.Send()); - int socks[1] = {socket}; - ASSERT_EQ (socket, Datagram::Wait(1,socks)); - Datagram rcv(socket); + SOCKET socks[1] = {socket}; + // Arno: timeout 0 gives undeterministic behaviour on win32 + SOCKET waitsocket = Datagram::Wait(1,socks,1000000); + ASSERT_EQ(socket,waitsocket); + Datagram rcv(waitsocket); ASSERT_EQ(datalen,rcv.Recv()); char* rbuf; int pl = rcv.Pull((uint8_t**)&rbuf,strlen(text)); @@ -71,26 +74,29 @@ TEST(Datagram,TwoPortTest) { addr2.sin_family = AF_INET; addr2.sin_port = htons(10002); addr2.sin_addr.s_addr = htonl(INADDR_LOOPBACK);*/ - + Datagram send(sock1,Datagram::Address(10002)); send.Push32(1234); send.Send(); - - int socks[2] = {sock1,sock2}; - EXPECT_EQ(sock2,Datagram::Wait(2,socks)); + + SOCKET socks[2] = {sock1,sock2}; + // Arno: timeout 0 gives undeterministic behaviour on win32 + EXPECT_EQ(sock2,Datagram::Wait(2,socks,1000000)); Datagram recv(sock2); recv.Recv(); uint32_t test = recv.Pull32(); ASSERT_EQ(1234,test); - + Datagram::Close(sock1); Datagram::Close(sock2); } int main (int argc, char** argv) { - + + p2tp::LibraryInit(); + testing::InitGoogleTest(&argc, argv); google::InitGoogleLogging(argv[0]); return RUN_ALL_TESTS(); - + } diff --git a/tests/freemap.cpp b/tests/freemap.cpp index f98b33a..f368d12 100755 --- a/tests/freemap.cpp +++ b/tests/freemap.cpp @@ -3,7 +3,7 @@ * serp++ * * Created by Victor Grishchenko on 3/22/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ #include @@ -11,6 +11,12 @@ #include #include "bins.h" +#ifdef _MSC_VER + #define RANDOM rand +#else + #define RANDOM random +#endif + int bins_stripe_count (bins& b) { int stripe_count; uint64_t * stripes = b.get_stripes(stripe_count); @@ -19,7 +25,7 @@ int bins_stripe_count (bins& b) { } uint8_t rand_norm (uint8_t lim) { - long rnd = random() & ((1< diff --git a/tests/ledbattest.cpp b/tests/ledbattest.cpp index 3155b40..ee6302f 100644 --- a/tests/ledbattest.cpp +++ b/tests/ledbattest.cpp @@ -39,8 +39,8 @@ TEST(Datagram,LedbatTest) { tint last_sec = 0; int sec_ackd = 0; - int send_sock = Datagram::Bind(10001); // bind sending socket - int ack_sock = Datagram::Bind(10002); // bind receiving socket + SOCKET send_sock = Datagram::Bind(10001); // bind sending socket + SOCKET ack_sock = Datagram::Bind(10002); // bind receiving socket struct sockaddr_in send_to, ack_to; send_to.sin_family = AF_INET; send_to.sin_port = htons(10002); @@ -49,8 +49,8 @@ TEST(Datagram,LedbatTest) { ack_to.sin_port = htons(10001); ack_to.sin_addr.s_addr = htonl(INADDR_LOOPBACK); uint8_t* garbage = (uint8_t*) malloc(1024); - int socks[2] = {send_sock,ack_sock}; - int sock2read; + SOCKET socks[2] = {send_sock,ack_sock}; + SOCKET sock2read; tint wait_time = 100*TINT_MSEC; while (sock2read = Datagram::Wait(2,socks,wait_time)) { @@ -67,7 +67,7 @@ TEST(Datagram,LedbatTest) { fprintf(stderr,"%lli rcvd%i\n",now/TINT_SEC,seq); // TODO: peer cwnd !!! continue; - } + } if (sock2read==send_sock) { // process an acknowledgement Datagram ack(send_sock); ack.Recv(); @@ -168,6 +168,9 @@ TEST(Datagram,LedbatTest) { int main (int argc, char** argv) { printf("Warning: use the script to set up dummynet!\n"); + + p2tp::LibraryInit(); + testing::InitGoogleTest(&argc, argv); google::InitGoogleLogging(argv[0]); return RUN_ALL_TESTS(); diff --git a/tests/ledbattest2.cpp b/tests/ledbattest2.cpp index 235d956..0acded2 100644 --- a/tests/ledbattest2.cpp +++ b/tests/ledbattest2.cpp @@ -1,8 +1,13 @@ #include #include -#include -#include -#include +#ifdef _MSC_VER + #include "compat/stdint.h" + #include +#else + #include + #include + #include +#endif #include #include #include "datagram.h" @@ -74,7 +79,7 @@ TEST(Datagram,LedbatTest) { fprintf(stderr,"%lli rcvd%i\n",now/TINT_SEC,seq); // TODO: peer cwnd !!! continue; - } + } if (sock2read==send_sock) { // process an acknowledgement Datagram ack(send_sock); ack.Recv(); diff --git a/tests/rwtest.cpp b/tests/rwtest.cpp index 1c80845..0f77b1b 100644 --- a/tests/rwtest.cpp +++ b/tests/rwtest.cpp @@ -3,7 +3,7 @@ * serp++ * * Created by Victor Grishchenko on 3/19/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ diff --git a/tests/sbit2test.cpp b/tests/sbit2test.cpp index 4251d5a..8877773 100644 --- a/tests/sbit2test.cpp +++ b/tests/sbit2test.cpp @@ -3,7 +3,7 @@ * serp++ * * Created by Victor Grishchenko on 4/1/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ diff --git a/tests/sbittest.cpp b/tests/sbittest.cpp index c321ac9..f6d22bd 100644 --- a/tests/sbittest.cpp +++ b/tests/sbittest.cpp @@ -3,7 +3,7 @@ * serp++ * * Created by Victor Grishchenko on 3/9/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ #include "bin.h" diff --git a/tests/transfertest.cpp b/tests/transfertest.cpp index 7ae096c..e4c4b1b 100644 --- a/tests/transfertest.cpp +++ b/tests/transfertest.cpp @@ -3,11 +3,16 @@ * p2tp * * Created by Victor Grishchenko on 10/7/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ #include +#include #include "p2tp.h" +#include "compat/util.h" +#ifdef _MSC_VER +#include "compat/unixio.h" +#endif using namespace p2tp; @@ -29,7 +34,7 @@ TEST(TransferTest,TransferFile) { ROOT = Sha1Hash(ROOT,Sha1Hash::ZERO); //printf("m %lli %s\n",(uint64_t)pos.parent(),ROOT.hex().c_str()); } - + // submit a new file FileTransfer* seed = new FileTransfer(BTF); EXPECT_TRUE(A==seed->hash(0)); @@ -43,7 +48,7 @@ TEST(TransferTest,TransferFile) { EXPECT_EQ(5,seed->size_kilo()); EXPECT_EQ(4100,seed->complete()); EXPECT_EQ(4100,seed->seq_complete()); - + // retrieve it unlink("copy"); FileTransfer::instance = 1; @@ -84,7 +89,7 @@ TEST(TransferTest,TransferFile) { EXPECT_EQ(5,leech->size_kilo()); EXPECT_EQ(4100,leech->complete()); EXPECT_EQ(4100,leech->seq_complete()); - + } /* FIXME @@ -92,18 +97,26 @@ TEST(TransferTest,TransferFile) { */ int main (int argc, char** argv) { - - unlink("/tmp/.70196e6065a42835b1f08227ac3e2fb419cf78c8.0.hashes"); - unlink("/tmp/.70196e6065a42835b1f08227ac3e2fb419cf78c8.0.peaks"); - unlink("/tmp/.70196e6065a42835b1f08227ac3e2fb419cf78c8.1.hashes"); - unlink("/tmp/.70196e6065a42835b1f08227ac3e2fb419cf78c8.1.peaks"); - unlink("/tmp/.70196e6065a42835b1f08227ac3e2fb419cf78c8.2.hashes"); - unlink("/tmp/.70196e6065a42835b1f08227ac3e2fb419cf78c8.2.peaks"); - + + google::InitGoogleLogging(argv[0]); + + std::string tempdir = gettmpdir(); + unlink((tempdir + std::string(".70196e6065a42835b1f08227ac3e2fb419cf78c8.0.hashes")).c_str()); + unlink((tempdir + std::string(".70196e6065a42835b1f08227ac3e2fb419cf78c8.0.peaks")).c_str()); + unlink((tempdir + std::string(".70196e6065a42835b1f08227ac3e2fb419cf78c8.1.hashes")).c_str()); + unlink((tempdir + std::string(".70196e6065a42835b1f08227ac3e2fb419cf78c8.1.peaks")).c_str()); + unlink((tempdir + std::string(".70196e6065a42835b1f08227ac3e2fb419cf78c8.2.hashes")).c_str()); + unlink((tempdir + std::string(".70196e6065a42835b1f08227ac3e2fb419cf78c8.2.peaks")).c_str()); + unlink(BTF); unlink("copy"); - + int f = open(BTF,O_RDWR|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + if (f < 0) + { + PLOG(FATAL)<< "Error opening " << BTF << "\n"; + return -1; + } uint8_t buf[1024]; memset(buf,'A',1024); A = Sha1Hash(buf,1024); @@ -121,9 +134,9 @@ int main (int argc, char** argv) { E = Sha1Hash(buf,4); write(f,buf,4); close(f); - + testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); - + return ret; } diff --git a/transfer.cpp b/transfer.cpp index 59900e5..bb6cdb7 100644 --- a/transfer.cpp +++ b/transfer.cpp @@ -3,18 +3,24 @@ * p2tp * * Created by Victor Grishchenko on 10/6/09. - * Copyright 2009 Delft Technical University. All rights reserved. + * Copyright 2009 Delft University of Technology. All rights reserved. * */ +#ifdef _MSC_VER +#include "compat/unixio.h" +#else #include +#endif #include +#include +#include #include "p2tp.h" +#include "compat/util.h" using namespace p2tp; std::vector FileTransfer::files(20); -const char* FileTransfer::HASH_FILE_TEMPLATE = "/tmp/.%s.%i.hashes"; -const char* FileTransfer::PEAK_FILE_TEMPLATE = "/tmp/.%s.%i.peaks"; + int FileTransfer::instance = 0; #define BINHASHSIZE (sizeof(bin64_t)+sizeof(Sha1Hash)) @@ -23,7 +29,7 @@ int FileTransfer::instance = 0; // FIXME: separate Bootstrap() and Download(), then Size(), Progress(), SeqProgress() FileTransfer::FileTransfer (const char* filename, const Sha1Hash& _root_hash) : - root_hash_(_root_hash), fd_(0), hashfd_(0), dry_run_(false), + root_hash_(_root_hash), fd_(0), hashfd_(0), dry_run_(false), peak_count_(0), hashes_(NULL), error_(NULL), size_(0), sizek_(0), complete_(0), completek_(0), seq_complete_(0) { @@ -42,9 +48,8 @@ FileTransfer::FileTransfer (const char* filename, const Sha1Hash& _root_hash) : void FileTransfer::LoadPeaks () { - char file_name[1024]; - sprintf(file_name,PEAK_FILE_TEMPLATE,root_hash().hex().c_str(),instance); - int peakfd = open(file_name,O_RDONLY); + std::string file_name = GetTempFilename(root_hash_,instance,std::string(".peaks")); + int peakfd = open(file_name.c_str(),O_RDONLY,0); if (peakfd<0) return; bin64_t peak; @@ -79,9 +84,8 @@ void FileTransfer::RecoverProgress () { void FileTransfer::SavePeaks () { - char file_name[1024]; - sprintf(file_name,PEAK_FILE_TEMPLATE,root_hash().hex().c_str(),instance); - int peakfd = open(file_name,O_RDWR|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + std::string file_name = GetTempFilename(root_hash_,instance,std::string(".peaks")); + int peakfd = open(file_name.c_str(),O_RDWR|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); for(int i=0; i>10) + ((size_&1023) ? 1 : 0); - - char file_name[1024]; + struct stat st; fstat(fd_, &st); if (st.st_size!=bytes) if (ftruncate(fd_, bytes)) return; // remain in the 0-state // mmap the hash file into memory - sprintf(file_name,HASH_FILE_TEMPLATE,root_hash().hex().c_str(),instance); - hashfd_ = open(file_name,O_RDWR|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); - size_t expected_size = Sha1Hash::SIZE * sizek_ * 2; + std::string file_name = GetTempFilename(root_hash_,instance,std::string(".hashes")); + hashfd_ = open(file_name.c_str(),O_RDWR|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + size_t expected_size_ = Sha1Hash::SIZE * sizek_ * 2; struct stat hash_file_st; fstat(hashfd_, &hash_file_st); - if ( hash_file_st.st_size != expected_size ) - ftruncate(hashfd_, expected_size); - hashes_ = (Sha1Hash*) mmap (NULL, expected_size, PROT_READ|PROT_WRITE, + if ( hash_file_st.st_size != expected_size_ ) + ftruncate(hashfd_, expected_size_); +#ifdef _MSC_VER + HANDLE hashhandle = (HANDLE)_get_osfhandle(hashfd_); + hashmaphandle_ = CreateFileMapping(hashhandle, + NULL, + PAGE_READWRITE, + 0, + 0, + NULL); + if (hashmaphandle_ != NULL) + { + hashes_ = (Sha1Hash*)MapViewOfFile(hashmaphandle_, + FILE_MAP_WRITE, + 0, + 0, + 0); + + } + if (hashmaphandle_ == NULL || hashes_ == NULL) +#else + hashes_ = (Sha1Hash*) mmap (NULL, expected_size, PROT_READ|PROT_WRITE, MAP_SHARED, hashfd_, 0); - if (hashes_==MAP_FAILED) { + if (hashes_==MAP_FAILED) +#endif + { hashes_ = NULL; size_ = sizek_ = complete_ = completek_ = seq_complete_ = 0; error_ = strerror(errno); // FIXME dprintf() @@ -120,7 +144,7 @@ void FileTransfer::SetSize (size_t bytes) { // peaks/root must be already set } for(int i=0; i=last_peak.layer() || + if ( pos.layer()>=last_peak.layer() || pos.base_offset()!=last_peak.base_offset()+last_peak.width() ) peak_count_ = 0; } @@ -265,14 +289,20 @@ void FileTransfer::OfferPeak (bin64_t pos, const Sha1Hash& hash) { } -FileTransfer::~FileTransfer () { +FileTransfer::~FileTransfer () +{ +#ifdef _MSC_VER + UnmapViewOfFile(hashes_); + CloseHandle(hashmaphandle_); +#else munmap(hashes_,sizek_*2*Sha1Hash::SIZE); close(hashfd_); close(fd_); files[fd_] = NULL; +#endif } - + FileTransfer* FileTransfer::Find (const Sha1Hash& root_hash) { for(int i=0; iroot_hash_==root_hash) @@ -281,6 +311,18 @@ FileTransfer* FileTransfer::Find (const Sha1Hash& root_hash) { } + +std::string FileTransfer::GetTempFilename(Sha1Hash& root_hash, int instance, std::string postfix) +{ + std::string tempfile = gettmpdir(); + std::stringstream ss; + ss << instance; + tempfile += std::string(".") + root_hash.hex() + std::string(".") + ss.str() + postfix; + return tempfile; +} + + + int p2tp::Open (const char* filename, const Sha1Hash& hash) { FileTransfer* ft = new FileTransfer(filename, hash); int fdes = ft->file_descriptor(); @@ -306,7 +348,7 @@ int p2tp::Open (const char* filename, const Sha1Hash& hash) { break; x = x.left(); } - + if (x.layer()==10) { if (recheck_data) { uint8_t data[1024]; @@ -319,16 +361,16 @@ int p2tp::Open (const char* filename, const Sha1Hash& hash) { ack_out->set(x,bins::FILLED); } } - + while (x.is_right() && x!=peaks[i]) x = x.parent(); x = x.sibling(); } while (x!=end); } - - - - + + + + // open file if ( hash_file_st.st_size < (sizeof(bin64_t)+Sha1Hash::SIZE)*64 ) return; @@ -354,6 +396,6 @@ int p2tp::Open (const char* filename, const Sha1Hash& hash) { } if (!size) return; - - + + */