From: Victor Grishchenko Date: Wed, 16 Dec 2009 15:06:53 +0000 (+0100) Subject: cured several connection stall bugs X-Git-Url: http://p2p-next.cs.pub.ro/gitweb/?a=commitdiff_plain;h=7898817a60ff9fce27884e7c7ae7b81176f22cf5;p=swift-upb.git cured several connection stall bugs --- diff --git a/BUGS b/BUGS index 12d3b41..28b97ba 100644 --- a/BUGS +++ b/BUGS @@ -42,4 +42,10 @@ v whether sending is limited by cwnd or app * actually: whether packets are ACKed faster than sent * uproot DATA NONE: complicates and deceives - * r735 goes to github + * r735 goes to github; r741 + * receiver is swapping => strange behavior + v on high losses cwnd goes to silly fractions => slows down recovery + * code the pingpong<->keepalive<->slowstart transition + * empty datagram hammering (see at linode) + * make a testkit!!! + * never back from keepalive syndrome (because of underhashing) diff --git a/ChangeLog b/ChangeLog old mode 100644 new mode 100755 diff --git a/bins.cpp b/bins.cpp index 3c4ca6e..ee5fbf8 100644 --- a/bins.cpp +++ b/bins.cpp @@ -353,6 +353,8 @@ void bins::remove (bins& b) { bin64_t bins::cover(bin64_t val) { + if (val==bin64_t::NONE) + return val; iterator i(this,val,false); while (i.pos!=val && !i.solid()) i.towards(val); diff --git a/doc/cloud4.jpg b/doc/cloud4.jpg deleted file mode 100644 index 1164ec5..0000000 Binary files a/doc/cloud4.jpg and /dev/null differ diff --git a/doc/index.html b/doc/index.html index eec7d96..c034b08 100644 --- a/doc/index.html +++ b/doc/index.html @@ -32,7 +32,7 @@ wise people say, the Internet was initially built for remotely connecting scientists to expensive supercomputers (whose computing power was comparable to modern cell phones). Thus, they supported the abstraction - of conversation. Currently, the Internet is mostly used for disseminating + of conversation. Currently, the Internet is mostly used for disseminating content to the masses, which mismatch definitely creates some problems.

The swift protocol is a content-centric multiparty transport @@ -278,10 +278,12 @@

-

Contacts&feedback

+

Contacts&feedback

mail us

subscribe to a mailing list

+ +
\ No newline at end of file diff --git a/doc/style.css b/doc/style.css index aec68ea..1295156 100644 --- a/doc/style.css +++ b/doc/style.css @@ -1,10 +1,5 @@ body { - background: #fefeff url("cloud4.jpg") fixed no-repeat; - #background-size: 100%; # - #-moz-background-size: 100% 100%; /* Gecko 1.9.2 (Firefox 3.6) */ - #-o-background-size: 100% 100%; /* Opera 9.5 */ - #-webkit-background-size: 100% 100%; /* Safari 3.0 */ - #-khtml-background-size: 100% 100%; /* Konqueror 3.5.4 */ + background: white no-repeat fixed; color: black; } @@ -17,12 +12,12 @@ p { } body > div { - width: 60%; + width: 60em; margin: auto; margin-top: 64px; margin-bottom: 64px; #background: #d0e0ff; - background: rgba(208,224,255,0.8); + background: rgba(208,224,255,0.9); padding-top: 16px; padding-bottom: 16px; } diff --git a/p2tp.cpp b/p2tp.cpp index 66984fd..ee42009 100644 --- a/p2tp.cpp +++ b/p2tp.cpp @@ -28,6 +28,7 @@ using namespace p2tp; p2tp::tint Channel::last_tick = 0; int Channel::MAX_REORDERING = 4; +bool Channel::SELF_CONN_OK = false; p2tp::tint Channel::TIMEOUT = TINT_SEC*60; std::vector Channel::channels(1); SOCKET Channel::sockets[8] = {0,0,0,0,0,0,0,0}; @@ -46,7 +47,9 @@ Channel::Channel (FileTransfer* transfer, int socket, Address peer_addr) : data_in_dbl_(bin64_t::NONE), hint_out_size_(0), cwnd_(1), send_interval_(TINT_SEC), send_control_(PING_PONG_CONTROL), sent_since_recv_(0), ack_rcvd_recent_(0), ack_not_rcvd_recent_(0), - last_loss_time_(0), owd_min_bin_(0), owd_min_bin_start_(NOW), owd_cur_bin_(0) + last_loss_time_(0), owd_min_bin_(0), owd_min_bin_start_(NOW), + owd_cur_bin_(0), dgrams_sent_(0), dgrams_rcvd_(0), + data_in_(TINT_NEVER,bin64_t::NONE) { if (peer_==Address()) peer_ = tracker; diff --git a/p2tp.h b/p2tp.h index 95354aa..3d7f88c 100644 --- a/p2tp.h +++ b/p2tp.h @@ -269,6 +269,7 @@ namespace p2tp { static tint LEDBAT_TARGET; static float LEDBAT_GAIN; static tint LEDBAT_DELAY_BIN; + static bool SELF_CONN_OK; const std::string id_string () const; /** A channel is "established" if had already sent and received packets. */ @@ -346,6 +347,9 @@ namespace p2tp { tint owd_min_bin_start_; tint owd_current_[4]; int owd_cur_bin_; + /** Stats */ + int dgrams_sent_; + int dgrams_rcvd_; int PeerBPS() const { return TINT_SEC / dip_avg_ * 1024; diff --git a/send_control.cpp b/send_control.cpp index 75c43c4..7111279 100644 --- a/send_control.cpp +++ b/send_control.cpp @@ -33,7 +33,8 @@ tint Channel::NextSendTime () { } tint Channel::SwitchSendControl (int control_mode) { - dprintf("%s #%u sendctrl %i->%i\n",tintstr(),id,send_control_,control_mode); + dprintf("%s #%u sendctrl switch %s->%s\n",tintstr(),id, + SEND_CONTROL_MODES[send_control_],SEND_CONTROL_MODES[control_mode]); switch (control_mode) { case KEEP_ALIVE_CONTROL: send_interval_ = max(TINT_SEC/10,rtt_avg_); @@ -45,6 +46,7 @@ tint Channel::SwitchSendControl (int control_mode) { cwnd_ = 1; break; case SLOW_START_CONTROL: + cwnd_ = 1; break; case AIMD_CONTROL: break; @@ -57,14 +59,12 @@ tint Channel::SwitchSendControl (int control_mode) { return NextSendTime(); } -// TODO: transitions, consistently -// TODO: may send data tint Channel::KeepAliveNextSendTime () { if (sent_since_recv_>=3 && last_recv_time_MAX_SEND_INTERVAL) @@ -73,33 +73,33 @@ tint Channel::KeepAliveNextSendTime () { } tint Channel::PingPongNextSendTime () { // FIXME INFINITE LOOP - if (last_recv_time_ < last_send_time_-TINT_SEC*3) { - // FIXME keepalive <-> pingpong (peers, transition) - } // last_data_out_time_ < last_send_time_ - TINT_SEC... - if (false) + if (dgrams_sent_>=10) return SwitchSendControl(KEEP_ALIVE_CONTROL); if (ack_rcvd_recent_) return SwitchSendControl(SLOW_START_CONTROL); - if (data_in_.bin!=bin64_t::NONE) + if (data_in_.time!=TINT_NEVER) return NOW; if (last_recv_time_>last_send_time_) return NOW; - else if (last_send_time_) - return last_send_time_ + ack_timeout(); - else + if (!last_send_time_) return NOW; + return last_send_time_ + ack_timeout(); // timeout } tint Channel::CwndRateNextSendTime () { - if (data_in_.bin!=bin64_t::NONE) + if (data_in_.time!=TINT_NEVER) return NOW; // TODO: delayed ACKs + //if (last_recv_time_std::max(rtt_avg_,TINT_SEC)*4) + return SwitchSendControl(KEEP_ALIVE_CONTROL); if (data_out_.size()NOW-TINT_SEC || data_out_.empty())) - return bin64_t::NONE; // once in a while, empty data is sent just to check rtt FIXME + 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 (tosend!=bin64_t::NONE) { // hashes - 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 (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 @@ -204,17 +205,15 @@ bin64_t Channel::AddData (Datagram& dgram) { dgram.Push8(P2TP_DATA); dgram.Push32(tosend.to32()); - if (tosend!=bin64_t::NONE) { // data - 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); + 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); @@ -232,20 +231,20 @@ void Channel::AddTs (Datagram& dgram) { void Channel::AddAck (Datagram& dgram) { - if (data_in_dbl_!=bin64_t::NONE) { + if (data_in_dbl_!=bin64_t::NONE) { // TODO: do redundancy better dgram.Push8(P2TP_ACK); - dgram.Push32(data_in_dbl_); + dgram.Push32(data_in_dbl_.to32()); data_in_dbl_=bin64_t::NONE; } - if (data_in_.bin!=bin64_t::NONE) { + if (data_in_.time!=TINT_NEVER) { // TODO: ACK NONE for corrupted data AddTs(dgram); bin64_t pos = file().ack_out().cover(data_in_.bin); dgram.Push8(P2TP_ACK); - dgram.Push32(pos); + dgram.Push32(pos.to32()); //dgram.Push64(data_in_.time); ack_out_.set(pos); dprintf("%s #%u +ack %s %s\n",tintstr(),id,pos.str(),tintstr(data_in_.time)); - data_in_ = tintbin(0,bin64_t::NONE); + data_in_ = tintbin(TINT_NEVER,bin64_t::NONE); if (pos.layer()>2) data_in_dbl_ = pos; } @@ -256,7 +255,7 @@ void Channel::AddAck (Datagram& dgram) { ack = file().ack_out().cover(ack); ack_out_.set(ack); dgram.Push8(P2TP_ACK); - dgram.Push32(ack); + dgram.Push32(ack.to32()); dprintf("%s #%u +ack %s\n",tintstr(),id,ack.str()); } } @@ -265,6 +264,7 @@ void Channel::AddAck (Datagram& dgram) { void Channel::Recv (Datagram& dgram) { dprintf("%s #%u recvd %i\n",tintstr(),id,dgram.size()+4); peer_send_time_ = 0; // has scope of 1 datagram + dgrams_rcvd_++; if (last_send_time_ && rtt_avg_==TINT_SEC && dev_avg_==0) { rtt_avg_ = NOW - last_send_time_; dev_avg_ = rtt_avg_; @@ -328,9 +328,10 @@ bin64_t Channel::OnData (Datagram& dgram) { int length = dgram.Pull(&data,1024); bool ok = (pos==bin64_t::NONE) || file().OfferData(pos, (char*)data, length) ; dprintf("%s #%u %cdata %s\n",tintstr(),id,ok?'-':'!',pos.str()); + data_in_ = tintbin(NOW,bin64_t::NONE); if (!ok) return bin64_t::NONE; - data_in_ = tintbin(NOW,pos); + data_in_.bin = pos; if (pos!=bin64_t::NONE) { if (last_data_in_time_) { tint dip = NOW - last_data_in_time_; @@ -400,7 +401,9 @@ void Channel::CleanDataOut (bin64_t ackd_pos) { // TODO: isn't it too long? void Channel::OnAck (Datagram& dgram) { bin64_t ackd_pos = dgram.Pull32(); - if (ackd_pos!=bin64_t::NONE && file().size() && ackd_pos.base_offset()>=file().packet_size()) { + if (ackd_pos==bin64_t::NONE) + return; // likely, brocken packet / insufficient hashes + if (file().size() && ackd_pos.base_offset()>=file().packet_size()) { eprintf("invalid ack: %s\n",ackd_pos.str()); return; } @@ -428,6 +431,14 @@ void Channel::OnHint (Datagram& dgram) { void Channel::OnHandshake (Datagram& dgram) { peer_channel_id_ = dgram.Pull32(); dprintf("%s #%u -hs %x\n",tintstr(),id,peer_channel_id_); + // self-connection check + if (!SELF_CONN_OK) { + uint32_t try_id = DecodeID(peer_channel_id_); + if (channel(try_id) && !channel(try_id)->peer_channel_id_) { + delete this; + return; + } + } // FUTURE: channel forking } @@ -550,9 +561,10 @@ void Channel::Loop (tint howlong) { void Channel::Reschedule () { next_send_time_ = NextSendTime(); - if (next_send_time_!=TINT_NEVER) + if (next_send_time_!=TINT_NEVER) { + assert(next_send_time_>10) + (st.st_size%1024?1:0) ; + Channel::SELF_CONN_OK = true; int sock1 = p2tp::Listen(7001); ASSERT_TRUE(sock1>=0);