void Channel::AddHandshake (Datagram& dgram) { if (!peer_channel_id_) { // initiating dgram.Push8(SWIFT_HASH); dgram.Push32(bin64_t::ALL32); dgram.PushHash(file().root_hash()); dprintf("%s #%u +hash ALL %s\n", tintstr(),id_,file().root_hash().hex().c_str()); } dgram.Push8(SWIFT_HANDSHAKE); int encoded = EncodeID(id_); dgram.Push32(encoded); dprintf("%s #%u +hs %x\n",tintstr(),id_,encoded); have_out_.clear(); AddHave(dgram); }
void Channel::AddHint (Datagram& dgram) { tint plan_for = max(TINT_SEC,rtt_avg_*4); tint timed_out = NOW - plan_for*2; while ( !hint_out_.empty() && hint_out_.front().time < timed_out ) { hint_out_size_ -= hint_out_.front().bin.width(); hint_out_.pop_front(); } int plan_pck = max ( (tint)1, plan_for / dip_avg_ ); if ( hint_out_size_ < plan_pck ) { int diff = plan_pck - hint_out_size_; // TODO: aggregate bin64_t hint = transfer().picker().Pick(ack_in_,diff,NOW+plan_for*2); if (hint!=bin64_t::NONE) { dgram.Push8(SWIFT_HINT); dgram.Push32(hint); dprintf("%s #%u +hint %s [%lli]\n",tintstr(),id_,hint.str(),hint_out_size_); hint_out_.push_back(hint); hint_out_size_ += hint.width(); } else dprintf("%s #%u Xhint\n",tintstr(),id_); } }
void Channel::AddHave (Datagram& dgram) { if (data_in_dbl_!=bin64_t::NONE) { // TODO: do redundancy better dgram.Push8(SWIFT_HAVE); dgram.Push32(data_in_dbl_.to32()); data_in_dbl_=bin64_t::NONE; } for(int count=0; count<4; count++) { bin64_t ack = file().ack_out().find_filtered // FIXME: do rotating queue (have_out_, bin64_t::ALL, binmap_t::FILLED); if (ack==bin64_t::NONE) break; ack = file().ack_out().cover(ack); have_out_.set(ack); dgram.Push8(SWIFT_HAVE); dgram.Push32(ack.to32()); dprintf("%s #%u +have %s\n",tintstr(),id_,ack.str()); } }
void Channel::AddPeakHashes (Datagram& dgram) { for(int i=0; i<file().peak_count(); i++) { bin64_t peak = file().peak(i); dgram.Push8(SWIFT_HASH); dgram.Push32((uint32_t)peak); dgram.PushHash(file().peak_hash(i)); dprintf("%s #%u +phash %s\n",tintstr(),id_,peak.str()); } }
void Channel::AddUncleHashes (Datagram& dgram, bin64_t pos) { bin64_t peak = file().peak_for(pos); while (pos!=peak && ((NOW&3)==3 || !data_out_cap_.within(pos.parent())) && ack_in_.get(pos.parent())==binmap_t::EMPTY ) { bin64_t uncle = pos.sibling(); dgram.Push8(SWIFT_HASH); dgram.Push32((uint32_t)uncle); dgram.PushHash( file().hash(uncle) ); dprintf("%s #%u +hash %s\n",tintstr(),id_,uncle.str()); pos = pos.parent(); } }
bin64_t Channel::AddData (Datagram& dgram) { if (!file().size()) // know nothing return bin64_t::NONE; bin64_t tosend = bin64_t::NONE; tint luft = send_interval_>>4; // may wake up a bit earlier if (data_out_.size()<cwnd_ && last_data_out_time_+send_interval_<=NOW+luft) { tosend = DequeueHint(); if (tosend==bin64_t::NONE) { dprintf("%s #%u sendctrl no idea what to send\n",tintstr(),id_); if (send_control_!=KEEP_ALIVE_CONTROL) SwitchSendControl(KEEP_ALIVE_CONTROL); } } else dprintf("%s #%u sendctrl wait cwnd %f data_out %i next %s\n", tintstr(),id_,cwnd_,data_out_.size(),tintstr(last_data_out_time_+NOW-send_interval_)); if (tosend==bin64_t::NONE)// && (last_data_out_time_>NOW-TINT_SEC || data_out_.empty())) return bin64_t::NONE; // once in a while, empty data is sent just to check rtt FIXED if (ack_in_.is_empty() && file().size()) AddPeakHashes(dgram); AddUncleHashes(dgram,tosend); if (!ack_in_.is_empty()) // TODO: cwnd_>1 data_out_cap_ = tosend; if (dgram.size()>254) { dgram.Send(); // kind of fragmentation dgram.Push32(peer_channel_id_); } dgram.Push8(SWIFT_DATA); dgram.Push32(tosend.to32()); uint8_t buf[1024]; size_t r = pread(file().file_descriptor(),buf,1024,tosend.base_offset()<<10); // TODO: corrupted data, retries, caching if (r<0) { print_error("error on reading"); return bin64_t::NONE; } assert(dgram.space()>=r+4+1); dgram.Push(buf,r); last_data_out_time_ = NOW; data_out_.push_back(tosend); dprintf("%s #%u +data %s\n",tintstr(),id_,tosend.str()); return tosend; }
void Channel::AddAck (Datagram& dgram) { if (data_in_==tintbin()) return; dgram.Push8(SWIFT_ACK); dgram.Push32(data_in_.bin.to32()); // FIXME not cover dgram.Push64(data_in_.time); // FIXME 32 have_out_.set(data_in_.bin); dprintf("%s #%u +ack %s %s\n", tintstr(),id_,data_in_.bin.str(),tintstr(data_in_.time)); if (data_in_.bin.layer()>2) data_in_dbl_ = data_in_.bin; data_in_ = tintbin(); }