mirror of https://github.com/aria2/aria2
				
				
				
			2008-09-28 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Fixed the bug that aria2 may send duplicate data to BitTorrent peer if whole message data is not sent in one send() call. * src/BtPieceMessage.cc * src/BtPieceMessage.h * src/PeerConnection.cc * src/PeerConnection.h * src/SimpleBtMessage.cc * src/SimpleBtMessage.hpull/1/head
							parent
							
								
									db5944b29b
								
							
						
					
					
						commit
						4f280af10b
					
				
							
								
								
									
										11
									
								
								ChangeLog
								
								
								
								
							
							
						
						
									
										11
									
								
								ChangeLog
								
								
								
								
							| 
						 | 
				
			
			@ -1,3 +1,14 @@
 | 
			
		|||
2008-09-28  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 | 
			
		||||
 | 
			
		||||
	Fixed the bug that aria2 may send duplicate data to BitTorrent peer if
 | 
			
		||||
	whole message data is not sent in one send() call.
 | 
			
		||||
	* src/BtPieceMessage.cc
 | 
			
		||||
	* src/BtPieceMessage.h
 | 
			
		||||
	* src/PeerConnection.cc
 | 
			
		||||
	* src/PeerConnection.h
 | 
			
		||||
	* src/SimpleBtMessage.cc
 | 
			
		||||
	* src/SimpleBtMessage.h
 | 
			
		||||
	
 | 
			
		||||
2008-09-28  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 | 
			
		||||
 | 
			
		||||
	Fixed the bug that aria2 downloads faster than max-download-limit when
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,6 +53,7 @@
 | 
			
		|||
#include "StringFormat.h"
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
 | 
			
		||||
namespace aria2 {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -140,61 +141,34 @@ void BtPieceMessage::send() {
 | 
			
		|||
  if(invalidate) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if(!headerSent) {
 | 
			
		||||
  if(!sendingInProgress) {
 | 
			
		||||
    logger->info(MSG_SEND_PEER_MESSAGE,
 | 
			
		||||
		 cuid, peer->ipaddr.c_str(), peer->port,
 | 
			
		||||
		 toString().c_str());
 | 
			
		||||
    getMessageHeader();
 | 
			
		||||
      leftDataLength = getMessageHeaderLength();
 | 
			
		||||
      sendingInProgress = true;
 | 
			
		||||
    }
 | 
			
		||||
    size_t writtenLength
 | 
			
		||||
      = peerConnection->sendMessage(msgHeader+getMessageHeaderLength()-leftDataLength,
 | 
			
		||||
				    leftDataLength);
 | 
			
		||||
    if(writtenLength == leftDataLength) {
 | 
			
		||||
      headerSent = true;
 | 
			
		||||
      leftDataLength = blockLength;
 | 
			
		||||
    } else {
 | 
			
		||||
      leftDataLength -= writtenLength;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if(headerSent) {
 | 
			
		||||
    sendingInProgress = false;
 | 
			
		||||
    peerConnection->sendMessage(msgHeader, getMessageHeaderLength());
 | 
			
		||||
    off_t pieceDataOffset =
 | 
			
		||||
      (off_t)index*btContext->getPieceLength()+begin+blockLength-leftDataLength;
 | 
			
		||||
    size_t writtenLength = sendPieceData(pieceDataOffset, leftDataLength);
 | 
			
		||||
      (off_t)index*btContext->getPieceLength()+begin;
 | 
			
		||||
    size_t writtenLength = sendPieceData(pieceDataOffset, blockLength);
 | 
			
		||||
    logger->debug("msglength = %zu bytes",
 | 
			
		||||
		  getMessageHeaderLength()+blockLength);
 | 
			
		||||
    peer->updateUploadLength(writtenLength);
 | 
			
		||||
  } else {
 | 
			
		||||
    ssize_t writtenLength = peerConnection->sendPendingData();
 | 
			
		||||
    peer->updateUploadLength(writtenLength);
 | 
			
		||||
    if(writtenLength < leftDataLength) {
 | 
			
		||||
      sendingInProgress = true;
 | 
			
		||||
    }
 | 
			
		||||
    leftDataLength -= writtenLength;
 | 
			
		||||
  }
 | 
			
		||||
  sendingInProgress = !peerConnection->sendBufferIsEmpty();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t BtPieceMessage::sendPieceData(off_t offset, size_t length) const {
 | 
			
		||||
  size_t BUF_SIZE = 256;
 | 
			
		||||
  unsigned char buf[BUF_SIZE];
 | 
			
		||||
  div_t res = div(length, BUF_SIZE);
 | 
			
		||||
  size_t writtenLength = 0;
 | 
			
		||||
  for(int i = 0; i < res.quot; i++) {
 | 
			
		||||
    if((size_t)pieceStorage->getDiskAdaptor()->readData(buf, BUF_SIZE, offset+i*BUF_SIZE) < BUF_SIZE) {
 | 
			
		||||
  assert(length <= 16*1024);
 | 
			
		||||
  unsigned char buf[16*1024];
 | 
			
		||||
  if(pieceStorage->getDiskAdaptor()->readData(buf, length, offset) ==
 | 
			
		||||
     static_cast<ssize_t>(length)) {
 | 
			
		||||
    return peerConnection->sendMessage(buf, length);
 | 
			
		||||
  } else {
 | 
			
		||||
    throw DlAbortEx(EX_DATA_READ);
 | 
			
		||||
  }
 | 
			
		||||
    size_t ws = peerConnection->sendMessage(buf, BUF_SIZE);
 | 
			
		||||
    writtenLength += ws;
 | 
			
		||||
    if(ws != BUF_SIZE) {
 | 
			
		||||
      return writtenLength;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if(res.rem > 0) {
 | 
			
		||||
    if(pieceStorage->getDiskAdaptor()->readData(buf, res.rem, offset+res.quot*BUF_SIZE) < res.rem) {
 | 
			
		||||
      throw DlAbortEx(EX_DATA_READ);
 | 
			
		||||
    }
 | 
			
		||||
    size_t ws = peerConnection->sendMessage(buf, res.rem);
 | 
			
		||||
    writtenLength += ws;
 | 
			
		||||
  }
 | 
			
		||||
  return writtenLength;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string BtPieceMessage::toString() const {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,8 +52,6 @@ private:
 | 
			
		|||
  uint32_t begin;
 | 
			
		||||
  uint32_t blockLength;
 | 
			
		||||
  unsigned char* block;
 | 
			
		||||
  size_t leftDataLength;
 | 
			
		||||
  bool headerSent;
 | 
			
		||||
  unsigned char* msgHeader;
 | 
			
		||||
 | 
			
		||||
  static size_t MESSAGE_HEADER_LENGTH;
 | 
			
		||||
| 
						 | 
				
			
			@ -99,8 +97,6 @@ public:
 | 
			
		|||
     begin(begin),
 | 
			
		||||
     blockLength(blockLength),
 | 
			
		||||
     block(0),
 | 
			
		||||
     leftDataLength(0),
 | 
			
		||||
     headerSent(false),
 | 
			
		||||
     msgHeader(0)
 | 
			
		||||
  {
 | 
			
		||||
    uploading = true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,11 +69,9 @@ PeerConnection::~PeerConnection() {}
 | 
			
		|||
ssize_t PeerConnection::sendMessage(const unsigned char* data,
 | 
			
		||||
				    size_t dataLength)
 | 
			
		||||
{
 | 
			
		||||
  if(socket->isWritable(0)) {
 | 
			
		||||
    return sendData(data, dataLength, _encryptionEnabled);
 | 
			
		||||
  } else {
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
  ssize_t writtenLength = sendData(data, dataLength, _encryptionEnabled);
 | 
			
		||||
  logger->debug("sent %d byte(s).", writtenLength);
 | 
			
		||||
  return writtenLength;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool PeerConnection::receiveMessage(unsigned char* data, size_t& dataLength) {
 | 
			
		||||
| 
						 | 
				
			
			@ -231,4 +229,16 @@ void PeerConnection::presetBuffer(const unsigned char* data, size_t length)
 | 
			
		|||
  resbufLength = length;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool PeerConnection::sendBufferIsEmpty() const
 | 
			
		||||
{
 | 
			
		||||
  return _socketBuffer.sendBufferIsEmpty();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ssize_t PeerConnection::sendPendingData()
 | 
			
		||||
{
 | 
			
		||||
  ssize_t writtenLength = _socketBuffer.send();
 | 
			
		||||
  logger->debug("sent %d byte(s).", writtenLength);
 | 
			
		||||
  return writtenLength;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace aria2
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -99,6 +99,10 @@ public:
 | 
			
		|||
			const SharedHandle<ARC4Decryptor>& decryptor);
 | 
			
		||||
 | 
			
		||||
  void presetBuffer(const unsigned char* data, size_t length);
 | 
			
		||||
 | 
			
		||||
  bool sendBufferIsEmpty() const;
 | 
			
		||||
  
 | 
			
		||||
  ssize_t sendPendingData();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef SharedHandle<PeerConnection> PeerConnectionHandle;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,7 @@
 | 
			
		|||
 | 
			
		||||
namespace aria2 {
 | 
			
		||||
 | 
			
		||||
SimpleBtMessage::SimpleBtMessage():leftDataLength(0) {}
 | 
			
		||||
SimpleBtMessage::SimpleBtMessage() {}//:leftDataLength(0) {}
 | 
			
		||||
 | 
			
		||||
SimpleBtMessage::~SimpleBtMessage() {}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -49,22 +49,22 @@ void SimpleBtMessage::send() {
 | 
			
		|||
  if(invalidate) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if(sendPredicate() || sendingInProgress) {
 | 
			
		||||
  if(!sendPredicate() && !sendingInProgress) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if(!sendingInProgress) {
 | 
			
		||||
    const unsigned char* msg = getMessage();
 | 
			
		||||
    size_t msgLength = getMessageLength();
 | 
			
		||||
    if(!sendingInProgress) {
 | 
			
		||||
    logger->info(MSG_SEND_PEER_MESSAGE,
 | 
			
		||||
		 cuid, peer->ipaddr.c_str(), peer->port, toString().c_str());
 | 
			
		||||
      leftDataLength = getMessageLength();
 | 
			
		||||
    }
 | 
			
		||||
    sendingInProgress = false;
 | 
			
		||||
    size_t writtenLength = peerConnection->sendMessage(msg+msgLength-leftDataLength, leftDataLength);
 | 
			
		||||
    if(writtenLength == leftDataLength) {
 | 
			
		||||
      onSendComplete();
 | 
			
		||||
    logger->debug("msglength = %zu bytes", msgLength);
 | 
			
		||||
    peerConnection->sendMessage(msg, msgLength);
 | 
			
		||||
  } else {
 | 
			
		||||
      leftDataLength -= writtenLength;
 | 
			
		||||
      sendingInProgress = true;
 | 
			
		||||
    peerConnection->sendPendingData();
 | 
			
		||||
  }
 | 
			
		||||
  sendingInProgress = !peerConnection->sendBufferIsEmpty();
 | 
			
		||||
  if(!sendingInProgress) {
 | 
			
		||||
    onSendComplete();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,8 +40,6 @@
 | 
			
		|||
namespace aria2 {
 | 
			
		||||
 | 
			
		||||
class SimpleBtMessage : public AbstractBtMessage {
 | 
			
		||||
private:
 | 
			
		||||
  size_t leftDataLength;
 | 
			
		||||
public:
 | 
			
		||||
  SimpleBtMessage();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue