3535using System . Threading ;
3636using System . Threading . Tasks ;
3737
38+ using MonoTorrent . Logging ;
3839using MonoTorrent . Messages ;
3940using MonoTorrent . Messages . Peer ;
4041
@@ -44,6 +45,8 @@ namespace MonoTorrent.Connections.Peer
4445{
4546 sealed class HttpPeerConnection : IPeerConnection
4647 {
48+ static readonly Logger Log = Logger . Create ( nameof ( HttpPeerConnection ) ) ;
49+
4750 static readonly Uri PaddingFileUri = new Uri ( "http://__paddingfile__" ) ;
4851
4952 class HttpRequestData
@@ -305,14 +308,20 @@ public async ReusableTask<int> SendAsync (Memory<byte> socketBuffer)
305308 {
306309 SendResult = new TaskCompletionSource < object ? > ( ) ;
307310
311+ var info = TorrentData . TorrentInfo ;
308312 List < BlockInfo > bundle = DecodeMessages ( socketBuffer . Span ) ;
309- if ( bundle . Count > 0 ) {
310- RequestMessages . AddRange ( bundle ) ;
311- CreateWebRequests ( RequestMessages . ToArray ( ) ) ;
312- } else {
313+
314+ // If the messages in the send buffer are anything *other* than piece request messages,
315+ // just pretend the bytes were sent and everything was fine.
316+ if ( bundle . Count == 0 || info == null )
313317 return socketBuffer . Length ;
314- }
315318
319+ // Otherwise, if there were 1 or more piece request messages, convert these to HTTP requests.
320+ // and only mark the bytes as successfully sent after all webrequests have run to completion
321+ // and the data has been received.
322+ RequestMessages . AddRange ( bundle ) ;
323+ ValidateWebRequests ( info , RequestMessages . ToArray ( ) ) ;
324+ CreateWebRequestsForSequentialRange ( RequestMessages [ 0 ] , RequestMessages [ RequestMessages . Count - 1 ] ) ;
316325 ReceiveWaiter . Set ( ) ;
317326 await SendResult . Task ;
318327 return socketBuffer . Length ;
@@ -331,22 +340,22 @@ static List<BlockInfo> DecodeMessages (ReadOnlySpan<byte> buffer)
331340 return messages ;
332341 }
333342
334- void CreateWebRequests ( BlockInfo [ ] blocks )
343+ static void ValidateWebRequests ( ITorrentInfo torrentInfo , BlockInfo [ ] blocks )
335344 {
336345 if ( blocks . Length > 0 ) {
337346 BlockInfo startBlock = blocks [ 0 ] ;
338347 BlockInfo currentBlock = startBlock ;
339348 for ( int i = 1 ; i < blocks . Length ; i ++ ) {
340349 BlockInfo previousBlock = blocks [ i - 1 ] ;
341350 currentBlock = blocks [ i ] ;
342- long endOffsetOfPreviousEndBlock = TorrentData . TorrentInfo ! . PieceIndexToByteOffset ( previousBlock . PieceIndex ) + previousBlock . StartOffset + previousBlock . RequestLength ;
343- long startOffsetOfCurrentBlock = TorrentData . TorrentInfo ! . PieceIndexToByteOffset ( currentBlock . PieceIndex ) + currentBlock . StartOffset ;
351+ long endOffsetOfPreviousEndBlock = torrentInfo . PieceIndexToByteOffset ( previousBlock . PieceIndex ) + previousBlock . StartOffset + previousBlock . RequestLength ;
352+ long startOffsetOfCurrentBlock = torrentInfo . PieceIndexToByteOffset ( currentBlock . PieceIndex ) + currentBlock . StartOffset ;
344353 if ( endOffsetOfPreviousEndBlock != startOffsetOfCurrentBlock ) {
345- CreateWebRequestsForSequentialRange ( startBlock , previousBlock ) ;
346- startBlock = currentBlock ;
354+ var msg = "Piece requests made from HTTP peers must be a strictly sequential range of blocks. The range must be 1 or more blocks long." ;
355+ Log . Error ( msg ) ;
356+ throw new InvalidOperationException ( msg ) ;
347357 }
348358 }
349- CreateWebRequestsForSequentialRange ( startBlock , currentBlock ) ;
350359 }
351360 }
352361
@@ -369,11 +378,10 @@ void CreateWebRequestsForSequentialRange (BlockInfo start, BlockInfo end)
369378 if ( count == 0 )
370379 break ;
371380
372- var lengthWithPadding = file . Length + file . Padding ;
373381 // If the first byte of data is from the next file, move to the next file immediately
374382 // and adjust start offset to be relative to that file.
375- if ( startOffset >= lengthWithPadding ) {
376- startOffset -= lengthWithPadding ;
383+ if ( startOffset >= file . Length + file . Padding ) {
384+ startOffset -= file . Length + file . Padding ;
377385 continue ;
378386 }
379387
0 commit comments