add .gitignore
[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 #include <errno.h>
10 #include <string>
11 #include <sstream>
12 #include "swift.h"
13
14 #include "ext/seq_picker.cpp" // FIXME FIXME FIXME FIXME 
15
16 using namespace swift;
17
18 std::vector<FileTransfer*> FileTransfer::files(20);
19
20 #define BINHASHSIZE (sizeof(bin64_t)+sizeof(Sha1Hash))
21
22 // FIXME: separate Bootstrap() and Download(), then Size(), Progress(), SeqProgress()
23
24 FileTransfer::FileTransfer (const char* filename, const Sha1Hash& _root_hash) :
25     file_(filename,_root_hash), hs_in_offset_(0), cb_installed(0)
26 {
27     if (files.size()<fd()+1)
28         files.resize(fd()+1);
29     files[fd()] = this;
30     picker_ = new SeqPiecePicker(this);
31     picker_->Randomize(rand()&63);
32     init_time_ = Datagram::Time();
33 }
34
35
36 void    Channel::CloseTransfer (FileTransfer* trans) {
37     for(int i=0; i<Channel::channels.size(); i++) 
38         if (Channel::channels[i] && Channel::channels[i]->transfer_==trans) 
39             delete Channel::channels[i];
40 }
41
42
43 void swift::AddProgressCallback (int transfer,ProgressCallback cb,uint8_t agg) {
44     FileTransfer* trans = FileTransfer::file(transfer);
45     if (!trans)
46         return;
47     trans->cb_agg[trans->cb_installed] = agg;
48     trans->callbacks[trans->cb_installed] = cb;
49     trans->cb_installed++;
50 }
51
52
53 void swift::ExternallyRetrieved (int transfer,bin64_t piece) {
54     FileTransfer* trans = FileTransfer::file(transfer);
55     if (!trans)
56         return;
57     trans->ack_out().set(piece); // that easy
58 }
59
60
61 void swift::RemoveProgressCallback (int transfer, ProgressCallback cb) {
62     FileTransfer* trans = FileTransfer::file(transfer);
63     if (!trans)
64         return;
65     for(int i=0; i<trans->cb_installed; i++)
66         if (trans->callbacks[i]==cb)
67             trans->callbacks[i]=trans->callbacks[--trans->cb_installed];
68 }
69
70
71 FileTransfer::~FileTransfer ()
72 {
73     Channel::CloseTransfer(this);
74     files[fd()] = NULL;
75     delete picker_;
76 }
77
78
79 FileTransfer* FileTransfer::Find (const Sha1Hash& root_hash) {
80     for(int i=0; i<files.size(); i++)
81         if (files[i] && files[i]->root_hash()==root_hash)
82             return files[i];
83     return NULL;
84 }
85
86
87 int       swift:: Find (Sha1Hash hash) {
88     FileTransfer* t = FileTransfer::Find(hash);
89     if (t)
90         return t->fd();
91     return -1;
92 }
93
94
95
96 void            FileTransfer::OnPexIn (const Address& addr) {
97     for(int i=0; i<hs_in_.size(); i++) {
98         Channel* c = Channel::channel(hs_in_[i]);
99         if (c && c->transfer().fd()==this->fd() && c->peer()==addr)
100             return; // already connected
101     }
102     if (hs_in_.size()<20) {
103         new Channel(this,Datagram::default_socket(),addr);
104     } else {
105         pex_in_.push_back(addr);
106         if (pex_in_.size()>1000)
107             pex_in_.pop_front();
108     }
109 }
110
111
112 int        FileTransfer::RevealChannel (int& pex_out_) { // FIXME brainfuck
113     pex_out_ -= hs_in_offset_;
114     if (pex_out_<0)
115         pex_out_ = 0;
116     while (pex_out_<hs_in_.size()) {
117         Channel* c = Channel::channel(hs_in_[pex_out_]);
118         if (c && c->transfer().fd()==this->fd()) {
119             if (c->is_established()) {
120                 pex_out_ += hs_in_offset_ + 1;
121                 return c->id();
122             } else
123                 pex_out_++;
124         } else {
125             hs_in_[pex_out_] = hs_in_[0];
126             hs_in_.pop_front();
127             hs_in_offset_++;
128         }
129     }
130     pex_out_ += hs_in_offset_;
131     return -1;
132 }
133