Merge branch 'master' of git@github.com:gritzko/swift
[swift-upb.git] / transfer.cpp
1 /*
2  *  transfer.cpp
3  *  some transfer-scope code
4  *
5  *  Created by Victor Grishchenko on 10/6/09.
6  *  Copyright 2009 Delft University of Technology. All rights reserved.
7  *
8  */
9 #ifdef _WIN32
10 #include "compat.h"
11 #else
12 #include <sys/mman.h>
13 #endif
14 #include <errno.h>
15 #include <string>
16 #include <sstream>
17 #include "p2tp.h"
18 #include "compat/util.h"
19
20 #include "ext/seq_picker.cpp" // FIXME FIXME FIXME FIXME 
21
22 using namespace p2tp;
23
24 std::vector<FileTransfer*> FileTransfer::files(20);
25
26 #define BINHASHSIZE (sizeof(bin64_t)+sizeof(Sha1Hash))
27
28 // FIXME: separate Bootstrap() and Download(), then Size(), Progress(), SeqProgress()
29
30 FileTransfer::FileTransfer (const char* filename, const Sha1Hash& _root_hash) :
31     file_(filename,_root_hash), hs_in_offset_(0)
32 {
33     if (files.size()<fd()+1)
34         files.resize(fd()+1);
35     files[fd()] = this;
36     picker_ = new SeqPiecePicker(this);
37     picker_->Randomize(rand()&63);
38     init_time_ = Datagram::Time();
39 }
40
41
42 void    Channel::CloseTransfer (FileTransfer* trans) {
43     for(int i=0; i<Channel::channels.size(); i++) 
44         if (Channel::channels[i] && Channel::channels[i]->transfer_==trans) 
45             delete Channel::channels[i];
46 }
47
48
49 FileTransfer::~FileTransfer ()
50 {
51     Channel::CloseTransfer(this);
52     files[fd()] = NULL;
53 }
54
55
56 FileTransfer* FileTransfer::Find (const Sha1Hash& root_hash) {
57     for(int i=0; i<files.size(); i++)
58         if (files[i] && files[i]->root_hash()==root_hash)
59             return files[i];
60     return NULL;
61 }
62
63
64 void            FileTransfer::OnPexIn (const Address& addr) {
65     for(int i=0; i<hs_in_.size(); i++) {
66         Channel* c = Channel::channel(hs_in_[i]);
67         if (c && c->transfer().fd()==this->fd() && c->peer()==addr)
68             return; // already connected
69     }
70     if (hs_in_.size()<20) {
71         new Channel(this,Channel::default_socket(),addr);
72     } else {
73         pex_in_.push_back(addr);
74         if (pex_in_.size()>1000)
75             pex_in_.pop_front();
76     }
77 }
78
79
80 int        FileTransfer::RevealChannel (int& pex_out_) { // FIXME brainfuck
81     pex_out_ -= hs_in_offset_;
82     if (pex_out_<0)
83         pex_out_ = 0;
84     while (pex_out_<hs_in_.size()) {
85         Channel* c = Channel::channel(hs_in_[pex_out_]);
86         if (c && c->transfer().fd()==this->fd()) {
87             if (c->is_established()) {
88                 pex_out_ += hs_in_offset_ + 1;
89                 return c->id();
90             } else
91                 pex_out_++;
92         } else {
93             hs_in_[pex_out_] = hs_in_[0];
94             hs_in_.pop_front();
95             hs_in_offset_++;
96         }
97     }
98     pex_out_ += hs_in_offset_;
99     return -1;
100 }
101