Bläddra i källkod

2010-03-05 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Reduced copying/std::string instantiation in sending/receiving
	BitTorrent messages.
	* src/BtBitfieldMessage.cc
	* src/BtBitfieldMessage.h
	* src/BtExtendedMessage.cc
	* src/BtExtendedMessage.h
	* src/BtHandshakeMessage.cc
	* src/BtHandshakeMessage.h
	* src/BtKeepAliveMessage.cc
	* src/BtKeepAliveMessage.h
	* src/BtPieceMessage.cc
	* src/BtPieceMessage.h
	* src/BtPortMessage.cc
	* src/BtPortMessage.h
	* src/BtUnchokeMessage.h
	* src/DefaultBtMessageReceiver.cc
	* src/IndexBtMessage.cc
	* src/IndexBtMessage.h
	* src/PeerConnection.cc
	* src/PeerConnection.h
	* src/RangeBtMessage.cc
	* src/RangeBtMessage.h
	* src/SimpleBtMessage.cc
	* src/SimpleBtMessage.h
	* src/SocketBuffer.cc
	* src/SocketBuffer.h
	* src/ZeroBtMessage.cc
	* src/ZeroBtMessage.h
	* test/BtAllowedFastMessageTest.cc
	* test/BtBitfieldMessageTest.cc
	* test/BtCancelMessageTest.cc
	* test/BtChokeMessageTest.cc
	* test/BtExtendedMessageTest.cc
	* test/BtHandshakeMessageTest.cc
	* test/BtHaveAllMessageTest.cc
	* test/BtHaveMessageTest.cc
	* test/BtHaveNoneMessageTest.cc
	* test/BtInterestedMessageTest.cc
	* test/BtKeepAliveMessageTest.cc
	* test/BtNotInterestedMessageTest.cc
	* test/BtPieceMessageTest.cc
	* test/BtPortMessageTest.cc
	* test/BtRejectMessageTest.cc
	* test/BtRequestMessageTest.cc
	* test/BtSuggestPieceMessageTest.cc
	* test/BtUnchokeMessageTest.cc
Tatsuhiro Tsujikawa 15 år sedan
förälder
incheckning
8b73c2843f
45 ändrade filer med 470 tillägg och 316 borttagningar
  1. 49 0
      ChangeLog
  2. 12 15
      src/BtBitfieldMessage.cc
  3. 1 6
      src/BtBitfieldMessage.h
  4. 18 23
      src/BtExtendedMessage.cc
  5. 1 5
      src/BtExtendedMessage.h
  6. 8 10
      src/BtHandshakeMessage.cc
  7. 1 3
      src/BtHandshakeMessage.h
  8. 10 10
      src/BtKeepAliveMessage.cc
  9. 4 9
      src/BtKeepAliveMessage.h
  10. 47 38
      src/BtPieceMessage.cc
  11. 9 7
      src/BtPieceMessage.h
  12. 15 20
      src/BtPortMessage.cc
  13. 1 4
      src/BtPortMessage.h
  14. 0 1
      src/BtUnchokeMessage.h
  15. 10 3
      src/DefaultBtMessageReceiver.cc
  16. 11 13
      src/IndexBtMessage.cc
  17. 2 9
      src/IndexBtMessage.h
  18. 44 3
      src/PeerConnection.cc
  19. 20 2
      src/PeerConnection.h
  20. 16 24
      src/RangeBtMessage.cc
  21. 1 4
      src/RangeBtMessage.h
  22. 4 5
      src/SimpleBtMessage.cc
  23. 1 1
      src/SimpleBtMessage.h
  24. 19 5
      src/SocketBuffer.cc
  25. 43 1
      src/SocketBuffer.h
  26. 9 11
      src/ZeroBtMessage.cc
  27. 2 9
      src/ZeroBtMessage.h
  28. 6 4
      test/BtAllowedFastMessageTest.cc
  29. 7 4
      test/BtBitfieldMessageTest.cc
  30. 6 4
      test/BtCancelMessageTest.cc
  31. 6 4
      test/BtChokeMessageTest.cc
  32. 7 4
      test/BtExtendedMessageTest.cc
  33. 6 4
      test/BtHandshakeMessageTest.cc
  34. 6 4
      test/BtHaveAllMessageTest.cc
  35. 6 4
      test/BtHaveMessageTest.cc
  36. 6 4
      test/BtHaveNoneMessageTest.cc
  37. 6 4
      test/BtInterestedMessageTest.cc
  38. 8 6
      test/BtKeepAliveMessageTest.cc
  39. 6 4
      test/BtNotInterestedMessageTest.cc
  40. 6 5
      test/BtPieceMessageTest.cc
  41. 6 4
      test/BtPortMessageTest.cc
  42. 6 4
      test/BtRejectMessageTest.cc
  43. 6 4
      test/BtRequestMessageTest.cc
  44. 6 4
      test/BtSuggestPieceMessageTest.cc
  45. 6 4
      test/BtUnchokeMessageTest.cc

+ 49 - 0
ChangeLog

@@ -1,3 +1,52 @@
+2010-03-05  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Reduced copying/std::string instantiation in sending/receiving
+	BitTorrent messages.
+	* src/BtBitfieldMessage.cc
+	* src/BtBitfieldMessage.h
+	* src/BtExtendedMessage.cc
+	* src/BtExtendedMessage.h
+	* src/BtHandshakeMessage.cc
+	* src/BtHandshakeMessage.h
+	* src/BtKeepAliveMessage.cc
+	* src/BtKeepAliveMessage.h
+	* src/BtPieceMessage.cc
+	* src/BtPieceMessage.h
+	* src/BtPortMessage.cc
+	* src/BtPortMessage.h
+	* src/BtUnchokeMessage.h
+	* src/DefaultBtMessageReceiver.cc
+	* src/IndexBtMessage.cc
+	* src/IndexBtMessage.h
+	* src/PeerConnection.cc
+	* src/PeerConnection.h
+	* src/RangeBtMessage.cc
+	* src/RangeBtMessage.h
+	* src/SimpleBtMessage.cc
+	* src/SimpleBtMessage.h
+	* src/SocketBuffer.cc
+	* src/SocketBuffer.h
+	* src/ZeroBtMessage.cc
+	* src/ZeroBtMessage.h
+	* test/BtAllowedFastMessageTest.cc
+	* test/BtBitfieldMessageTest.cc
+	* test/BtCancelMessageTest.cc
+	* test/BtChokeMessageTest.cc
+	* test/BtExtendedMessageTest.cc
+	* test/BtHandshakeMessageTest.cc
+	* test/BtHaveAllMessageTest.cc
+	* test/BtHaveMessageTest.cc
+	* test/BtHaveNoneMessageTest.cc
+	* test/BtInterestedMessageTest.cc
+	* test/BtKeepAliveMessageTest.cc
+	* test/BtNotInterestedMessageTest.cc
+	* test/BtPieceMessageTest.cc
+	* test/BtPortMessageTest.cc
+	* test/BtRejectMessageTest.cc
+	* test/BtRequestMessageTest.cc
+	* test/BtSuggestPieceMessageTest.cc
+	* test/BtUnchokeMessageTest.cc
+
 2010-03-03  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Rewritten SocketBuffer. Old implementation uses single std::string

+ 12 - 15
src/BtBitfieldMessage.cc

@@ -81,25 +81,22 @@ void BtBitfieldMessage::doReceivedAction() {
   }
 }
 
-const unsigned char* BtBitfieldMessage::getMessage() {
-  if(!msg) {
-    /**
-     * len --- 1+bitfieldLength, 4bytes
-     * id --- 5, 1byte
-     * bitfield --- bitfield, len bytes
-     * total: 5+len bytes
-     */
-    msgLength = 5+bitfieldLength;
-    msg = new unsigned char[msgLength];
-    bittorrent::createPeerMessageString(msg, msgLength, 1+bitfieldLength, ID);
-    memcpy(msg+5, bitfield, bitfieldLength);
-  }
+unsigned char* BtBitfieldMessage::createMessage() {
+  /**
+   * len --- 1+bitfieldLength, 4bytes
+   * id --- 5, 1byte
+   * bitfield --- bitfield, len bytes
+   * total: 5+len bytes
+   */
+  const size_t msgLength = 5+bitfieldLength;
+  unsigned char* msg = new unsigned char[msgLength];
+  bittorrent::createPeerMessageString(msg, msgLength, 1+bitfieldLength, ID);
+  memcpy(msg+5, bitfield, bitfieldLength);
   return msg;
 }
 
 size_t BtBitfieldMessage::getMessageLength() {
-  getMessage();
-  return msgLength;
+  return 5+bitfieldLength;
 }
 
 std::string BtBitfieldMessage::toString() const {

+ 1 - 6
src/BtBitfieldMessage.h

@@ -47,14 +47,10 @@ class BtBitfieldMessage : public SimpleBtMessage {
 private:
   unsigned char* bitfield;
   size_t bitfieldLength;
-  unsigned char* msg;
-  size_t msgLength;
 
   void init() {
     bitfield = 0;
     bitfieldLength = 0;
-    msg = 0;
-    msgLength = 0;
   }
 public:
   BtBitfieldMessage():SimpleBtMessage(ID, NAME)
@@ -71,7 +67,6 @@ public:
 
   virtual ~BtBitfieldMessage() {
     delete [] bitfield;
-    delete [] msg;
   }
 
   static const uint8_t ID = 5;
@@ -88,7 +83,7 @@ public:
 
   virtual void doReceivedAction();
 
-  virtual const unsigned char* getMessage();
+  virtual unsigned char* createMessage();
 
   virtual size_t getMessageLength();
 

+ 18 - 23
src/BtExtendedMessage.cc

@@ -55,36 +55,31 @@ BtExtendedMessage::BtExtendedMessage
 (const ExtensionMessageHandle& extensionMessage):
   SimpleBtMessage(ID, NAME),
   _extensionMessage(extensionMessage),
-  _msg(0),
   _msgLength(0)
 {}
 
-BtExtendedMessage::~BtExtendedMessage()
+unsigned char* BtExtendedMessage::createMessage()
 {
-  delete [] _msg;
-}
-
-const unsigned char* BtExtendedMessage::getMessage() {
-  if(!_msg) {
-    /**
-     * len --- 2+extpayload.length, 4bytes
-     * id --- 20, 1byte
-     * extmsgid --- extmsgid, 1byte
-     * extpayload --- extpayload, nbytes
-     * total: 6+extpayload.length bytes
-     */
-    std::string payload = _extensionMessage->getPayload();
-    _msgLength = 6+payload.size();
-    _msg = new unsigned char[_msgLength];
-    bittorrent::createPeerMessageString(_msg, _msgLength, 2+payload.size(), ID);
-    *(_msg+5) = _extensionMessage->getExtensionMessageID();
-    memcpy(_msg+6, payload.c_str(), payload.size());
-  }
-  return _msg;
+  /**
+   * len --- 2+extpayload.length, 4bytes
+   * id --- 20, 1byte
+   * extmsgid --- extmsgid, 1byte
+   * extpayload --- extpayload, nbytes
+   * total: 6+extpayload.length bytes
+   */
+  std::string payload = _extensionMessage->getPayload();
+  _msgLength = 6+payload.size();
+  unsigned char* msg = new unsigned char[_msgLength];
+  bittorrent::createPeerMessageString(msg, _msgLength, 2+payload.size(), ID);
+  *(msg+5) = _extensionMessage->getExtensionMessageID();
+  memcpy(msg+6, payload.data(), payload.size());
+  return msg;
 }
 
 size_t BtExtendedMessage::getMessageLength() {
-  getMessage();
+  if(!_msgLength) {
+    _msgLength = 6+_extensionMessage->getPayload().size();
+  }
   return _msgLength;
 }
 

+ 1 - 5
src/BtExtendedMessage.h

@@ -49,15 +49,11 @@ class BtExtendedMessage:public SimpleBtMessage
 private:
   SharedHandle<ExtensionMessage> _extensionMessage;
 
-  unsigned char* _msg;
-
   size_t _msgLength;
 public:
   BtExtendedMessage(const SharedHandle<ExtensionMessage>& extensionMessage =
                     SharedHandle<ExtensionMessage>());
 
-  virtual ~BtExtendedMessage();
-
   static const uint8_t ID = 20;
 
   static const std::string NAME;
@@ -70,7 +66,7 @@ public:
 
   virtual void doReceivedAction();
 
-  virtual const unsigned char* getMessage();
+  virtual unsigned char* createMessage();
 
   virtual size_t getMessageLength();
 

+ 8 - 10
src/BtHandshakeMessage.cc

@@ -62,7 +62,6 @@ BtHandshakeMessage::BtHandshakeMessage(const unsigned char* infoHash,
 }
 
 void BtHandshakeMessage::init() {
-  msg = 0;
   this->pstrlen = 19;
   pstr = new unsigned char[PSTR_LENGTH];
   reserved = new unsigned char[RESERVED_LENGTH];
@@ -88,15 +87,14 @@ BtHandshakeMessage::create(const unsigned char* data, size_t dataLength)
   return message;
 }
 
-const unsigned char* BtHandshakeMessage::getMessage() {
-  if(!msg) {
-    msg = new unsigned char[MESSAGE_LENGTH];
-    msg[0] = pstrlen;
-    memcpy(msg+1, pstr, PSTR_LENGTH);
-    memcpy(msg+20, reserved, RESERVED_LENGTH);
-    memcpy(msg+28, infoHash, INFO_HASH_LENGTH);
-    memcpy(msg+48, peerId, PEER_ID_LENGTH);
-  }
+unsigned char* BtHandshakeMessage::createMessage()
+{
+  unsigned char* msg = new unsigned char[MESSAGE_LENGTH];
+  msg[0] = pstrlen;
+  memcpy(msg+1, pstr, PSTR_LENGTH);
+  memcpy(msg+20, reserved, RESERVED_LENGTH);
+  memcpy(msg+28, infoHash, INFO_HASH_LENGTH);
+  memcpy(msg+48, peerId, PEER_ID_LENGTH);
   return msg;
 }
 

+ 1 - 3
src/BtHandshakeMessage.h

@@ -51,7 +51,6 @@ private:
   unsigned char* reserved;
   unsigned char* infoHash;
   unsigned char* peerId;
-  unsigned char* msg;
   void init();
 public:
   BtHandshakeMessage();
@@ -65,7 +64,6 @@ public:
   create(const unsigned char* data, size_t dataLength);
 
   virtual ~BtHandshakeMessage() {
-    delete [] msg;
     delete [] pstr;
     delete [] reserved;
     delete [] infoHash;
@@ -78,7 +76,7 @@ public:
 
   virtual void doReceivedAction() {};
 
-  virtual const unsigned char* getMessage();
+  virtual unsigned char* createMessage();
 
   virtual size_t getMessageLength();
 

+ 10 - 10
src/BtKeepAliveMessage.cc

@@ -39,19 +39,19 @@ namespace aria2 {
 
 const std::string BtKeepAliveMessage::NAME("keep alive");
 
-const unsigned char* BtKeepAliveMessage::getMessage() {
-  if(!msg) {
-    /**
-     * len --- 0, 4bytes
-     * total: 4bytes
-     */
-    msg = new unsigned char[MESSAGE_LENGTH];
-    memset(msg, 0, MESSAGE_LENGTH);
-  }
+unsigned char* BtKeepAliveMessage::createMessage()
+{
+  /**
+   * len --- 0, 4bytes
+   * total: 4bytes
+   */
+  unsigned char* msg = new unsigned char[MESSAGE_LENGTH];
+  memset(msg, 0, MESSAGE_LENGTH);
   return msg;
 }
 
-size_t BtKeepAliveMessage::getMessageLength() {
+size_t BtKeepAliveMessage::getMessageLength()
+{
   return MESSAGE_LENGTH;
 }
 

+ 4 - 9
src/BtKeepAliveMessage.h

@@ -45,15 +45,9 @@ typedef SharedHandle<BtKeepAliveMessage> BtKeepAliveMessageHandle;
 
 class BtKeepAliveMessage : public SimpleBtMessage {
 private:
-  unsigned char* msg;
-
   static const size_t MESSAGE_LENGTH = 4;
 public:
-  BtKeepAliveMessage():SimpleBtMessage(ID, NAME), msg(0) {}
-
-  virtual ~BtKeepAliveMessage() {
-    delete [] msg;
-  }
+  BtKeepAliveMessage():SimpleBtMessage(ID, NAME) {}
 
   static const uint8_t ID = 99;
 
@@ -61,11 +55,12 @@ public:
 
   virtual void doReceivedAction() {}
 
-  virtual const unsigned char* getMessage();
+  virtual unsigned char* createMessage();
 
   virtual size_t getMessageLength();
 
-  virtual std::string toString() const {
+  virtual std::string toString() const
+  {
     return NAME;
   }
 };

+ 47 - 38
src/BtPieceMessage.cc

@@ -59,11 +59,11 @@ namespace aria2 {
 
 const std::string BtPieceMessage::NAME("piece");
 
-void BtPieceMessage::setBlock(const unsigned char* block, size_t blockLength) {
-  delete [] this->block;
-  this->blockLength = blockLength;
-  this->block = new unsigned char[this->blockLength];
-  memcpy(this->block, block, this->blockLength);
+void BtPieceMessage::setRawMessage(unsigned char* data)
+{
+  delete [] _rawData;
+  _rawData = data;
+  this->block = data+9;
 }
 
 BtPieceMessageHandle BtPieceMessage::create(const unsigned char* data, size_t dataLength) {
@@ -72,7 +72,7 @@ BtPieceMessageHandle BtPieceMessage::create(const unsigned char* data, size_t da
   BtPieceMessageHandle message(new BtPieceMessage());
   message->setIndex(bittorrent::getIntParam(data, 1));
   message->setBegin(bittorrent::getIntParam(data, 5));
-  message->setBlock(data+9, dataLength-9);
+  message->setBlockLength(dataLength-9);
   return message;
 }
 
@@ -119,21 +119,20 @@ void BtPieceMessage::doReceivedAction() {
 
 size_t BtPieceMessage::MESSAGE_HEADER_LENGTH = 13;
 
-const unsigned char* BtPieceMessage::getMessageHeader() {
-  if(!msgHeader) {
-    /**
-     * len --- 9+blockLength, 4bytes
-     * id --- 7, 1byte
-     * index --- index, 4bytes
-     * begin --- begin, 4bytes
-     * total: 13bytes
-     */
-    msgHeader = new unsigned char[MESSAGE_HEADER_LENGTH];
-    bittorrent::createPeerMessageString(msgHeader, MESSAGE_HEADER_LENGTH,
-                                        9+blockLength, ID);
-    bittorrent::setIntParam(&msgHeader[5], index);
-    bittorrent::setIntParam(&msgHeader[9], begin);
-  }
+unsigned char* BtPieceMessage::createMessageHeader()
+{
+  /**
+   * len --- 9+blockLength, 4bytes
+   * id --- 7, 1byte
+   * index --- index, 4bytes
+   * begin --- begin, 4bytes
+   * total: 13bytes
+   */
+  unsigned char* msgHeader = new unsigned char[MESSAGE_HEADER_LENGTH];
+  bittorrent::createPeerMessageString(msgHeader, MESSAGE_HEADER_LENGTH,
+                                      9+blockLength, ID);
+  bittorrent::setIntParam(&msgHeader[5], index);
+  bittorrent::setIntParam(&msgHeader[9], begin);
   return msgHeader;
 }
 
@@ -145,34 +144,44 @@ void BtPieceMessage::send() {
   if(invalidate) {
     return;
   }
+  size_t writtenLength;
   if(!sendingInProgress) {
-    logger->info(MSG_SEND_PEER_MESSAGE,
-                 cuid, peer->ipaddr.c_str(), peer->port,
-                 toString().c_str());
-    getMessageHeader();
-    peerConnection->sendMessage(msgHeader, getMessageHeaderLength());
-    off_t pieceDataOffset =
-      (off_t)index*_downloadContext->getPieceLength()+begin;
-    size_t writtenLength = sendPieceData(pieceDataOffset, blockLength);
+    if(logger->info()) {
+      logger->info(MSG_SEND_PEER_MESSAGE,
+                   cuid, peer->ipaddr.c_str(), peer->port,
+                   toString().c_str());
+    }
+    unsigned char* msgHdr = createMessageHeader();
+    size_t msgHdrLen = getMessageHeaderLength();
     if(logger->debug()) {
       logger->debug("msglength = %lu bytes",
-                    static_cast<unsigned long>(getMessageHeaderLength()+
-                                               blockLength));
+                    static_cast<unsigned long>(msgHdrLen+blockLength));
     }
-    peer->updateUploadLength(writtenLength);
+    peerConnection->pushBytes(msgHdr, msgHdrLen);
+    peerConnection->sendPendingData();
+    off_t pieceDataOffset =
+      (off_t)index*_downloadContext->getPieceLength()+begin;
+    writtenLength = sendPieceData(pieceDataOffset, blockLength);
   } else {
-    ssize_t writtenLength = peerConnection->sendPendingData();
-    peer->updateUploadLength(writtenLength);
+    writtenLength = peerConnection->sendPendingData();
   }
+  peer->updateUploadLength(writtenLength);
   sendingInProgress = !peerConnection->sendBufferIsEmpty();
 }
 
 size_t BtPieceMessage::sendPieceData(off_t offset, size_t length) const {
   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);
+  unsigned char* buf = new unsigned char[length];
+  ssize_t r;
+  try {
+    r = pieceStorage->getDiskAdaptor()->readData(buf, length, offset);
+  } catch(RecoverableException& e) {
+    delete [] buf;
+    throw;
+  }
+  if(r == static_cast<ssize_t>(length)) {
+    peerConnection->pushBytes(buf, length);
+    return peerConnection->sendPendingData();
   } else {
     throw DL_ABORT_EX(EX_DATA_READ);
   }

+ 9 - 7
src/BtPieceMessage.h

@@ -51,7 +51,7 @@ private:
   uint32_t begin;
   uint32_t blockLength;
   unsigned char* block;
-  unsigned char* msgHeader;
+  unsigned char* _rawData;
   SharedHandle<DownloadContext> _downloadContext;
 
   static size_t MESSAGE_HEADER_LENGTH;
@@ -72,14 +72,13 @@ public:
      begin(begin),
      blockLength(blockLength),
      block(0),
-     msgHeader(0)
+     _rawData(0)
   {
     uploading = true;
   }
 
   virtual ~BtPieceMessage() {
-    delete [] msgHeader;
-    delete []  block;
+    delete [] _rawData;
   }
 
   static const uint8_t ID = 7;
@@ -96,10 +95,13 @@ public:
 
   const unsigned char* getBlock() const { return block; }
 
-  void setBlock(const unsigned char* block, size_t blockLength);
-
   size_t getBlockLength() const { return blockLength; }
 
+  // Stores raw message data. After this function call, this object
+  // has ownership of data. Caller must not be free or alter data.
+  // Member block is pointed to block starting position in data.
+  void setRawMessage(unsigned char* data);
+
   void setBlockLength(size_t blockLength) { this->blockLength = blockLength; }
 
   void setDownloadContext(const SharedHandle<DownloadContext>& downloadContext);
@@ -108,7 +110,7 @@ public:
 
   virtual void doReceivedAction();
 
-  const unsigned char* getMessageHeader();
+  unsigned char* createMessageHeader();
 
   size_t getMessageHeaderLength();
 

+ 15 - 20
src/BtPortMessage.cc

@@ -52,14 +52,10 @@ namespace aria2 {
 const std::string BtPortMessage::NAME("port");
 
 BtPortMessage::BtPortMessage(uint16_t port):
-  SimpleBtMessage(ID, NAME), _port(port), _msg(0) {}
+  SimpleBtMessage(ID, NAME), _port(port) {}
 
-BtPortMessage::~BtPortMessage()
-{
-  delete [] _msg;
-}
-
-SharedHandle<BtPortMessage> BtPortMessage::create(const unsigned char* data, size_t dataLength)
+SharedHandle<BtPortMessage> BtPortMessage::create
+(const unsigned char* data, size_t dataLength)
 {
   bittorrent::assertPayloadLengthEqual(3, dataLength, NAME);
   bittorrent::assertID(ID, data, NAME);
@@ -96,19 +92,18 @@ void BtPortMessage::doReceivedAction()
   }
 }
 
-const unsigned char* BtPortMessage::getMessage() {
-  if(!_msg) {
-    /**
-     * len --- 5, 4bytes
-     * id --- 4, 1byte
-     * port --- port number, 2bytes
-     * total: 7bytes
-     */
-    _msg = new unsigned char[MESSAGE_LENGTH];
-    bittorrent::createPeerMessageString(_msg, MESSAGE_LENGTH, 3, ID);
-    bittorrent::setShortIntParam(&_msg[5], _port);
-  }
-  return _msg;
+unsigned char* BtPortMessage::createMessage()
+{
+  /**
+   * len --- 5, 4bytes
+   * id --- 4, 1byte
+   * port --- port number, 2bytes
+   * total: 7bytes
+   */
+  unsigned char* msg = new unsigned char[MESSAGE_LENGTH];
+  bittorrent::createPeerMessageString(msg, MESSAGE_LENGTH, 3, ID);
+  bittorrent::setShortIntParam(&msg[5], _port);
+  return msg;
 }
 
 size_t BtPortMessage::getMessageLength() {

+ 1 - 4
src/BtPortMessage.h

@@ -47,7 +47,6 @@ class DHTTaskFactory;
 class BtPortMessage : public SimpleBtMessage {
 private:
   uint16_t _port;
-  unsigned char* _msg;
   static const size_t MESSAGE_LENGTH = 7;
 
   WeakHandle<DHTNode> _localNode;
@@ -60,8 +59,6 @@ private:
 public:
   BtPortMessage(uint16_t port);
 
-  virtual ~BtPortMessage();
-
   static const uint8_t ID = 9;
 
   static const std::string NAME;
@@ -72,7 +69,7 @@ public:
 
   virtual void doReceivedAction();
 
-  virtual const unsigned char* getMessage();
+  virtual unsigned char* createMessage();
 
   virtual size_t getMessageLength();
 

+ 0 - 1
src/BtUnchokeMessage.h

@@ -45,7 +45,6 @@ typedef SharedHandle<BtUnchokeMessage> BtUnchokeMessageHandle;
 
 class BtUnchokeMessage : public ZeroBtMessage {
 private:
-  unsigned char* msg;
   static const size_t MESSAGE_LENGTH = 5;
 public:
   BtUnchokeMessage():ZeroBtMessage(ID, NAME) {}

+ 10 - 3
src/DefaultBtMessageReceiver.cc

@@ -46,6 +46,7 @@
 #include "Logger.h"
 #include "LogFactory.h"
 #include "bittorrent_helper.h"
+#include "BtPieceMessage.h"
 
 namespace aria2 {
 
@@ -104,13 +105,19 @@ void DefaultBtMessageReceiver::sendHandshake() {
 }
 
 BtMessageHandle DefaultBtMessageReceiver::receiveMessage() {
-  unsigned char data[MAX_PAYLOAD_LEN];
   size_t dataLength = 0;
-  if(!peerConnection->receiveMessage(data, dataLength)) {
+  // Give 0 to PeerConnection::receiveMessage() to prevent memcpy.
+  if(!peerConnection->receiveMessage(0, dataLength)) {
     return SharedHandle<BtMessage>();
   }
-  BtMessageHandle msg = messageFactory->createBtMessage(data, dataLength);
+  BtMessageHandle msg =
+    messageFactory->createBtMessage(peerConnection->getBuffer(), dataLength);
   msg->validate();
+  if(msg->getId() == BtPieceMessage::ID) {
+    SharedHandle<BtPieceMessage> piecemsg =
+      dynamic_pointer_cast<BtPieceMessage>(msg);
+    piecemsg->setRawMessage(peerConnection->detachBuffer());
+  }
   return msg;
 }
 

+ 11 - 13
src/IndexBtMessage.cc

@@ -39,20 +39,18 @@
 
 namespace aria2 {
 
-const unsigned char* IndexBtMessage::getMessage()
+unsigned char* IndexBtMessage::createMessage()
 {
-  if(!_msg) {
-    /**
-     * len --- 5, 4bytes
-     * id --- ?, 1byte
-     * piece index --- index, 4bytes
-     * total: 9bytes
-     */
-    _msg = new unsigned char[MESSAGE_LENGTH];
-    bittorrent::createPeerMessageString(_msg, MESSAGE_LENGTH, 5, getId());
-    bittorrent::setIntParam(&_msg[5], _index);
-  }
-  return _msg;
+  /**
+   * len --- 5, 4bytes
+   * id --- ?, 1byte
+   * piece index --- index, 4bytes
+   * total: 9bytes
+   */
+  unsigned char* msg = new unsigned char[MESSAGE_LENGTH];
+  bittorrent::createPeerMessageString(msg, MESSAGE_LENGTH, 5, getId());
+  bittorrent::setIntParam(&msg[5], _index);
+  return msg;
 }
 
 size_t IndexBtMessage::getMessageLength()

+ 2 - 9
src/IndexBtMessage.h

@@ -43,7 +43,6 @@ namespace aria2 {
 class IndexBtMessage : public SimpleBtMessage {
 private:
   size_t _index;
-  unsigned char* _msg;
 
   static const size_t MESSAGE_LENGTH = 9;
 protected:
@@ -59,19 +58,13 @@ protected:
 public:
   IndexBtMessage(uint8_t id, const std::string& name, size_t index)
     :SimpleBtMessage(id, name),
-     _index(index),
-     _msg(0) {}
-
-  virtual ~IndexBtMessage()
-  {
-    delete [] _msg;
-  }
+     _index(index) {}
 
   void setIndex(size_t index) { _index = index; }
 
   size_t getIndex() const { return _index; }
 
-  virtual const unsigned char* getMessage();
+  virtual unsigned char* createMessage();
 
   virtual size_t getMessageLength();
 

+ 44 - 3
src/PeerConnection.cc

@@ -56,6 +56,7 @@ PeerConnection::PeerConnection(int32_t cuid, const SocketHandle& socket)
   :cuid(cuid),
    socket(socket),
    logger(LogFactory::getInstance()),
+   resbuf(new unsigned char[MAX_PAYLOAD_LEN]),
    resbufLength(0),
    currentPayloadLength(0),
    lenbufLength(0),
@@ -64,7 +65,10 @@ PeerConnection::PeerConnection(int32_t cuid, const SocketHandle& socket)
    _prevPeek(false)
 {}
 
-PeerConnection::~PeerConnection() {}
+PeerConnection::~PeerConnection()
+{
+  delete [] resbuf;
+}
 
 ssize_t PeerConnection::sendMessage(const unsigned char* data,
                                     size_t dataLength)
@@ -76,6 +80,42 @@ ssize_t PeerConnection::sendMessage(const unsigned char* data,
   return writtenLength;
 }
 
+void PeerConnection::pushStr(const std::string& data)
+{
+  if(_encryptionEnabled) {
+    const size_t len = data.size();
+    unsigned char* chunk = new unsigned char[len];
+    try {
+      _encryptor->encrypt
+        (chunk, len, reinterpret_cast<const unsigned char*>(data.data()), len);
+    } catch(RecoverableException& e) {
+      delete [] chunk;
+      throw;
+    }
+    _socketBuffer.pushBytes(chunk, len);
+  } else {
+    _socketBuffer.feedSendBuffer(data);
+  }
+}
+
+void PeerConnection::pushBytes(unsigned char* data, size_t len)
+{
+  if(_encryptionEnabled) {
+    unsigned char* chunk = new unsigned char[len];
+    try {
+      _encryptor->encrypt(chunk, len, data, len);
+    } catch(RecoverableException& e) {
+      delete [] data;
+      delete [] chunk;
+      throw;
+    }
+    delete [] data;
+    _socketBuffer.pushBytes(chunk, len);
+  } else {
+    _socketBuffer.pushBytes(data, len);
+  }
+}
+
 bool PeerConnection::receiveMessage(unsigned char* data, size_t& dataLength) {
   if(resbufLength == 0 && 4 > lenbufLength) {
     if(!socket->isReadable(0)) {
@@ -140,8 +180,9 @@ bool PeerConnection::receiveMessage(unsigned char* data, size_t& dataLength) {
   // we got whole payload.
   resbufLength = 0;
   lenbufLength = 0;
-
-  memcpy(data, resbuf, currentPayloadLength);
+  if(data) {
+    memcpy(data, resbuf, currentPayloadLength);
+  }
   dataLength = currentPayloadLength;
   return true;
 }

+ 20 - 2
src/PeerConnection.h

@@ -36,9 +36,11 @@
 #define _D_PEER_CONNECTION_H_
 
 #include "common.h"
+
+#include <unistd.h>
+
 #include "SharedHandle.h"
 #include "SocketBuffer.h"
-#include <unistd.h>
 
 namespace aria2 {
 
@@ -57,7 +59,7 @@ private:
   SharedHandle<SocketCore> socket;
   Logger* logger;
 
-  unsigned char resbuf[MAX_PAYLOAD_LEN];
+  unsigned char* resbuf;
   size_t resbufLength;
   size_t currentPayloadLength;
   unsigned char lenbuf[4];
@@ -83,6 +85,10 @@ public:
   // Returns the number of bytes written
   ssize_t sendMessage(const unsigned char* data, size_t dataLength);
 
+  void pushBytes(unsigned char* data, size_t len);
+
+  void pushStr(const std::string& data);
+
   bool receiveMessage(unsigned char* data, size_t& dataLength);
 
   /**
@@ -101,6 +107,18 @@ public:
   bool sendBufferIsEmpty() const;
   
   ssize_t sendPendingData();
+
+  const unsigned char* getBuffer() const
+  {
+    return resbuf;
+  }
+
+  unsigned char* detachBuffer()
+  {
+    unsigned char* detachbuf = resbuf;
+    resbuf = new unsigned char[MAX_PAYLOAD_LEN];
+    return detachbuf;
+  }
 };
 
 typedef SharedHandle<PeerConnection> PeerConnectionHandle;

+ 16 - 24
src/RangeBtMessage.cc

@@ -45,32 +45,24 @@ RangeBtMessage::RangeBtMessage(uint8_t id,
   :SimpleBtMessage(id, name),
    _index(index),
    _begin(begin),
-   _length(length),
-   _msg(0) {}
+   _length(length) {}
 
-RangeBtMessage::~RangeBtMessage()
+unsigned char* RangeBtMessage::createMessage()
 {
-  delete [] _msg;
-}
-
-const unsigned char* RangeBtMessage::getMessage()
-{
-  if(!_msg) {
-    /**
-     * len --- 13, 4bytes
-     * id --- ?, 1byte
-     * index --- index, 4bytes
-     * begin --- begin, 4bytes
-     * length -- length, 4bytes
-     * total: 17bytes
-     */
-    _msg = new unsigned char[MESSAGE_LENGTH];
-    bittorrent::createPeerMessageString(_msg, MESSAGE_LENGTH, 13, getId());
-    bittorrent::setIntParam(&_msg[5], _index);
-    bittorrent::setIntParam(&_msg[9], _begin);
-    bittorrent::setIntParam(&_msg[13], _length);
-  }
-  return _msg;
+  /**
+   * len --- 13, 4bytes
+   * id --- ?, 1byte
+   * index --- index, 4bytes
+   * begin --- begin, 4bytes
+   * length -- length, 4bytes
+   * total: 17bytes
+   */
+  unsigned char* msg = new unsigned char[MESSAGE_LENGTH];
+  bittorrent::createPeerMessageString(msg, MESSAGE_LENGTH, 13, getId());
+  bittorrent::setIntParam(&msg[5], _index);
+  bittorrent::setIntParam(&msg[9], _begin);
+  bittorrent::setIntParam(&msg[13], _length);
+  return msg;
 }
 
 size_t RangeBtMessage::getMessageLength()

+ 1 - 4
src/RangeBtMessage.h

@@ -45,7 +45,6 @@ private:
   size_t _index;
   uint32_t _begin;
   size_t _length;
-  unsigned char* _msg;
 
   static const size_t MESSAGE_LENGTH = 17;
 protected:
@@ -65,8 +64,6 @@ public:
   RangeBtMessage(uint8_t id, const std::string& name,
                  size_t index, uint32_t begin, size_t length);
 
-  virtual ~RangeBtMessage();
-
   size_t getIndex() const { return _index; }
 
   void setIndex(size_t index) { _index = index; }
@@ -79,7 +76,7 @@ public:
 
   void setLength(size_t length) { _length = length; }
 
-  virtual const unsigned char* getMessage();
+  virtual unsigned char* createMessage();
 
   virtual size_t getMessageLength();
 

+ 4 - 5
src/SimpleBtMessage.cc

@@ -53,20 +53,19 @@ void SimpleBtMessage::send() {
     return;
   }
   if(!sendingInProgress) {
-    const unsigned char* msg = getMessage();
-    size_t msgLength = getMessageLength();
     if(logger->info()) {
       logger->info(MSG_SEND_PEER_MESSAGE,
                    cuid, peer->ipaddr.c_str(), peer->port, toString().c_str());
     }
+    unsigned char* msg = createMessage();
+    size_t msgLength = getMessageLength();
     if(logger->debug()) {
       logger->debug("msglength = %lu bytes",
                     static_cast<unsigned long>(msgLength));
     }
-    peerConnection->sendMessage(msg, msgLength);
-  } else {
-    peerConnection->sendPendingData();
+    peerConnection->pushBytes(msg, msgLength);
   }
+  peerConnection->sendPendingData();
   sendingInProgress = !peerConnection->sendBufferIsEmpty();
   if(!sendingInProgress) {
     onSendComplete();

+ 1 - 1
src/SimpleBtMessage.h

@@ -47,7 +47,7 @@ public:
 
   virtual void send();
 
-  virtual const unsigned char* getMessage() = 0;
+  virtual unsigned char* createMessage() = 0;
 
   virtual size_t getMessageLength() = 0;
 

+ 19 - 5
src/SocketBuffer.cc

@@ -48,9 +48,14 @@ SocketBuffer::SocketBuffer(const SharedHandle<SocketCore>& socket):
 
 SocketBuffer::~SocketBuffer() {}
 
+void SocketBuffer::pushBytes(unsigned char* bytes, size_t len)
+{
+  _bufq.push_back(BufEntry::createBytes(bytes, len));
+}
+
 void SocketBuffer::feedSendBuffer(const std::string& data)
 {
-  _bufq.push_back(data);
+  _bufq.push_back(BufEntry::createStr(data));
 }
 
 ssize_t SocketBuffer::feedAndSend(const std::string& data)
@@ -63,10 +68,18 @@ ssize_t SocketBuffer::send()
 {
   size_t totalslen = 0;
   while(!_bufq.empty()) {
-    const std::string& data = _bufq[0];
-    const size_t size = data.size();
-    ssize_t r = size-_offset;
-    ssize_t slen = _socket->writeData(data.data()+_offset, r);
+    BufEntry& buf = _bufq[0];
+    const char* data;
+    ssize_t r;
+    if(buf.type == TYPE_BYTES) {
+      data = reinterpret_cast<const char*>(buf.bytes);
+      r = buf.bytesLen-_offset;
+    } else {
+      const std::string& str = *buf.str;
+      data = str.data();
+      r = str.size()-_offset;
+    }
+    ssize_t slen = _socket->writeData(data+_offset, r);
     if(slen == 0 && !_socket->wantRead() && !_socket->wantWrite()) {
       throw DL_ABORT_EX(StringFormat(EX_SOCKET_SEND,
                                      "Connection closed.").str());
@@ -77,6 +90,7 @@ ssize_t SocketBuffer::send()
       break;
     } else {
       _offset = 0;
+      buf.deleteBuf();
       _bufq.pop_front();
     }
   }

+ 43 - 1
src/SocketBuffer.h

@@ -48,9 +48,46 @@ class SocketCore;
 
 class SocketBuffer {
 private:
+  enum BUF_TYPE {
+    TYPE_BYTES,
+    TYPE_STR
+  };
+  struct BufEntry {
+    BUF_TYPE type;
+    unsigned char* bytes;
+    size_t bytesLen;
+    std::string* str;
+
+    void deleteBuf()
+    {
+      if(type == TYPE_BYTES) {
+        delete [] bytes;
+      } else if(type == TYPE_STR) {
+        delete str;
+      }
+    }
+      
+    static BufEntry createBytes(unsigned char* bytes, size_t len)
+    {
+      BufEntry b;
+      b.type = TYPE_BYTES;
+      b.bytes = bytes;
+      b.bytesLen = len;
+      return b;
+    }
+
+    static BufEntry createStr(const std::string& str)
+    {
+      BufEntry b;
+      b.type = TYPE_STR;
+      b.str = new std::string(str);
+      return b;
+    }
+  };
+    
   SharedHandle<SocketCore> _socket;
 
-  std::deque<std::string> _bufq;
+  std::deque<BufEntry> _bufq;
 
   // Offset of data in _bufq[0]. SocketBuffer tries to send _bufq[0],
   // but it cannot always send whole data. In this case, offset points
@@ -61,6 +98,11 @@ public:
 
   ~SocketBuffer();
 
+  // Feeds data pointered by bytes with length len. into queue.  This
+  // object gets ownership of bytes, so caller must not delete or
+  // later bytes after this call.
+  void pushBytes(unsigned char* bytes, size_t len);
+
   // Feeds data into queue. This function doesn't send data.
   void feedSendBuffer(const std::string& data);
 

+ 9 - 11
src/ZeroBtMessage.cc

@@ -37,18 +37,16 @@
 
 namespace aria2 {
 
-const unsigned char* ZeroBtMessage::getMessage()
+unsigned char* ZeroBtMessage::createMessage()
 {
-  if(!_msg) {
-    /**
-     * len --- 1, 4bytes
-     * id --- ?, 1byte
-     * total: 5bytes
-     */
-    _msg = new unsigned char[MESSAGE_LENGTH];
-    bittorrent::createPeerMessageString(_msg, MESSAGE_LENGTH, 1, getId());
-  }
-  return _msg;
+  /**
+   * len --- 1, 4bytes
+   * id --- ?, 1byte
+   * total: 5bytes
+   */
+  unsigned char* msg = new unsigned char[MESSAGE_LENGTH];
+  bittorrent::createPeerMessageString(msg, MESSAGE_LENGTH, 1, getId());
+  return msg;
 }
 
 size_t ZeroBtMessage::getMessageLength()

+ 2 - 9
src/ZeroBtMessage.h

@@ -42,8 +42,6 @@ namespace aria2 {
 
 class ZeroBtMessage : public SimpleBtMessage {
 private:
-  unsigned char* _msg;
-
   static const size_t MESSAGE_LENGTH = 5;
 protected:
   template<typename T>
@@ -57,14 +55,9 @@ protected:
 
 public:
   ZeroBtMessage(uint8_t id, const std::string& name):
-    SimpleBtMessage(id, name), _msg(0) {}
-
-  virtual ~ZeroBtMessage()
-  {
-    delete [] _msg;
-  }
+    SimpleBtMessage(id, name) {}
 
-  virtual const unsigned char* getMessage();
+  virtual unsigned char* createMessage();
 
   virtual size_t getMessageLength();
 

+ 6 - 4
test/BtAllowedFastMessageTest.cc

@@ -13,7 +13,7 @@ class BtAllowedFastMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtAllowedFastMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testDoReceivedAction);
   CPPUNIT_TEST(testOnSendComplete);
   CPPUNIT_TEST(testToString);
@@ -25,7 +25,7 @@ public:
   }
 
   void testCreate();
-  void testGetMessage();
+  void testCreateMessage();
   void testDoReceivedAction();
   void testOnSendComplete();
   void testToString();
@@ -60,13 +60,15 @@ void BtAllowedFastMessageTest::testCreate() {
   }
 }
 
-void BtAllowedFastMessageTest::testGetMessage() {
+void BtAllowedFastMessageTest::testCreateMessage() {
   BtAllowedFastMessage msg;
   msg.setIndex(12345);
   unsigned char data[9];
   bittorrent::createPeerMessageString(data, sizeof(data), 5, 17);
   bittorrent::setIntParam(&data[5], 12345);
-  CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 9) == 0);
+  unsigned char* rawmsg = msg.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 9) == 0);
+  delete [] rawmsg;
 }
 
 void BtAllowedFastMessageTest::testDoReceivedAction() {

+ 7 - 4
test/BtBitfieldMessageTest.cc

@@ -16,7 +16,7 @@ class BtBitfieldMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtBitfieldMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testDoReceivedAction);
   CPPUNIT_TEST(testDoReceivedAction_goodByeSeeder);
   CPPUNIT_TEST(testToString);
@@ -28,7 +28,7 @@ public:
   }
 
   void testCreate();
-  void testGetMessage();
+  void testCreateMessage();
   void testDoReceivedAction();
   void testDoReceivedAction_goodByeSeeder();
   void testToString();
@@ -65,7 +65,7 @@ void BtBitfieldMessageTest::testCreate() {
   }
 }
 
-void BtBitfieldMessageTest::testGetMessage() {
+void BtBitfieldMessageTest::testCreateMessage() {
   BtBitfieldMessage msg;
   unsigned char bitfield[2];
   memset(bitfield, 0xff, sizeof(bitfield));
@@ -73,7 +73,10 @@ void BtBitfieldMessageTest::testGetMessage() {
   unsigned char data[5+2];
   bittorrent::createPeerMessageString(data, sizeof(data), 3, 5);
   memcpy(&data[5], bitfield, sizeof(bitfield));
-  CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 7) == 0);
+  unsigned char* rawmsg = msg.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 7) == 0);
+  delete [] rawmsg;
+  CPPUNIT_ASSERT_EQUAL((size_t)7, msg.getMessageLength());
 }
 
 void BtBitfieldMessageTest::testDoReceivedAction() {

+ 6 - 4
test/BtCancelMessageTest.cc

@@ -16,7 +16,7 @@ class BtCancelMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtCancelMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testDoReceivedAction);
   CPPUNIT_TEST_SUITE_END();
 private:
@@ -27,7 +27,7 @@ public:
   }
 
   void testCreate();
-  void testGetMessage();
+  void testCreateMessage();
   void testDoReceivedAction();
 
   class MockBtMessageDispatcher2 : public MockBtMessageDispatcher {
@@ -81,7 +81,7 @@ void BtCancelMessageTest::testCreate() {
   }
 }
 
-void BtCancelMessageTest::testGetMessage() {
+void BtCancelMessageTest::testCreateMessage() {
   BtCancelMessage msg;
   msg.setIndex(12345);
   msg.setBegin(256);
@@ -91,7 +91,9 @@ void BtCancelMessageTest::testGetMessage() {
   bittorrent::setIntParam(&data[5], 12345);
   bittorrent::setIntParam(&data[9], 256);
   bittorrent::setIntParam(&data[13], 1024);
-  CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 17) == 0);
+  unsigned char* rawmsg = msg.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 17) == 0);
+  delete [] rawmsg;
 }
 
 void BtCancelMessageTest::testDoReceivedAction() {

+ 6 - 4
test/BtChokeMessageTest.cc

@@ -16,7 +16,7 @@ class BtChokeMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtChokeMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testDoReceivedAction);
   CPPUNIT_TEST(testOnSendComplete);
   CPPUNIT_TEST(testToString);
@@ -34,7 +34,7 @@ public:
   }
 
   void testCreate();
-  void testGetMessage();
+  void testCreateMessage();
   void testDoReceivedAction();
   void testOnSendComplete();
   void testToString();
@@ -94,11 +94,13 @@ void BtChokeMessageTest::testCreate() {
   }
 }
 
-void BtChokeMessageTest::testGetMessage() {
+void BtChokeMessageTest::testCreateMessage() {
   BtChokeMessage msg;
   unsigned char data[5];
   bittorrent::createPeerMessageString(data, sizeof(data), 1, 0);
-  CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 5) == 0);
+  unsigned char* rawmsg = msg.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 5) == 0);
+  delete [] rawmsg;
 }
 
 void BtChokeMessageTest::testDoReceivedAction() {

+ 7 - 4
test/BtExtendedMessageTest.cc

@@ -16,7 +16,7 @@ class BtExtendedMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtExtendedMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testDoReceivedAction);
   CPPUNIT_TEST(testToString);
   CPPUNIT_TEST_SUITE_END();
@@ -24,7 +24,7 @@ private:
 
 public:
   void testCreate();
-  void testGetMessage();
+  void testCreateMessage();
   void testDoReceivedAction();
   void testToString();
 };
@@ -70,7 +70,7 @@ void BtExtendedMessageTest::testCreate() {
   }
 }
 
-void BtExtendedMessageTest::testGetMessage() {
+void BtExtendedMessageTest::testCreateMessage() {
   std::string payload = "4:name3:foo";
   uint8_t extendedMessageID = 1;
   SharedHandle<MockExtensionMessage> exmsg
@@ -81,7 +81,10 @@ void BtExtendedMessageTest::testGetMessage() {
   bittorrent::createPeerMessageString(data, sizeof(data), 13, 20);
   *(data+5) = extendedMessageID;
   memcpy(data+6, payload.c_str(), payload.size());
-  CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 17) == 0);
+  unsigned char* rawmsg = msg.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 17) == 0);
+  delete [] rawmsg;
+  CPPUNIT_ASSERT_EQUAL((size_t)17, msg.getMessageLength());
 }
 
 void BtExtendedMessageTest::testDoReceivedAction() {

+ 6 - 4
test/BtHandshakeMessageTest.cc

@@ -13,7 +13,7 @@ class BtHandshakeMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtHandshakeMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testToString);
   CPPUNIT_TEST(testSetDHTEnabled);
   CPPUNIT_TEST_SUITE_END();
@@ -24,7 +24,7 @@ public:
   }
 
   void testCreate();
-  void testGetMessage();
+  void testCreateMessage();
   void testToString();
   void testSetDHTEnabled();
 
@@ -70,7 +70,7 @@ void BtHandshakeMessageTest::testCreate() {
                        util::toHex(message->getPeerId(), PEER_ID_LENGTH));
 }
 
-void BtHandshakeMessageTest::testGetMessage() {
+void BtHandshakeMessageTest::testCreateMessage() {
   unsigned char infoHash[] = { 0xff, 0xff, 0xff, 0xff, 0xff,
                                0xff, 0xff, 0xff, 0xff, 0xff,
                                0xff, 0xff, 0xff, 0xff, 0xff,
@@ -86,8 +86,10 @@ void BtHandshakeMessageTest::testGetMessage() {
 
   unsigned char data[68];
   createHandshakeMessageData(data);
+  unsigned char* rawmsg = msg->createMessage();
   CPPUNIT_ASSERT_EQUAL(util::toHex((const unsigned char*)data, 68),
-                       util::toHex((const unsigned char*)msg->getMessage(), 68));
+                       util::toHex(rawmsg, 68));
+  delete [] rawmsg;
 }
 
 void BtHandshakeMessageTest::testToString() {

+ 6 - 4
test/BtHaveAllMessageTest.cc

@@ -15,7 +15,7 @@ class BtHaveAllMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtHaveAllMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testDoReceivedAction);
   CPPUNIT_TEST(testDoReceivedAction_goodByeSeeder);
   CPPUNIT_TEST_SUITE_END();
@@ -26,7 +26,7 @@ public:
   }
 
   void testCreate();
-  void testGetMessage();
+  void testCreateMessage();
   void testDoReceivedAction();
   void testDoReceivedAction_goodByeSeeder();
 };
@@ -58,11 +58,13 @@ void BtHaveAllMessageTest::testCreate() {
   }
 }
 
-void BtHaveAllMessageTest::testGetMessage() {
+void BtHaveAllMessageTest::testCreateMessage() {
   BtHaveAllMessage msg;
   unsigned char data[5];
   bittorrent::createPeerMessageString(data, sizeof(data), 1, 14);
-  CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 5) == 0);
+  unsigned char* rawmsg = msg.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 5) == 0);
+  delete [] rawmsg;
 }
 
 void BtHaveAllMessageTest::testDoReceivedAction() {

+ 6 - 4
test/BtHaveMessageTest.cc

@@ -15,7 +15,7 @@ class BtHaveMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtHaveMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testDoReceivedAction);
   CPPUNIT_TEST(testDoReceivedAction_goodByeSeeder);
   CPPUNIT_TEST(testToString);
@@ -27,7 +27,7 @@ public:
   }
 
   void testCreate();
-  void testGetMessage();
+  void testCreateMessage();
   void testDoReceivedAction();
   void testDoReceivedAction_goodByeSeeder();
   void testToString();
@@ -62,13 +62,15 @@ void BtHaveMessageTest::testCreate() {
   }
 }
 
-void BtHaveMessageTest::testGetMessage() {
+void BtHaveMessageTest::testCreateMessage() {
   BtHaveMessage msg;
   msg.setIndex(12345);
   unsigned char data[9];
   bittorrent::createPeerMessageString(data, sizeof(data), 5, 4);
   bittorrent::setIntParam(&data[5], 12345);
-  CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 9) == 0);
+  unsigned char* rawmsg = msg.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 9) == 0);
+  delete [] rawmsg;
 }
 
 void BtHaveMessageTest::testDoReceivedAction() {

+ 6 - 4
test/BtHaveNoneMessageTest.cc

@@ -13,7 +13,7 @@ class BtHaveNoneMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtHaveNoneMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testDoReceivedAction);
   CPPUNIT_TEST(testToString);
   CPPUNIT_TEST_SUITE_END();
@@ -24,7 +24,7 @@ public:
   }
 
   void testCreate();
-  void testGetMessage();
+  void testCreateMessage();
   void testDoReceivedAction();
   void testToString();
 };
@@ -56,11 +56,13 @@ void BtHaveNoneMessageTest::testCreate() {
   }
 }
 
-void BtHaveNoneMessageTest::testGetMessage() {
+void BtHaveNoneMessageTest::testCreateMessage() {
   BtHaveNoneMessage msg;
   unsigned char data[5];
   bittorrent::createPeerMessageString(data, sizeof(data), 1, 15);
-  CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 5) == 0);
+  unsigned char* rawmsg = msg.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 5) == 0);
+  delete [] rawmsg;
 }
 
 void BtHaveNoneMessageTest::testDoReceivedAction() {

+ 6 - 4
test/BtInterestedMessageTest.cc

@@ -14,14 +14,14 @@ class BtInterestedMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtInterestedMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testDoReceivedAction);
   CPPUNIT_TEST(testOnSendComplete);
   CPPUNIT_TEST(testToString);
   CPPUNIT_TEST_SUITE_END();
 public:
   void testCreate();
-  void testGetMessage();
+  void testCreateMessage();
   void testDoReceivedAction();
   void testOnSendComplete();
   void testToString();
@@ -54,11 +54,13 @@ void BtInterestedMessageTest::testCreate() {
   }
 }
 
-void BtInterestedMessageTest::testGetMessage() {
+void BtInterestedMessageTest::testCreateMessage() {
   BtInterestedMessage msg;
   unsigned char data[5];
   bittorrent::createPeerMessageString(data, sizeof(data), 1, 2);
-  CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 5) == 0);
+  unsigned char* rawmsg = msg.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 5) == 0);
+  delete [] rawmsg;
 }
 
 void BtInterestedMessageTest::testDoReceivedAction() {

+ 8 - 6
test/BtKeepAliveMessageTest.cc

@@ -7,7 +7,7 @@ namespace aria2 {
 class BtKeepAliveMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtKeepAliveMessageTest);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testToString);
   CPPUNIT_TEST_SUITE_END();
 private:
@@ -16,19 +16,21 @@ public:
   void setUp() {
   }
 
-  void testGetMessage();
+  void testCreateMessage();
   void testToString();
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(BtKeepAliveMessageTest);
 
-void BtKeepAliveMessageTest::testGetMessage() {
-  char msg[4];
-  memset(msg, 0, sizeof(msg));
+void BtKeepAliveMessageTest::testCreateMessage() {
+  char data[4];
+  memset(data, 0, sizeof(data));
   BtKeepAliveMessage message;
   CPPUNIT_ASSERT_EQUAL((uint8_t)99, message.getId());
   CPPUNIT_ASSERT_EQUAL((size_t)4, message.getMessageLength());
-  CPPUNIT_ASSERT(memcmp(msg, message.getMessage(), 4) == 0);
+  unsigned char* rawmsg = message.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 4) == 0);
+  delete [] rawmsg;
 }
 
 void BtKeepAliveMessageTest::testToString() {

+ 6 - 4
test/BtNotInterestedMessageTest.cc

@@ -14,14 +14,14 @@ class BtNotInterestedMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtNotInterestedMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testDoReceivedAction);
   CPPUNIT_TEST(testOnSendComplete);
   CPPUNIT_TEST(testToString);
   CPPUNIT_TEST_SUITE_END();
 public:
   void testCreate();
-  void testGetMessage();
+  void testCreateMessage();
   void testDoReceivedAction();
   void testOnSendComplete();
   void testToString();
@@ -54,11 +54,13 @@ void BtNotInterestedMessageTest::testCreate() {
   }
 }
 
-void BtNotInterestedMessageTest::testGetMessage() {
+void BtNotInterestedMessageTest::testCreateMessage() {
   BtNotInterestedMessage msg;
   unsigned char data[5];
   bittorrent::createPeerMessageString(data, sizeof(data), 1, 3);
-  CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 5) == 0);
+  unsigned char* rawmsg = msg.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 5) == 0);
+  delete [] rawmsg;
 }
 
 void BtNotInterestedMessageTest::testDoReceivedAction() {

+ 6 - 5
test/BtPieceMessageTest.cc

@@ -22,7 +22,7 @@ class BtPieceMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtPieceMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessageHeader);
+  CPPUNIT_TEST(testCreateMessageHeader);
   CPPUNIT_TEST(testChokingEvent);
   CPPUNIT_TEST(testChokingEvent_allowedFastEnabled);
   CPPUNIT_TEST(testChokingEvent_inAmAllowedIndexSet);
@@ -38,7 +38,7 @@ class BtPieceMessageTest:public CppUnit::TestFixture {
   CPPUNIT_TEST_SUITE_END();
 public:
   void testCreate();
-  void testGetMessageHeader();
+  void testCreateMessageHeader();
   void testChokingEvent();
   void testChokingEvent_allowedFastEnabled();
   void testChokingEvent_inAmAllowedIndexSet();
@@ -114,7 +114,6 @@ void BtPieceMessageTest::testCreate() {
   CPPUNIT_ASSERT_EQUAL((uint8_t)7, pm->getId());
   CPPUNIT_ASSERT_EQUAL((size_t)12345, pm->getIndex());
   CPPUNIT_ASSERT_EQUAL((uint32_t)256, pm->getBegin());
-  CPPUNIT_ASSERT(memcmp(data, pm->getBlock(), sizeof(data)) == 0);
   CPPUNIT_ASSERT_EQUAL((size_t)2, pm->getBlockLength());
 
   // case: payload size is wrong
@@ -135,7 +134,7 @@ void BtPieceMessageTest::testCreate() {
   }
 }
 
-void BtPieceMessageTest::testGetMessageHeader() {
+void BtPieceMessageTest::testCreateMessageHeader() {
   BtPieceMessage msg;
   msg.setIndex(12345);
   msg.setBegin(256);
@@ -144,7 +143,9 @@ void BtPieceMessageTest::testGetMessageHeader() {
   bittorrent::createPeerMessageString(data, sizeof(data), 9+1024, 7);
   bittorrent::setIntParam(&data[5], 12345);
   bittorrent::setIntParam(&data[9], 256);
-  CPPUNIT_ASSERT(memcmp(msg.getMessageHeader(), data, 13) == 0);
+  unsigned char* rawmsg = msg.createMessageHeader();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 13) == 0);
+  delete [] rawmsg;
 }
 
 void BtPieceMessageTest::testChokingEvent() {

+ 6 - 4
test/BtPortMessageTest.cc

@@ -21,7 +21,7 @@ class BtPortMessageTest:public CppUnit::TestFixture {
   CPPUNIT_TEST_SUITE(BtPortMessageTest);
   CPPUNIT_TEST(testCreate);
   CPPUNIT_TEST(testToString);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testDoReceivedAction);
   CPPUNIT_TEST(testDoReceivedAction_bootstrap);
   CPPUNIT_TEST_SUITE_END();
@@ -33,7 +33,7 @@ public:
 
   void testCreate();
   void testToString();
-  void testGetMessage();
+  void testCreateMessage();
   void testDoReceivedAction();
   void testDoReceivedAction_bootstrap();
 
@@ -89,12 +89,14 @@ void BtPortMessageTest::testToString() {
   CPPUNIT_ASSERT_EQUAL(std::string("port port=1"), msg.toString());
 }
 
-void BtPortMessageTest::testGetMessage() {
+void BtPortMessageTest::testCreateMessage() {
   BtPortMessage msg(6881);
   unsigned char data[7];
   bittorrent::createPeerMessageString(data, sizeof(data), 3, 9);
   bittorrent::setShortIntParam(&data[5], 6881);
-  CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 7) == 0);
+  unsigned char* rawmsg = msg.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 7) == 0);
+  delete [] rawmsg;
 }
 
 void BtPortMessageTest::testDoReceivedAction()

+ 6 - 4
test/BtRejectMessageTest.cc

@@ -15,7 +15,7 @@ class BtRejectMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtRejectMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testDoReceivedAction);
   CPPUNIT_TEST(testDoReceivedActionNoMatch);
   CPPUNIT_TEST(testDoReceivedActionFastExtensionDisabled);
@@ -25,7 +25,7 @@ private:
 
 public:
   void testCreate();
-  void testGetMessage();
+  void testCreateMessage();
   void testDoReceivedAction();
   void testDoReceivedActionNoMatch();
   void testDoReceivedActionFastExtensionDisabled();
@@ -114,7 +114,7 @@ void BtRejectMessageTest::testCreate() {
   }
 }
 
-void BtRejectMessageTest::testGetMessage() {
+void BtRejectMessageTest::testCreateMessage() {
   BtRejectMessage msg;
   msg.setIndex(12345);
   msg.setBegin(256);
@@ -124,7 +124,9 @@ void BtRejectMessageTest::testGetMessage() {
   bittorrent::setIntParam(&data[5], 12345);
   bittorrent::setIntParam(&data[9], 256);
   bittorrent::setIntParam(&data[13], 1024);
-  CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 17) == 0);
+  unsigned char* rawmsg = msg.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 17) == 0);
+  delete [] rawmsg;
 }
 
 void BtRejectMessageTest::testDoReceivedAction() {

+ 6 - 4
test/BtRequestMessageTest.cc

@@ -22,7 +22,7 @@ class BtRequestMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtRequestMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testDoReceivedAction_hasPieceAndAmNotChoking);
   CPPUNIT_TEST(testDoReceivedAction_hasPieceAndAmChokingAndFastExtensionEnabled);
   CPPUNIT_TEST(testDoReceivedAction_hasPieceAndAmChokingAndFastExtensionDisabled);
@@ -40,7 +40,7 @@ private:
 
 public:
   void testCreate();
-  void testGetMessage();
+  void testCreateMessage();
   void testDoReceivedAction_hasPieceAndAmNotChoking();
   void testDoReceivedAction_hasPieceAndAmChokingAndFastExtensionEnabled();
   void testDoReceivedAction_hasPieceAndAmChokingAndFastExtensionDisabled();
@@ -156,7 +156,7 @@ void BtRequestMessageTest::testCreate() {
   }
 }
 
-void BtRequestMessageTest::testGetMessage() {
+void BtRequestMessageTest::testCreateMessage() {
   BtRequestMessage msg;
   msg.setIndex(12345);
   msg.setBegin(256);
@@ -166,7 +166,9 @@ void BtRequestMessageTest::testGetMessage() {
   bittorrent::setIntParam(&data[5], 12345);
   bittorrent::setIntParam(&data[9], 256);
   bittorrent::setIntParam(&data[13], 1024);
-  CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 17) == 0);
+  unsigned char* rawmsg = msg.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 17) == 0);
+  delete [] rawmsg;
 }
 
 void BtRequestMessageTest::testDoReceivedAction_hasPieceAndAmNotChoking() {

+ 6 - 4
test/BtSuggestPieceMessageTest.cc

@@ -11,7 +11,7 @@ class BtSuggestPieceMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtSuggestPieceMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testToString);
   CPPUNIT_TEST_SUITE_END();
 private:
@@ -21,7 +21,7 @@ public:
   }
 
   void testCreate();
-  void testGetMessage();
+  void testCreateMessage();
   void testToString();
 };
 
@@ -54,13 +54,15 @@ void BtSuggestPieceMessageTest::testCreate() {
   }
 }
 
-void BtSuggestPieceMessageTest::testGetMessage() {
+void BtSuggestPieceMessageTest::testCreateMessage() {
   BtSuggestPieceMessage msg;
   msg.setIndex(12345);
   unsigned char data[9];
   bittorrent::createPeerMessageString(data, sizeof(data), 5, 13);
   bittorrent::setIntParam(&data[5], 12345);
-  CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 9) == 0);
+  unsigned char* rawmsg = msg.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 9) == 0);
+  delete [] rawmsg;
 }
 
 void BtSuggestPieceMessageTest::testToString() {

+ 6 - 4
test/BtUnchokeMessageTest.cc

@@ -10,7 +10,7 @@ class BtUnchokeMessageTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(BtUnchokeMessageTest);
   CPPUNIT_TEST(testCreate);
-  CPPUNIT_TEST(testGetMessage);
+  CPPUNIT_TEST(testCreateMessage);
   CPPUNIT_TEST(testDoReceivedAction);
   CPPUNIT_TEST(testOnSendComplete);
   CPPUNIT_TEST(testToString);
@@ -22,7 +22,7 @@ public:
   }
 
   void testCreate();
-  void testGetMessage();
+  void testCreateMessage();
   void testDoReceivedAction();
   void testOnSendComplete();
   void testToString();
@@ -54,11 +54,13 @@ void BtUnchokeMessageTest::testCreate() {
   }
 }
 
-void BtUnchokeMessageTest::testGetMessage() {
+void BtUnchokeMessageTest::testCreateMessage() {
   BtUnchokeMessage msg;
   unsigned char data[5];
   bittorrent::createPeerMessageString(data, sizeof(data), 1, 1);
-  CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 5) == 0);
+  unsigned char* rawmsg = msg.createMessage();
+  CPPUNIT_ASSERT(memcmp(rawmsg, data, 5) == 0);
+  delete [] rawmsg;
 }
 
 void BtUnchokeMessageTest::testDoReceivedAction() {