#ifndef BIN_H
#define BIN_H
#include <assert.h>
-#ifdef _WIN32
+#ifdef _MSC_VER
// To avoid complaints about std::max. Appears to work in VS2008
#undef min
#undef max
#ifndef BIN64_H
#define BIN64_H
#include <assert.h>
-#ifdef _WIN32
+#ifdef _MSC_VER
#include "compat/stdint.h"
#else
#include <stdint.h>
else
return right();
}
-
+
bin64_t twisted (uint64_t mask) const {
return bin64_t( v ^ ((mask<<1)&~tail_bits()) );
}
#include "compat.h"
#include <sys/stat.h>
#include <stdio.h>
-#include <unistd.h>
+#include <assert.h>
#ifdef _WIN32
-#include <windows.h>
#include <Tchar.h>
#include <io.h>
-#include <winsock2.h>
#include <sys/timeb.h>
+#include "compat/hirestimeofday.h"
#else
+#include <unistd.h>
#include <sys/time.h>
#endif
namespace p2tp {
+#ifdef _WIN32
+static HANDLE map_handles[1024];
+#endif
+
size_t file_size (int fd) {
struct stat st;
fstat(fd, &st);
#ifdef _WIN32
int e = WSAGetLastError();
if (e)
- fprintf(stderr,"network error #%i\n",e);
+ fprintf(stderr,"network error #%i\n",e);
#endif
}
#else
HANDLE fhandle = (HANDLE)_get_osfhandle(fd);
assert(fd<1024);
- static HANDLE map_handles[1024];
- maphandle = CreateFileMapping( fhandle,
+ HANDLE maphandle = CreateFileMapping( fhandle,
NULL,
PAGE_READWRITE,
0,
if (maphandle == NULL)
return NULL;
map_handles[fd] = maphandle;
-
+
mapping = MapViewOfFile ( maphandle,
FILE_MAP_WRITE,
0,
0,
0 );
-
+
return mapping;
#endif
}
CloseHandle(map_handles[fd]);
#endif
}
-
+
#ifdef _WIN32
-
+
size_t pread(int fildes, void *buf, size_t nbyte, long offset)
{
_lseek(fildes,offset,SEEK_SET);
return 1;
}
-#endif
-
-tint usec_time () {
+tint usec_time(void)
+{
+ HiResTimeOfDay* tod = HiResTimeOfDay::Instance();
+ return tod->getTimeUSec();
+}
+
+
+#else
+
+tint usec_time(void)
+{
struct timeval t;
gettimeofday(&t,NULL);
tint ret;
ret *= 1000000;
ret += t.tv_usec;
return ret;
-}
-
+}
+
+#endif
+
}
*/
#ifndef P2TP_COMPAT_H
#define P2TP_COMPAT_H
-#ifndef _WIN32
+
+#ifdef _MSC_VER
+#include "compat/stdint.h"
+#else
+#include <stdint.h>
+#endif
+#ifdef _WIN32
+#include <winsock2.h>
+#include <sys/stat.h>
+#else
#include <sys/mman.h>
#endif
#include <fcntl.h>
#define S_IROTH _S_IREAD
#endif
+namespace p2tp {
+
typedef int64_t tint;
+#define TINT_HOUR ((tint)1000000*60*60)
+#define TINT_MIN ((tint)1000000*60)
#define TINT_SEC ((tint)1000000)
#define TINT_MSEC ((tint)1000)
#define TINT_uSEC ((tint)1)
#define TINT_NEVER ((tint)0x7fffffffffffffffLL)
-namespace p2tp {
size_t file_size (int fd);
int file_resize (int fd, size_t new_size);
-void* memory_map (int fd, size_t size=0);
+void* memory_map (int fd, size_t size=0);
void memory_unmap (int fd, void*, size_t size);
void print_error (const char* msg);
-
+
#ifdef _WIN32
-
+
/** UNIX pread approximation. Does change file pointer. Is not thread-safe */
size_t pread(int fildes, void *buf, size_t nbyte, long offset);
-
+
/** UNIX pwrite approximation. Does change file pointer. Is not thread-safe */
size_t pwrite(int fildes, const void *buf, size_t nbyte, long offset);
-
+
int inet_aton(const char *cp, struct in_addr *inp);
#endif
-
+
tint usec_time ();
-
+
};
#endif
#ifndef HIRESTIMEOFDAY_H\r
#define HIRESTIMEOFDAY_H\r
\r
-#ifdef _WIN32\r
+#ifdef _MSC_VER\r
#include "compat/stdint.h"\r
-#include <windows.h>\r
#else\r
#include <stdint.h>\r
#endif\r
-\r
+#ifdef _WIN32\r
+#include <windows.h>\r
+#endif\r
\r
namespace p2tp {\r
\r
#ifndef DATAGRAM_H
#define DATAGRAM_H
-#ifdef _WIN32
+#ifdef _MSC_VER
#include "compat/stdint.h"
- #include <winsock2.h>
- #include "compat/unixio.h"
#else
- typedef int SOCKET;
#include <stdint.h>
+#endif
+#ifdef _WIN32
+ #include <winsock2.h>
+ #include "compat.h"
+#else
+ typedef int SOCKET;
+
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string>
#include "hashtree.h"
-#include "compat/hirestimeofday.h"
#include "compat/util.h"
namespace p2tp {
-typedef int64_t tint;
-#define TINT_HOUR ((tint)1000000*60*60)
-#define TINT_MIN ((tint)1000000*60)
-#define TINT_SEC ((tint)1000000)
-#define TINT_MSEC ((tint)1000)
-#define TINT_uSEC ((tint)1)
-#define TINT_NEVER ((tint)0x7fffffffffffffffLL)
#define MAXDGRAMSZ 2800
#ifndef _WIN32
#define INVALID_SOCKET -1
#endif
-
+
struct Address {
struct sockaddr_in addr;
static uint32_t LOCALHOST;
memset(&addr,0,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
}
- Address() {
+ Address() {
clear();
}
Address(const char* ip, uint16_t port) {
uint32_t ipv4 () const { return ntohl(addr.sin_addr.s_addr); }
uint16_t port () const { return ntohs(addr.sin_port); }
operator sockaddr_in () const {return addr;}
- bool operator == (const Address& b) const {
+ bool operator == (const Address& b) const {
return addr.sin_family==b.addr.sin_family &&
addr.sin_port==b.addr.sin_port &&
addr.sin_addr.s_addr==b.addr.sin_addr.s_addr;
}
bool operator != (const Address& b) const { return !(*this==b); }
};
-
-
+
+
struct Datagram {
Address addr;
#define dprintf(...) printf(__VA_ARGS__)
#define eprintf(...) fprintf(stderr,__VA_ARGS__)
//#define dprintf(...) {}
-
+
}
#endif
Import("DEBUG")
Import("env")
+Import("libs")
Import("libpath")
cpppath = env["CPPPATH"]
-libs = ['p2tp']
+libs = ['p2tp'] + libs # order is important, crypto needs to be last
if sys.platform == "win32":
cpppath = ".."
int main (int argn, char** args) {
-
+
if (argn<2) {
fprintf(stderr,"Usage: %s file_name\n",args[0]);
return 1;
}
p2tp::HashTree* ht = new p2tp::HashTree(args[1]);
-
+
printf("SHA1 Merkle tree root hash: %s\n",ht->root_hash().hex().c_str());
-
+
}
*
*/
#include "p2tp.h"
+#include <time.h>
using namespace p2tp;
/** P2TP downloader. Params: root hash, filename, tracker ip/port, own ip/port */
int main (int argn, char** args) {
-
+
srand(time(NULL));
FileTransfer::instance = rand();
-
+
if (argn<4) {
fprintf(stderr,"parameters: root_hash filename tracker_ip:port [own_ip:port]\n");
return -1;
fprintf(stderr,"Sha1 hash format: hex, 40 symbols\n");
return -2;
}
-
+
+ p2tp::LibraryInit();
+
char* filename = args[2];
-
+
Address tracker(args[3]), bindaddr;
-
+
if (tracker==Address()) {
fprintf(stderr,"Tracker address format: [1.2.3.4:]12345\n");
return -2;
}
- if (argn>=5)
+ if (argn>=5)
bindaddr = Address(args[4]);
else
- bindaddr = Address(INADDR_ANY,rand()%10000+7000);
-
+ bindaddr = Address((uint32_t)INADDR_ANY,rand()%10000+7000);
+
assert(0<p2tp::Listen(bindaddr));
-
+
p2tp::SetTracker(tracker);
-
+
int file = p2tp::Open(filename,root_hash);
printf("Downloading %s\n",root_hash.hex().c_str());
-
+
while (!p2tp::IsComplete(file)) {
p2tp::Loop(TINT_SEC);
printf("done %lli of %lli (seq %lli) %lli dgram %lli bytes up, %lli dgram %lli bytes down\n",
Datagram::dgrams_up, Datagram::bytes_up,
Datagram::dgrams_down, Datagram::bytes_down );
}
-
+
p2tp::Close(file);
-
+
p2tp::Shutdown();
-
+
}
/** P2TP seeder. Params: filename, own ip/port, tracker ip/port */
int main (int argn, char** args) {
-
+
if (argn<3) {
fprintf(stderr,"parameters: filename own_ip/port [tracker_ip/port]\n");
return -1;
}
-
+
+ p2tp::LibraryInit();
+
char* filename = args[1];
-
+
if (argn>=4) {
Address tracker(args[3]);
p2tp::SetTracker(tracker);
}
Address bindaddr(args[2]);
-
+
if (bindaddr==Address()) {
fprintf(stderr,"Bind address format: [1.2.3.4:]12345\n");
return -2;
}
-
+
assert(0<p2tp::Listen(bindaddr));
printf("seeder bound to %s\n",bindaddr.str().c_str());
-
+
int file = p2tp::Open(filename);
printf("seeding %s %s\n",filename,RootMerkleHash(file).hex().c_str());
-
+
while (true) {
p2tp::Loop(TINT_SEC*60);
printf("%lli dgram %lli bytes up, %lli dgram %lli bytes down\n",
Datagram::dgrams_up, Datagram::bytes_up,
Datagram::dgrams_down, Datagram::bytes_down );
}
-
+
p2tp::Close(file);
-
+
p2tp::Shutdown();
-
+
}
#include "sha1.h"
#include <string.h>
#include <stdlib.h>
+#include <io.h>
#include <fcntl.h>
#include "compat.h"
}
root_hash_ = DeriveRoot();
-
+
}
return false;
for(int i=0; i<peak_count_; i++)
sizek_ += peaks_[i].width();
-
+
// bingo, we now know the file size (rounded up to a KByte)
-
+
size_ = sizek_<<10;
completek_ = complete_ = 0;
sizek_ = (size_>>10) + ((size_&1023) ? 1 : 0);
-
+
size_t cur_size = file_size(fd_);
if ( cur_size<=(sizek_-1)<<10 || cur_size>sizek_<<10 )
if (file_resize(fd_, size_)) {
size_=0; // remain in the 0-state
return false;
}
-
+
// mmap the hash file into memory
size_t expected_size = sizeof(Sha1Hash)*sizek_*2;
if ( file_size(hash_fd_) != expected_size )
file_resize (hash_fd_, expected_size);
-
+
hashes_ = (Sha1Hash*) memory_map(hash_fd_,expected_size);
if (!hashes_) {
size_ = sizek_ = complete_ = completek_ = 0;
print_error("mmap failed");
return false;
}
-
+
for(int i=0; i<peak_count_; i++)
hashes_[peaks_[i]] = peak_hashes_[i];
return true;
if (!OfferHash(pos, Sha1Hash(data,length)))
return false;
-
+
//printf("g %lli %s\n",(uint64_t)pos,hash.hex().c_str());
ack_out_.set(pos,bins::FILLED);
pwrite(fd_,data,length,pos.base_offset()<<10);
#include <stdlib.h>
#include <fcntl.h>
+#ifndef _WIN32
#include <sys/select.h>
-#include <sys/stat.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <arpa/inet.h>
-#include <string.h>
#include <unistd.h>
+#endif
+#include <sys/stat.h>
+#include <string.h>
+
//#include <glog/logging.h>
#include "p2tp.h"
#include "datagram.h"
int Channel::MAX_REORDERING = 4;
p2tp::tint Channel::TIMEOUT = TINT_SEC*60;
std::vector<Channel*> Channel::channels(1);
-int Channel::sockets[8] = {0,0,0,0,0,0,0,0};
+SOCKET Channel::sockets[8] = {0,0,0,0,0,0,0,0};
int Channel::socket_count = 0;
Address Channel::tracker;
tbqueue Channel::send_queue;
FileTransfer* ft = new FileTransfer(filename, hash);
int fdes = ft->file().file_descriptor();
if (fdes>0) {
-
+
/*if (FileTransfer::files.size()<fdes) // FIXME duplication
FileTransfer::files.resize(fdes);
FileTransfer::files[fdes] = ft;*/
-
+
// initiate tracker connections
if (Channel::tracker!=Address())
new Channel(ft);
-
+
return fdes;
} else {
delete ft;
#ifndef P2TP_H
#define P2TP_H
-#ifdef _WIN32
+#ifdef _MSC_VER
#include "compat/stdint.h"
#else
#include <stdint.h>
P2TP_PEX_RM = 6,
P2TP_MESSAGE_COUNT = 7
} messageid_t;
-
+
class PiecePicker;
class CongestionController;
class PeerSelector;
//bin64_t RevealAck (uint64_t& offset);
/** Rotating queue read for channels of this transmission. */
int RevealChannel (int& i);
-
+
static FileTransfer* Find (const Sha1Hash& hash);
static FileTransfer* file (int fd) {
return fd<files.size() ? files[fd] : NULL;
static std::vector<FileTransfer*> files;
HashTree file_;
-
+
/** Piece picker strategy. */
PiecePicker* picker_;
-
+
/** Channels working for this transfer. */
binqueue hs_in_;
int hs_in_offset_;
std::deque<Address> pex_in_;
-
+
/** Messages we are accepting. */
uint64_t cap_out_;
friend void Close (int fd) ;
};
-
+
#include "ext/send_control.h"
-
+
class PiecePicker {
public:
virtual void Received (bin64_t b) = 0;
};
-
+
class PeerSelector {
public:
virtual void AddPeer (const Address& addr, const Sha1Hash& root) = 0;
virtual Address GetPeer (const Sha1Hash& for_root) = 0;
};
-
+
class DataStorer {
public:
DataStorer (const Sha1Hash& id, size_t size);
FileTransfer& transfer() { return *transfer_; }
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) {
tint next_send_time_;
tint peer_send_time_;
static tbqueue send_queue;
-
+
void RequeueSend (tint next_time);
int PeerBPS() const {
return TINT_SEC / dip_avg_ * 1024;
static int MAX_REORDERING;
static tint TIMEOUT;
- static int sockets[8];
+ static SOCKET sockets[8];
static int socket_count;
static tint last_tick;
friend void AddPeer (Address address, const Sha1Hash& root);
friend void SetTracker(const Address& tracker);
friend int Open (const char*, const Sha1Hash&) ; // FIXME
-
+
friend class FileTransfer; // FIXME!!!
friend class SendController; // FIXME!!!
};
root hash is zero, the peer might be talked to regarding any transmission
(likely, a tracker, cache or an archive). */
void AddPeer (Address address, const Sha1Hash& root=Sha1Hash::ZERO);
-
+
void SetTracker(const Address& tracker);
-
+
/** Returns size of the file in bytes, 0 if unknown. Might be rounded up to a kilobyte
before the transmission is complete. */
uint64_t Size (int fdes);
/* this is only to get definitions for memcpy(), ntohl() and htonl() */
//#include "../git-compat-util.h"
+#ifdef _WIN32
+#include <winsock2.h>
+#else
#include <arpa/inet.h>
+#endif
#include <string.h>
#include "sha1.h"
#include <gtest/gtest.h>
//#include <glog/logging.h>
#include "p2tp.h"
+#include <time.h>
+
using namespace p2tp;
TEST(P2TP,CwndTest) {
srand ( time(NULL) );
-
+
unlink("doc/sofi-copy.jpg");
struct stat st;
ASSERT_EQ(0,stat("doc/sofi.jpg", &st));
int size = st.st_size;//, sizek = (st.st_size>>10) + (st.st_size%1024?1:0) ;
-
+
int sock1 = p2tp::Listen(7001);
ASSERT_TRUE(sock1>=0);
-
+
int file = p2tp::Open("doc/sofi.jpg");
FileTransfer* fileobj = FileTransfer::file(file);
FileTransfer::instance++;
-
+
p2tp::SetTracker(Address("127.0.0.1",7001));
-
+
int copy = p2tp::Open("doc/sofi-copy.jpg",fileobj->root_hash());
-
+
p2tp::Loop(TINT_SEC);
-
+
int count = 0;
while (p2tp::SeqComplete(copy)!=size && count++<600)
p2tp::Loop(TINT_SEC);
ASSERT_EQ(size,p2tp::SeqComplete(copy));
-
+
p2tp::Close(file);
p2tp::Close(copy);
int main (int argc, char** argv) {
-
+
+ p2tp::LibraryInit();
testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
-
+
}
TEST(Sha1HashTest,SubmitTest) {
- FILE* f123 = fopen("123","w+");
+ FILE* f123 = fopen("123","wb+");
fprintf(f123, "123\n");
fclose(f123);
HashTree ht123("123");
int main (int argc, char** argv) {
//bin::init();
-
+
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
-
+
}
*
*/
#ifdef _WIN32
-#include "compat/unixio.h"
+#include "compat.h"
#else
#include <sys/mman.h>
#endif