<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,3 +1,13 @@
+Version 0.61
+
+     BitTorrent:
+      * Delay writing 'piece request' results.
+        Bitflu used to respond to piece-requests ASAP. This caused some ugly
+        'buffer overrun' messages to appear if the remote client did ignore
+        the 'reqq' value sent during handshake.
+        Bitflu now has an internal buffer for all piece request and only writes
+        a response if the buffer won't get 'overflowed' by this.
+
 Version 0.60 (Released: 20081009)
      Cron:
       * Added version check: Bitflu checks if your version is up-to-date and sends you</diff>
      <filename>ChangeLog.txt</filename>
    </modified>
    <modified>
      <diff>@@ -790,6 +790,11 @@ sub run {
 					}
 					$PH-&gt;{chokemap}-&gt;{can_unchoke}-&gt;{$c_sname} = $foopoints;
 				}
+				
+				# Deliver pieces
+				# FIXME: Der loop wird ziemlich haeftig aufgerufen.. brauchts da keine limitierung?!
+				$c_obj-&gt;FlushDeliverQueue;
+				
 				#END
 			}
 			elsif($c_status == STATE_NOMETA) {
@@ -1136,7 +1141,8 @@ sub _Network_Data {
 					elsif($msgtype == MSG_REQUEST) {
 						my(undef,undef, $this_piece, $this_offset, $this_size) = unpack(&quot;NC N N N&quot;, $cbuff);
 						$self-&gt;debug(&quot;Request { Index=&gt; $this_piece , Offset =&gt; $this_offset , Size =&gt; $this_size }&quot;);
-						$client-&gt;DeliverData(Index=&gt;$this_piece, Offset=&gt;$this_offset, Size=&gt;$this_size) or return; # = DeliverData closed the connection
+						$client-&gt;PushDeliverQueue(Index=&gt;$this_piece, Offset=&gt;$this_offset, Size=&gt;$this_size);
+						$client-&gt;FlushDeliverQueue; # Try to deliver 1 piece to socket
 						$client-&gt;SetLastUsefulTime;
 					}
 					elsif($msgtype == MSG_EPROTO) {
@@ -1703,7 +1709,7 @@ package Bitflu::DownloadBitTorrent::Peer;
 		           ME_interested =&gt; 0, PEER_interested =&gt; 0, ME_choked =&gt; 1, PEER_choked =&gt; 1, rqslots =&gt; 0,
 		           bitfield =&gt; [], rqmap =&gt; {}, piececache =&gt; [], time_lastuseful =&gt; 0 , time_lastdownload =&gt; 0,
 		           kudos =&gt; { born =&gt; $self-&gt;{super}-&gt;Network-&gt;GetTime, bytes_stored =&gt; 0, bytes_sent =&gt; 0, choke =&gt; 0, unchoke =&gt;0, store=&gt;0, fail=&gt;0, ok=&gt;0 },
-		           extensions=&gt;{}, readbuff =&gt; { buff =&gt; '', len =&gt; 0 }, utmeta_rq =&gt; [] };
+		           extensions=&gt;{}, readbuff =&gt; { buff =&gt; '', len =&gt; 0 }, utmeta_rq =&gt; [], deliverq =&gt; [] };
 		bless($xo,ref($self));
 		
 		$xo-&gt;SetRequestSlots(DEF_OUTSTANDING_REQUESTS);  # Inits slot counter to smalles possible value
@@ -1883,6 +1889,44 @@ package Bitflu::DownloadBitTorrent::Peer;
 	}
 	
 	##########################################################################
+	# Add an item to deliver queue, returns FALSE if the client reached
+	# it's limit
+	sub PushDeliverQueue {
+		my($self, %args) = @_;
+		my $items = push(@{$self-&gt;{deliverq}}, {Index=&gt;$args{Index}, Offset=&gt;$args{Offset}, Size=&gt;$args{Size}});
+		
+		if($items &gt; MAX_OUTSTANDING_REQUESTS) {
+			$self-&gt;warn($self-&gt;XID.&quot; reached queue limit, dropping last request&quot;);
+			shift(@{$self-&gt;{deliverq}});
+			return 0;
+		}
+		else {
+			$self-&gt;warn($self-&gt;XID.&quot; has $items queued requests&quot;);
+			return 1;
+		}
+	}
+	
+	sub FlushDeliverQueue {
+		my($self) = @_;
+		
+		my @dcpy  = @{$self-&gt;{deliverq}};
+		foreach my $d_ref (@dcpy) {
+			my $qfree = $self-&gt;{super}-&gt;Network-&gt;GetQueueFree($self-&gt;GetOwnSocket);
+			my $qlim  = $d_ref-&gt;{Size}*2;
+			
+			if($qfree &gt;= $qlim) {
+				$self-&gt;warn(&quot;Can deliver piece $d_ref-&gt;{Index} \@ $d_ref-&gt;{Offset}&quot;);
+				shift(@{$self-&gt;{deliverq}});
+				$self-&gt;DeliverData(%$d_ref);
+			}
+			else {
+				$self-&gt;warn(&quot;Cannot deliver,socket is full dude!&quot;);
+				last;
+			}
+		}
+	}
+	
+	##########################################################################
 	# Register a metadata request
 	sub AddUtMetaRequest {
 		my($self, $piece) = @_;
@@ -2023,9 +2067,8 @@ package Bitflu::DownloadBitTorrent::Peer;
 	sub DeliverData {
 		my($self, %args) = @_;
 		
-		my $good_client  = 1;
 		my $torrent      = $self-&gt;{_super}-&gt;Torrent-&gt;GetTorrent($self-&gt;GetSha1);
-
+		
 		if($self-&gt;GetChokePEER) {
 			$self-&gt;debug($self-&gt;XID.&quot; Choked peer asked for data, ignoring (protocol race condition)&quot;);
 		}
@@ -2040,18 +2083,12 @@ package Bitflu::DownloadBitTorrent::Peer;
 			$self-&gt;{super}-&gt;Queue-&gt;IncrementStats($self-&gt;GetSha1, {'uploaded_bytes' =&gt; $data_len});
 			$torrent-&gt;SetStatsUp($torrent-&gt;GetStatsUp + $data_len);
 			
-			$good_client = $self-&gt;WritePiece(%args);
+			$self-&gt;WritePiece(%args) or $self-&gt;panic(&quot;Write failed&quot;); # Should not fail because caller has to check qlength
 		}
 		else {
 			$self-&gt;info($self-&gt;XID.&quot; Asked me for unadvertised data! (Index=&gt;$args{Index})&quot;);
-			$good_client = 0;
-		}
-		
-		unless($good_client) {
-			$self-&gt;info(&quot;&lt;$self&gt; Droppin connection, write failed ($!)&quot;);
-			$self-&gt;{_super}-&gt;KillClient($self);
 		}
-		return $good_client;
+		return undef;
 	}
 	
 	</diff>
      <filename>plugins/Bitflu/20_DownloadBitTorrent.pm</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>06f6784e11c77b4baedfa8916d81006e406bd288</id>
    </parent>
  </parents>
  <author>
    <name>pab</name>
    <email>pab@d21b55b8-521e-4b26-8270-cc5f5b338b51</email>
  </author>
  <url>http://github.com/melo/bitflu/commit/58c953960179ab13154551be3875af9469c6745b</url>
  <id>58c953960179ab13154551be3875af9469c6745b</id>
  <committed-date>2008-10-13T09:07:11-07:00</committed-date>
  <authored-date>2008-10-13T09:07:11-07:00</authored-date>
  <message>Experimental DeliverQ support


git-svn-id: https://svn.origo.ethz.ch/bitflu@221 d21b55b8-521e-4b26-8270-cc5f5b338b51</message>
  <tree>e81b74efbbe061a300a82e1c5f9901f6556dbe1a</tree>
  <committer>
    <name>pab</name>
    <email>pab@d21b55b8-521e-4b26-8270-cc5f5b338b51</email>
  </committer>
</commit>
