amended the draft
[swift-upb.git] / channel.cpp
1 /*
2  *  swift.cpp
3  *  serp++
4  *
5  *  Created by Victor Grishchenko on 3/6/09.
6  *  Copyright 2009 Delft University of Technology. All rights reserved.
7  *
8  */
9
10 #include <stdlib.h>
11 #include <fcntl.h>
12 #ifndef _WIN32
13 #include <sys/select.h>
14 #include <sys/time.h>
15 #include <sys/mman.h>
16 #include <arpa/inet.h>
17 #include <unistd.h>
18 #endif
19 #include <sys/stat.h>
20 #include <string.h>
21
22 //#include <glog/logging.h>
23 #include "swift.h"
24 #include "datagram.h"
25
26 using namespace std;
27 using namespace swift;
28
29 swift::tint Channel::last_tick = 0;
30 int Channel::MAX_REORDERING = 4;
31 bool Channel::SELF_CONN_OK = false;
32 swift::tint Channel::TIMEOUT = TINT_SEC*60;
33 std::vector<Channel*> Channel::channels(1);
34 socket_callbacks_t Channel::sockets[SWFT_MAX_SOCK_OPEN] = {};
35 int Channel::socket_count = 0;
36 Address Channel::tracker;
37 tbheap Channel::send_queue;
38 FILE* Channel::debug_file = NULL;
39 #include "ext/simple_selector.cpp"
40 PeerSelector* Channel::peer_selector = new SimpleSelector();
41
42 Channel::Channel    (FileTransfer* transfer, int socket, Address peer_addr) :
43     transfer_(transfer), peer_(peer_addr), peer_channel_id_(0), pex_out_(0),
44     socket_(socket==INVALID_SOCKET?sockets[0].sock:socket), // FIXME
45     data_out_cap_(bin64_t::ALL), last_data_out_time_(0), last_data_in_time_(0),
46     own_id_mentioned_(false), next_send_time_(0), last_send_time_(0),
47     last_recv_time_(0), rtt_avg_(TINT_SEC), dev_avg_(0), dip_avg_(TINT_SEC),
48     data_in_dbl_(bin64_t::NONE), hint_out_size_(0),
49     cwnd_(1), send_interval_(TINT_SEC), send_control_(PING_PONG_CONTROL),
50     sent_since_recv_(0), ack_rcvd_recent_(0), ack_not_rcvd_recent_(0),
51     last_loss_time_(0), owd_min_bin_(0), owd_min_bin_start_(NOW), 
52     owd_cur_bin_(0), dgrams_sent_(0), dgrams_rcvd_(0), 
53     data_in_(TINT_NEVER,bin64_t::NONE)
54 {
55     if (peer_==Address())
56         peer_ = tracker;
57     this->id_ = channels.size();
58     channels.push_back(this);
59     transfer_->hs_in_.push_back(id_);
60     for(int i=0; i<4; i++) {
61         owd_min_bins_[i] = TINT_NEVER;
62         owd_current_[i] = TINT_NEVER;
63     }
64     Reschedule();
65     dprintf("%s #%u init %s\n",tintstr(),id_,peer_.str());
66 }
67
68
69 Channel::~Channel () {
70     channels[id_] = NULL;
71 }
72
73
74 void     swift::SetTracker(const Address& tracker) {
75     Channel::tracker = tracker;
76 }
77
78
79 int Channel::DecodeID(int scrambled) {
80     return scrambled ^ (int)Datagram::start;
81 }
82 int Channel::EncodeID(int unscrambled) {
83     return unscrambled ^ (int)Datagram::start;
84 }
85
86
87 int     swift::Listen (Address addr) {
88     int sock = Datagram::Bind(addr);
89     if (sock!=INVALID_SOCKET) {
90         socket_callbacks_t cb(sock);
91         cb.may_read = &Channel::RecvDatagram;
92         Channel::sockets[Channel::socket_count++] = cb;
93     }
94     return sock;
95 }
96
97
98 void    swift::Shutdown (int sock_des) {
99     for(int i=0; i<Channel::socket_count; i++)
100         if (sock_des==-1 || Channel::sockets[i].sock==sock_des) {
101             Datagram::Close(Channel::sockets[i].sock);
102             Channel::sockets[i] = Channel::sockets[--Channel::socket_count];
103         }
104 }
105
106
107 void    swift::Loop (tint till) {
108     Channel::Loop(till);
109 }
110
111
112 bool    swift::Listen3rdPartySocket (socket_callbacks_t cb) {
113     int i=0;
114     while (i<Channel::socket_count && Channel::sockets[i].sock!=cb.sock) i++;
115     if (i==Channel::socket_count)
116         if (i==SWFT_MAX_SOCK_OPEN)
117             return false;
118         else
119             Channel::socket_count++;
120     Channel::sockets[i]=cb;
121     if (!cb.may_read && !cb.may_write && !cb.on_error)
122         Channel::sockets[i] = Channel::sockets[--Channel::socket_count];
123     return true;
124 }
125
126
127 int      swift::Open (const char* filename, const Sha1Hash& hash) {
128     FileTransfer* ft = new FileTransfer(filename, hash);
129     if (ft && ft->file().file_descriptor()) {
130
131         /*if (FileTransfer::files.size()<fdes)  // FIXME duplication
132             FileTransfer::files.resize(fdes);
133         FileTransfer::files[fdes] = ft;*/
134
135         // initiate tracker connections
136         if (Channel::tracker!=Address())
137             new Channel(ft);
138
139         return ft->file().file_descriptor();
140     } else {
141         if (ft)
142             delete ft;
143         return -1;
144     }
145 }
146
147
148 void    swift::Close (int fd) {
149     if (fd<FileTransfer::files.size() && FileTransfer::files[fd])
150         delete FileTransfer::files[fd];
151 }
152
153
154 void    swift::AddPeer (Address address, const Sha1Hash& root) {
155     Channel::peer_selector->AddPeer(address,root);
156 }
157
158
159 uint64_t  swift::Size (int fdes) {
160     if (FileTransfer::files.size()>fdes && FileTransfer::files[fdes])
161         return FileTransfer::files[fdes]->file().size();
162     else
163         return 0;
164 }
165
166
167 bool  swift::IsComplete (int fdes) {
168     if (FileTransfer::files.size()>fdes && FileTransfer::files[fdes])
169         return FileTransfer::files[fdes]->file().is_complete();
170     else
171         return 0;
172 }
173
174
175 uint64_t  swift::Complete (int fdes) {
176     if (FileTransfer::files.size()>fdes && FileTransfer::files[fdes])
177         return FileTransfer::files[fdes]->file().complete();
178     else
179         return 0;
180 }
181
182
183 uint64_t  swift::SeqComplete (int fdes) {
184     if (FileTransfer::files.size()>fdes && FileTransfer::files[fdes])
185         return FileTransfer::files[fdes]->file().seq_complete();
186     else
187         return 0;
188 }
189
190
191 const Sha1Hash& swift::RootMerkleHash (int file) {
192     FileTransfer* trans = FileTransfer::file(file);
193     if (!trans)
194         return Sha1Hash::ZERO;
195     return trans->file().root_hash();
196 }
197
198
199 /**    <h2> swift handshake </h2>
200  Basic rules:
201  <ul>
202  <li>    to send a datagram, a channel must be created
203  (channels are cheap and easily recycled)
204  <li>    a datagram must contain either the receiving
205  channel id (scrambled) or the root hash
206  </ul>
207  <b>Note:</b>
208  */