Browse Source

2008-12-09 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Use BDE instead of Dictionary/List/Data classes.
	* src/CompactPeerListProcessor.cc
	* src/CompactPeerListProcessor.h
	* src/DefaultBtAnnounce.cc
	* src/DefaultBtContext.cc
	* src/DefaultBtContext.h
	* src/DefaultPeerListProcessor.cc
	* src/DefaultPeerListProcessor.h
	* src/DelegatingPeerListProcessor.cc
	* src/DelegatingPeerListProcessor.h
	* src/PeerListProcessor.h
	* src/UTPexExtensionMessage.cc
	* src/Util.h
	* src/message.h
	* test/DefaultBtContextTest.cc
	* test/DefaultPeerListProcessorTest.cc
Tatsuhiro Tsujikawa 17 năm trước cách đây
mục cha
commit
8129042a3a

+ 19 - 0
ChangeLog

@@ -1,3 +1,22 @@
+2008-12-09  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Use BDE instead of Dictionary/List/Data classes.
+	* src/CompactPeerListProcessor.cc
+	* src/CompactPeerListProcessor.h
+	* src/DefaultBtAnnounce.cc
+	* src/DefaultBtContext.cc
+	* src/DefaultBtContext.h
+	* src/DefaultPeerListProcessor.cc
+	* src/DefaultPeerListProcessor.h
+	* src/DelegatingPeerListProcessor.cc
+	* src/DelegatingPeerListProcessor.h
+	* src/PeerListProcessor.h
+	* src/UTPexExtensionMessage.cc
+	* src/Util.h
+	* src/message.h
+	* test/DefaultBtContextTest.cc
+	* test/DefaultPeerListProcessorTest.cc
+
 2008-12-09  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Added bencode helper functions and BDE class.

+ 12 - 11
src/CompactPeerListProcessor.cc

@@ -32,9 +32,9 @@
  */
 /* copyright --> */
 #include "CompactPeerListProcessor.h"
-#include "Peer.h"
-#include "Data.h"
 #include "a2netcompat.h"
+#include "bencode.h"
+#include "Peer.h"
 
 namespace aria2 {
 
@@ -42,23 +42,24 @@ CompactPeerListProcessor::CompactPeerListProcessor() {}
 
 CompactPeerListProcessor::~CompactPeerListProcessor() {}
 
-bool CompactPeerListProcessor::canHandle(const MetaEntry* peersEntry) const {
-  return dynamic_cast<const Data*>(peersEntry) != 0;
+bool CompactPeerListProcessor::canHandle(const bencode::BDE& peerData) const
+{
+  return peerData.isString();
 }
 
 void CompactPeerListProcessor::extractPeer
-(std::deque<SharedHandle<Peer> >& peers, const MetaEntry* peersEntry)
+(std::deque<SharedHandle<Peer> >& peers, const bencode::BDE& peerData)
 {
-  const Data* peersData = dynamic_cast<const Data*>(peersEntry);
-  if(!peersData) {
+  if(!canHandle(peerData)) {
     return;
   }
-  if(peersData->getLen()%6 == 0) {
-    for(size_t i = 0; i < peersData->getLen(); i += 6) {
+  size_t length = peerData.s().size();
+  if(length%6 == 0) {
+    for(size_t i = 0; i < length; i += 6) {
       struct in_addr in;
-      in.s_addr = *(uint32_t*)(peersData->getData()+i);
+      in.s_addr = *(uint32_t*)(peerData.s().c_str()+i);
       std::string ipaddr = inet_ntoa(in);
-      uint16_t port = ntohs(*(uint16_t*)(peersData->getData()+i+4));
+      uint16_t port = ntohs(*(uint16_t*)(peerData.s().c_str()+i+4));
       PeerHandle peer(new Peer(ipaddr, port));
       peers.push_back(peer);
     }

+ 2 - 2
src/CompactPeerListProcessor.h

@@ -45,9 +45,9 @@ public:
   virtual ~CompactPeerListProcessor();
 
   virtual void extractPeer
-  (std::deque<SharedHandle<Peer> >& peers, const MetaEntry* peersEntry);
+  (std::deque<SharedHandle<Peer> >& peers, const bencode::BDE& peerData);
 
-  virtual bool canHandle(const MetaEntry* peersEntry) const;
+  virtual bool canHandle(const bencode::BDE& peerData) const;
 };
 
 } // namespace aria2

+ 37 - 56
src/DefaultBtAnnounce.cc

@@ -35,10 +35,6 @@
 #include "DefaultBtAnnounce.h"
 #include "LogFactory.h"
 #include "Logger.h"
-#include "MetaFileUtil.h"
-#include "Dictionary.h"
-#include "List.h"
-#include "Data.h"
 #include "DelegatingPeerListProcessor.h"
 #include "Util.h"
 #include "prefs.h"
@@ -54,6 +50,7 @@
 #include "StringFormat.h"
 #include "A2STR.h"
 #include "Request.h"
+#include "bencode.h"
 
 namespace aria2 {
 
@@ -200,48 +197,35 @@ void
 DefaultBtAnnounce::processAnnounceResponse(const unsigned char* trackerResponse,
 					   size_t trackerResponseLength)
 {
-  SharedHandle<MetaEntry> entry(MetaFileUtil::bdecoding(trackerResponse,
-							trackerResponseLength));
-  const Dictionary* response = dynamic_cast<const Dictionary*>(entry.get());
-  if(!response) {
+  logger->debug("Now processing tracker response.");
+  const bencode::BDE dict =
+    bencode::decode(trackerResponse, trackerResponseLength);
+  if(!dict.isDict()) {
     throw DlAbortEx(MSG_NULL_TRACKER_RESPONSE);
   }
-  const Data* failureReasonData =
-    dynamic_cast<const Data*>(response->get(BtAnnounce::FAILURE_REASON));
-  if(failureReasonData) {
+  const bencode::BDE& failure = dict[BtAnnounce::FAILURE_REASON];
+  if(failure.isString()) {
     throw DlAbortEx
-      (StringFormat(EX_TRACKER_FAILURE,
-		    failureReasonData->toString().c_str()).str());
+      (StringFormat(EX_TRACKER_FAILURE, failure.s().c_str()).str());
   }
-  const Data* warningMessageData =
-    dynamic_cast<const Data*>(response->get(BtAnnounce::WARNING_MESSAGE));
-  if(warningMessageData) {
-    logger->warn(MSG_TRACKER_WARNING_MESSAGE,
-		 warningMessageData->toString().c_str());
+  const bencode::BDE& warn = dict[BtAnnounce::WARNING_MESSAGE];
+  if(warn.isString()) {
+    logger->warn(MSG_TRACKER_WARNING_MESSAGE, warn.s().c_str());
   }
-  const Data* trackerIdData =
-    dynamic_cast<const Data*>(response->get(BtAnnounce::TRACKER_ID));
-  if(trackerIdData) {
-    trackerId = trackerIdData->toString();
+  const bencode::BDE& tid = dict[BtAnnounce::TRACKER_ID];
+  if(tid.isString()) {
+    trackerId = tid.s();
     logger->debug("Tracker ID:%s", trackerId.c_str());
   }
-  const Data* intervalData =
-    dynamic_cast<const Data*>(response->get(BtAnnounce::INTERVAL));
-  if(intervalData) {
-    time_t t = intervalData->toInt();
-    if(t > 0) {
-      interval = intervalData->toInt();
-      logger->debug("Interval:%d", interval);
-    }
+  const bencode::BDE& ival = dict[BtAnnounce::INTERVAL];
+  if(ival.isInteger() && ival.i() > 0) {
+    interval = ival.i();
+    logger->debug("Interval:%d", interval);
   }
-  const Data* minIntervalData =
-    dynamic_cast<const Data*>(response->get(BtAnnounce::MIN_INTERVAL));
-  if(minIntervalData) {
-    time_t t = minIntervalData->toInt();
-    if(t > 0) {
-      minInterval = minIntervalData->toInt();
-      logger->debug("Min interval:%d", minInterval);
-    }
+  const bencode::BDE& mival = dict[BtAnnounce::MIN_INTERVAL];
+  if(mival.isInteger() && mival.i() > 0) {
+    minInterval = mival.i();
+    logger->debug("Min interval:%d", minInterval);
     if(minInterval > interval) {
       minInterval = interval;
     }
@@ -249,28 +233,25 @@ DefaultBtAnnounce::processAnnounceResponse(const unsigned char* trackerResponse,
     // Use interval as a minInterval if minInterval is not supplied.
     minInterval = interval;
   }
-  const Data* completeData =
-    dynamic_cast<const Data*>(response->get(BtAnnounce::COMPLETE));
-  if(completeData) {
-    complete = completeData->toInt();
+  const bencode::BDE& comp = dict[BtAnnounce::COMPLETE];
+  if(comp.isInteger()) {
+    complete = comp.i();
     logger->debug("Complete:%d", complete);
   }
-  const Data* incompleteData =
-    dynamic_cast<const Data*>(response->get(BtAnnounce::INCOMPLETE));
-  if(incompleteData) {
-    incomplete = incompleteData->toInt();
+  const bencode::BDE& incomp = dict[BtAnnounce::INCOMPLETE];
+  if(incomp.isInteger()) {
+    incomplete = incomp.i();
     logger->debug("Incomplete:%d", incomplete);
   }
-  const MetaEntry* peersEntry = response->get(BtAnnounce::PEERS);
-  if(peersEntry &&
-     !btRuntime->isHalt() &&
-     btRuntime->lessThanMinPeers()) {
-    DelegatingPeerListProcessor proc;
-    std::deque<SharedHandle<Peer> > peers;
-    proc.extractPeer(peers, peersEntry);
-    peerStorage->addPeer(peers);
-  }
-  if(!peersEntry) {
+  const bencode::BDE& peerData = dict[BtAnnounce::PEERS];
+  if(!peerData.isNone()) {
+    if(!btRuntime->isHalt() && btRuntime->lessThanMinPeers()) {
+      DelegatingPeerListProcessor proc;
+      std::deque<SharedHandle<Peer> > peers;
+      proc.extractPeer(peers, peerData);
+      peerStorage->addPeer(peers);
+    }
+  } else {
     logger->info(MSG_NO_PEER_LIST_RECEIVED);
   }
 }

+ 133 - 168
src/DefaultBtContext.cc

@@ -33,12 +33,13 @@
  */
 /* copyright --> */
 #include "DefaultBtContext.h"
-#include "MetaFileUtil.h"
-#include "Dictionary.h"
-#include "List.h"
-#include "Data.h"
+
+#include <cstring>
+#include <ostream>
+#include <functional>
+#include <algorithm>
+
 #include "DlAbortEx.h"
-#include "BencodeVisitor.h"
 #include "Util.h"
 #include "MessageDigestHelper.h"
 #include "a2netcompat.h"
@@ -51,10 +52,7 @@
 #include "PeerMessageUtil.h"
 #include "StringFormat.h"
 #include "A2STR.h"
-#include <cstring>
-#include <ostream>
-#include <functional>
-#include <algorithm>
+#include "bencode.h"
 
 namespace aria2 {
 
@@ -102,84 +100,67 @@ void DefaultBtContext::clear() {
   _private = false;
 }
 
-void DefaultBtContext::extractPieceHash(const unsigned char* hashData,
-					size_t hashDataLength,
-					size_t hashLength) {
-  size_t numPieces = hashDataLength/hashLength;
+void DefaultBtContext::extractPieceHash(const std::string& hashData,
+					size_t hashLength)
+{
+  size_t numPieces = hashData.size()/hashLength;
   for(size_t i = 0; i < numPieces; i++) {
-    pieceHashes.push_back(Util::toHex(&hashData[i*hashLength],
+    pieceHashes.push_back(Util::toHex(hashData.data()+i*hashLength,
 				      hashLength));
   }
 }
 
-void DefaultBtContext::extractFileEntries(const Dictionary* infoDic,
+void DefaultBtContext::extractFileEntries(const bencode::BDE& infoDict,
 					  const std::string& defaultName,
 					  const std::string& overrideName,
-					  const std::deque<std::string>& urlList) {
+					  const std::deque<std::string>& urlList)
+{
   if(overrideName.empty()) {
-    const Data* nameData =
-      dynamic_cast<const Data*>(infoDic->get(BtContext::C_NAME));
-    if(nameData) {
-      name = nameData->toString();
+    const bencode::BDE& nameData = infoDict[BtContext::C_NAME];
+    if(nameData.isString()) {
+      name = nameData.s();
     } else {
       name = File(defaultName).getBasename()+".file";
     }
   } else {
     name = overrideName;
   }
-  const List* files = dynamic_cast<const List*>(infoDic->get(BtContext::C_FILES));
-  if(files) {
+  const bencode::BDE& filesList = infoDict[BtContext::C_FILES];
+  if(filesList.isList()) {
     uint64_t length = 0;
     off_t offset = 0;
     // multi-file mode
     fileMode = BtContext::MULTI;
-    const std::deque<MetaEntry*>& metaList = files->getList();
-    for(std::deque<MetaEntry*>::const_iterator itr = metaList.begin();
-	itr != metaList.end(); itr++) {
-      const Dictionary* fileDic = dynamic_cast<const Dictionary*>((*itr));
-      if(!fileDic) {
+    for(bencode::BDE::List::const_iterator itr = filesList.listBegin();
+	itr != filesList.listEnd(); ++itr) {
+      const bencode::BDE& fileDict = *itr;
+      if(!fileDict.isDict()) {
 	continue;
       }
-      const Data* lengthData =
-	dynamic_cast<const Data*>(fileDic->get(BtContext::C_LENGTH));
-      if(lengthData) {
-	length += lengthData->toLLInt();
-      } else {
-	throw DlAbortEx
-	  (StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "file length").str());
+
+      const bencode::BDE& fileLengthData = fileDict[BtContext::C_LENGTH];
+      if(!fileLengthData.isInteger()) {
+	throw DlAbortEx(StringFormat(MSG_MISSING_BT_INFO,
+				     BtContext::C_LENGTH.c_str()).str());
       }
-      const List* pathList =
-	dynamic_cast<const List*>(fileDic->get(BtContext::C_PATH));
-      if(!pathList) {
-	throw DlAbortEx
-	  (StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "file path list").str());
+      length += fileLengthData.i();
+
+      const bencode::BDE& pathList = fileDict[BtContext::C_PATH];
+      if(!pathList.isList() || pathList.empty()) {
+	throw DlAbortEx("Path is empty.");
       }
-      const std::deque<MetaEntry*>& paths = pathList->getList();
       std::string path;
-      for(size_t i = 0; i < paths.size()-1; i++) {
-	const Data* subpath = dynamic_cast<const Data*>(paths[i]);
-	if(subpath) {
-	  path += subpath->toString()+"/";
-	} else {
-	  throw DlAbortEx
-	    (StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "file path element").str());
-	}
-      }
-      const Data* lastPath = dynamic_cast<const Data*>(paths.back());
-      if(lastPath) {
-	path += lastPath->toString();
-      } else {
-	throw DlAbortEx
-	  (StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "file path element").str());
+      for(size_t i = 0; i < pathList.size()-1; ++i) {
+	path += pathList[i].s()+"/";
+
       }
+      path += pathList[pathList.size()-1].s();
 
       std::deque<std::string> uris;
       std::transform(urlList.begin(), urlList.end(), std::back_inserter(uris),
 		     std::bind2nd(std::plus<std::string>(), "/"+name+"/"+path));
-      FileEntryHandle fileEntry(new FileEntry(path,
-					      lengthData->toLLInt(),
-					      offset,
-					      uris));
+      FileEntryHandle fileEntry(new FileEntry(path, fileLengthData.i(),
+					      offset, uris));
       fileEntries.push_back(fileEntry);
       offset += fileEntry->getLength();
     }
@@ -187,91 +168,100 @@ void DefaultBtContext::extractFileEntries(const Dictionary* infoDic,
   } else {
     // single-file mode;
     fileMode = BtContext::SINGLE;
-    const Data* length =
-      dynamic_cast<const Data*>(infoDic->get(BtContext::C_LENGTH));
-    if(length) {
-      totalLength = length->toLLInt();
-    } else {
-      throw DlAbortEx
-	(StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "file length").str());
+    const bencode::BDE& lengthData = infoDict[BtContext::C_LENGTH];
+    if(!lengthData.isInteger()) {
+	throw DlAbortEx(StringFormat(MSG_MISSING_BT_INFO,
+				     BtContext::C_LENGTH.c_str()).str());      
     }
+    totalLength = lengthData.i();
     FileEntryHandle fileEntry(new FileEntry(name, totalLength, 0, urlList));
     fileEntries.push_back(fileEntry);
   }
 }
 
-void DefaultBtContext::extractAnnounce(const Data* announceData) {
+void DefaultBtContext::extractAnnounceURI(const bencode::BDE& announceData)
+{
+  // Assumed announceData is string
   std::deque<std::string> urls;
-  urls.push_back(Util::trim(announceData->toString()));
+  urls.push_back(Util::trim(announceData.s()));
   announceTiers.push_back(AnnounceTierHandle(new AnnounceTier(urls)));
 }
 
-void DefaultBtContext::extractAnnounceList(const List* announceListData) {
-  for(std::deque<MetaEntry*>::const_iterator itr = announceListData->getList().begin();
-      itr != announceListData->getList().end(); itr++) {
-    const List* elem = dynamic_cast<const List*>(*itr);
-    if(!elem) {
+void DefaultBtContext::extractAnnounceList(const bencode::BDE& announceList)
+{
+  // Assumed announceList is string
+  for(bencode::BDE::List::const_iterator itr = announceList.listBegin();
+      itr != announceList.listEnd(); ++itr) {
+    const bencode::BDE& elemList = *itr;
+    if(!elemList.isList()) {
       continue;
     }
     std::deque<std::string> urls;
-    for(std::deque<MetaEntry*>::const_iterator elemItr = elem->getList().begin();
-	elemItr != elem->getList().end(); elemItr++) {
-      const Data* data = dynamic_cast<const Data*>(*elemItr);
-      if(data) {
-	urls.push_back(Util::trim(data->toString()));
+    for(bencode::BDE::List::const_iterator elemItr = elemList.listBegin();
+	elemItr != elemList.listEnd(); ++elemItr) {
+      const bencode::BDE& url = (*elemItr);
+      if(url.isString()) {
+	urls.push_back(Util::trim(url.s()));
       }
     }
-    if(urls.size()) {
+    if(!urls.empty()) {
       AnnounceTierHandle tier(new AnnounceTier(urls));
       announceTiers.push_back(tier);
     }
   }
 }
 
+void DefaultBtContext::extractAnnounce(const bencode::BDE& rootDict)
+{
+  const bencode::BDE& announceList = rootDict[BtContext::C_ANNOUNCE_LIST];
+  if(announceList.isList()) {
+    extractAnnounceList(announceList);
+  } else {
+    const bencode::BDE& announce = rootDict[BtContext::C_ANNOUNCE];
+    if(announce.isString()) {
+      extractAnnounceURI(announce);
+    }
+  }
+}
+
 void DefaultBtContext::extractUrlList(std::deque<std::string>& uris,
-				      const MetaEntry* obj)
+				      const bencode::BDE& bde)
 {
-  if(dynamic_cast<const List*>(obj)) {
-    const List* urlList = reinterpret_cast<const List*>(obj);
-    for(std::deque<MetaEntry*>::const_iterator itr = urlList->getList().begin();
-	itr != urlList->getList().end(); ++itr) {
-      const Data* data = dynamic_cast<const Data*>(*itr);
-      if(data) {
-	uris.push_back(data->toString());
+  if(bde.isList()) {
+    for(bencode::BDE::List::const_iterator itr = bde.listBegin();
+	itr != bde.listEnd(); ++itr) {
+      if((*itr).isString()) {
+	uris.push_back((*itr).s());
       }
     }
-  } else if(dynamic_cast<const Data*>(obj)) {
-    const Data* urlData = reinterpret_cast<const Data*>(obj);
-    uris.push_back(urlData->toString());
+  } else if(bde.isString()) {
+    uris.push_back(bde.s());
   }
 }
 
-void DefaultBtContext::extractNodes(const List* nodes)
+void DefaultBtContext::extractNodes(const bencode::BDE& nodesList)
 {
-  
-  for(std::deque<MetaEntry*>::const_iterator i = nodes->getList().begin();
-      i != nodes->getList().end(); ++i) {
-    const List* addrPair = dynamic_cast<const List*>(*i);
-    if(!addrPair || addrPair->getList().size() != 2) {
-      continue;
-    }
-    const Data* hostname = dynamic_cast<const Data*>(addrPair->getList()[0]);
-    if(!hostname) {
+  if(!nodesList.isList()) {
+    return;
+  }
+  for(bencode::BDE::List::const_iterator i = nodesList.listBegin();
+      i != nodesList.listEnd(); ++i) {
+    const bencode::BDE& addrPairList = (*i);
+    if(!addrPairList.isList() || addrPairList.size() != 2) {
       continue;
     }
-    std::string h = hostname->toString();
-    if(Util::trim(h).empty()) {
+    const bencode::BDE& hostname = addrPairList[0];
+    if(!hostname.isString()) {
       continue;
     }
-    const Data* port = dynamic_cast<const Data*>(addrPair->getList()[1]);
-    if(!port) {
+    if(Util::trim(hostname.s()).empty()) {
       continue;
     }
-    uint16_t p = port->toInt();
-    if(p == 0) {
+    const bencode::BDE& port = addrPairList[1];
+    if(!port.isInteger() || !(0 < port.i() && port.i() < 65536)) {
       continue;
     }
-    _nodes.push_back(std::pair<std::string, uint16_t>(h, p));
+    _nodes.push_back(std::pair<std::string, uint16_t>(hostname.s(), port.i()));
   }
 }
 
@@ -280,103 +270,78 @@ void DefaultBtContext::loadFromMemory(const unsigned char* content,
 				      const std::string& defaultName,
 				      const std::string& overrideName)
 {
-  SharedHandle<MetaEntry> rootEntry(MetaFileUtil::bdecoding(content, length));
-  const Dictionary* rootDic = dynamic_cast<const Dictionary*>(rootEntry.get());
-  if(!rootDic) {
-    throw DlAbortEx
-      (StringFormat("torrent file does not contain a root dictionary .").str());
-  }
-  processRootDictionary(rootDic, defaultName, overrideName);
+  processRootDictionary(bencode::decode(content, length), defaultName,
+			overrideName);
 }
 
 void DefaultBtContext::load(const std::string& torrentFile,
 			    const std::string& overrideName) {
-  SharedHandle<MetaEntry> rootEntry(MetaFileUtil::parseMetaFile(torrentFile));
-  const Dictionary* rootDic = dynamic_cast<const Dictionary*>(rootEntry.get());
-  if(!rootDic) {
-    throw DlAbortEx
-      (StringFormat("torrent file does not contain a root dictionary .").str());
-  }
-  processRootDictionary(rootDic, torrentFile, overrideName);
+  processRootDictionary(bencode::decodeFromFile(torrentFile), torrentFile,
+			overrideName);
 }
 
-void DefaultBtContext::processRootDictionary(const Dictionary* rootDic,
+void DefaultBtContext::processRootDictionary(const bencode::BDE& rootDict,
 					     const std::string& defaultName,
 					     const std::string& overrideName)
 {
   clear();
-  const Dictionary* infoDic =
-    dynamic_cast<const Dictionary*>(rootDic->get(BtContext::C_INFO));
-  if(!infoDic) {
-    throw DlAbortEx
-      (StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "info directory").str());
+  if(!rootDict.isDict()) {
+    throw DlAbortEx("torrent file does not contain a root dictionary.");
+  }
+  const bencode::BDE& infoDict = rootDict[BtContext::C_INFO];
+  if(!infoDict.isDict()) {
+    throw DlAbortEx(StringFormat(MSG_MISSING_BT_INFO,
+				 BtContext::C_INFO.c_str()).str());
   }
   // retrieve infoHash
-  BencodeVisitor v;
-  infoDic->accept(&v);
+  std::string encodedInfoDict = bencode::encode(infoDict);
   MessageDigestHelper::digest(infoHash, INFO_HASH_LENGTH,
 			      MessageDigestContext::SHA1,
-			      v.getBencodedData().c_str(),
-			      v.getBencodedData().size());
+			      encodedInfoDict.data(),
+			      encodedInfoDict.size());
   infoHashString = Util::toHex(infoHash, INFO_HASH_LENGTH);
   // calculate the number of pieces
-  const Data* pieceHashData =
-    dynamic_cast<const Data*>(infoDic->get(BtContext::C_PIECES));
-  if(!pieceHashData) {
-    throw DlAbortEx
-      (StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "pieces").str());
+  const bencode::BDE& piecesData = infoDict[BtContext::C_PIECES];
+  if(!piecesData.isString()) {
+    throw DlAbortEx(StringFormat(MSG_MISSING_BT_INFO,
+				 BtContext::C_PIECES.c_str()).str());
   }
-  if(pieceHashData->getLen() == 0) {
+  if(piecesData.s().empty()) {
     throw DlAbortEx("The length of piece hash is 0.");
   }
-  numPieces = pieceHashData->getLen()/PIECE_HASH_LENGTH;
+  numPieces = piecesData.s().size()/PIECE_HASH_LENGTH;
   if(numPieces == 0) {
     throw DlAbortEx("The number of pieces is 0.");
   }
   // retrieve piece length
-  const Data* pieceLengthData =
-    dynamic_cast<const Data*>(infoDic->get(BtContext::C_PIECE_LENGTH));
-  if(!pieceLengthData) {
-    throw DlAbortEx
-      (StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "piece length").str());
+  const bencode::BDE& pieceLengthData = infoDict[BtContext::C_PIECE_LENGTH];
+  if(!pieceLengthData.isInteger()) {
+    throw DlAbortEx(StringFormat(MSG_MISSING_BT_INFO,
+				 BtContext::C_PIECE_LENGTH.c_str()).str());
   }
-  pieceLength = pieceLengthData->toInt();
+  pieceLength = pieceLengthData.i();
   // retrieve piece hashes
-  extractPieceHash(pieceHashData->getData(), pieceHashData->getLen(),
-		   PIECE_HASH_LENGTH);
-  const Data* privateFlag =
-    dynamic_cast<const Data*>(infoDic->get(BtContext::C_PRIVATE));
-  if(privateFlag) {
-    if(privateFlag->toString() == BtContext::C_PRIVATE_ON) {
-      _private = true;
-    }
+  extractPieceHash(piecesData.s(), PIECE_HASH_LENGTH);
+  // private flag
+  const bencode::BDE& privateData = infoDict[BtContext::C_PRIVATE];
+  if(privateData.isInteger()) {
+    _private = (privateData.i() == 1);
   }
   // retrieve uri-list.
   // This implemantation obeys HTTP-Seeding specification:
   // see http://www.getright.com/seedtorrent.html
   std::deque<std::string> urlList;
-  extractUrlList(urlList, rootDic->get(BtContext::C_URL_LIST));
+  extractUrlList(urlList, rootDict[BtContext::C_URL_LIST]);
+
   // retrieve file entries
-  extractFileEntries(infoDic, defaultName, overrideName, urlList);
+  extractFileEntries(infoDict, defaultName, overrideName, urlList);
   if((totalLength+pieceLength-1)/pieceLength != numPieces) {
     throw DlAbortEx("Too few/many piece hash.");
   }
   // retrieve announce
-  const Data* announceData =
-    dynamic_cast<const Data*>(rootDic->get(BtContext::C_ANNOUNCE));
-  const List* announceListData =
-    dynamic_cast<const List*>(rootDic->get(BtContext::C_ANNOUNCE_LIST));
-  if(announceListData) {
-    extractAnnounceList(announceListData);
-  } else if(announceData) {
-    extractAnnounce(announceData);
-  }
+  extractAnnounce(rootDict);
   // retrieve nodes
-  const List* nodes =
-    dynamic_cast<const List*>(rootDic->get(BtContext::C_NODES));
-  if(nodes) {
-    extractNodes(nodes);
-  }
+  extractNodes(rootDict[BtContext::C_NODES]);
 }
 
 const std::string& DefaultBtContext::getPieceHash(size_t index) const {

+ 13 - 14
src/DefaultBtContext.h

@@ -36,17 +36,17 @@
 #define _D_DEFAULT_BT_CONTEXT_H_
 
 #include "BtContext.h"
-#include "A2STR.h"
+
 #include <iosfwd>
 
 namespace aria2 {
 
 class Randomizer;
 class Logger;
-class MetaEntry;
-class Dictionary;
-class List;
-class Data;
+
+namespace bencode {
+class BDE;
+}
 
 #define INFO_HASH_LENGTH 20
 #define PIECE_HASH_LENGTH 20
@@ -73,21 +73,20 @@ private:
   Logger* _logger;
 
   void clear();
-  void extractPieceHash(const unsigned char* hashData,
-			size_t hashDataLength,
-			size_t hashLength);
-  void extractFileEntries(const Dictionary* infoDic,
+  void extractPieceHash(const std::string& hashData, size_t hashLength);
+  void extractFileEntries(const bencode::BDE& infoDic,
 			  const std::string& defaultName,
 			  const std::string& overrideName,
 			  const std::deque<std::string>& urlList);
-  void extractAnnounce(const Data* announceData);
-  void extractAnnounceList(const List* announceListData);
+  void extractAnnounceURI(const bencode::BDE& announceData);
+  void extractAnnounceList(const bencode::BDE& announceListData);
+  void extractAnnounce(const bencode::BDE& rootDict);
 
-  void extractUrlList(std::deque<std::string>& uris, const MetaEntry* obj);
+  void extractUrlList(std::deque<std::string>& uris, const bencode::BDE& obj);
 
-  void extractNodes(const List* nodes);
+  void extractNodes(const bencode::BDE& nodes);
 
-  void processRootDictionary(const Dictionary* rootDic,
+  void processRootDictionary(const bencode::BDE& rootDic,
 			     const std::string& defaultName,
 			     const std::string& overrideName);
 

+ 16 - 19
src/DefaultPeerListProcessor.cc

@@ -34,9 +34,7 @@
 /* copyright --> */
 #include "DefaultPeerListProcessor.h"
 #include "Peer.h"
-#include "List.h"
-#include "Dictionary.h"
-#include "Data.h"
+#include "bencode.h"
 
 namespace aria2 {
 
@@ -48,31 +46,30 @@ DefaultPeerListProcessor::DefaultPeerListProcessor() {}
 
 DefaultPeerListProcessor::~DefaultPeerListProcessor() {}
 
-bool DefaultPeerListProcessor::canHandle(const MetaEntry* peersEntry) const {
-  const List* peersList = dynamic_cast<const List*>(peersEntry);
-  return peersList != 0;
+bool DefaultPeerListProcessor::canHandle(const bencode::BDE& peerData) const
+{
+  return peerData.isList();
 }
 
 void DefaultPeerListProcessor::extractPeer
-(std::deque<SharedHandle<Peer> >& peers, const MetaEntry* peersEntry)
+(std::deque<SharedHandle<Peer> >& peers, const bencode::BDE& peerData)
 {
-  const List* peersList = dynamic_cast<const List*>(peersEntry);
-  if(!peersList) {
+  if(!canHandle(peerData)) {
     return;
   }
-  const std::deque<MetaEntry*>& metaList = peersList->getList();
-  for(std::deque<MetaEntry*>::const_iterator itr = metaList.begin();
-      itr != metaList.end(); itr++) {
-    const Dictionary* peerDic = dynamic_cast<const Dictionary*>(*itr);
-    if(!peerDic) {
-      break;
+  for(bencode::BDE::List::const_iterator itr = peerData.listBegin();
+      itr != peerData.listEnd(); ++itr) {
+    const bencode::BDE& peerDict = *itr;
+    if(!peerDict.isDict()) {
+      continue;
     }
-    const Data* ip = dynamic_cast<const Data*>(peerDic->get(IP));
-    const Data* port = dynamic_cast<const Data*>(peerDic->get(PORT));
-    if(!ip || !port || !port->isNumber()) {
+    const bencode::BDE& ip = peerDict[IP];
+    const bencode::BDE& port = peerDict[PORT];
+    if(!ip.isString() || !port.isInteger() ||
+       !(0 < port.i() && port.i() < 65536)) {
       continue;
     }
-    PeerHandle peer(new Peer(ip->toString(), port->toInt()));
+    PeerHandle peer(new Peer(ip.s(), port.i()));
     peers.push_back(peer);
   }
 }

+ 2 - 2
src/DefaultPeerListProcessor.h

@@ -50,9 +50,9 @@ public:
   virtual ~DefaultPeerListProcessor();
 
   virtual void extractPeer
-  (std::deque<SharedHandle<Peer> >& peers, const MetaEntry* peersEntry);
+  (std::deque<SharedHandle<Peer> >& peers, const bencode::BDE& peerData);
 
-  virtual bool canHandle(const MetaEntry* peersEntry) const;
+  virtual bool canHandle(const bencode::BDE& peerData) const;
 };
 
 } // namespace aria2

+ 14 - 10
src/DelegatingPeerListProcessor.cc

@@ -32,10 +32,13 @@
  */
 /* copyright --> */
 #include "DelegatingPeerListProcessor.h"
+
+#include <algorithm>
+
 #include "DefaultPeerListProcessor.h"
 #include "CompactPeerListProcessor.h"
 #include "Peer.h"
-#include <algorithm>
+#include "bencode.h"
 
 namespace aria2 {
 
@@ -54,22 +57,23 @@ DelegatingPeerListProcessor::DelegatingPeerListProcessor()
 DelegatingPeerListProcessor::~DelegatingPeerListProcessor() {}
 
 void DelegatingPeerListProcessor::extractPeer
-(std::deque<SharedHandle<Peer> >& peers, const MetaEntry* peersEntry)
+(std::deque<SharedHandle<Peer> >& peers, const bencode::BDE& peerData)
 {
-  for(std::deque<SharedHandle<PeerListProcessor> >::iterator itr = processors.begin();
-      itr != processors.end(); itr++) {
+  for(std::deque<SharedHandle<PeerListProcessor> >::iterator itr =
+	processors.begin(); itr != processors.end(); ++itr) {
     PeerListProcessorHandle processor = *itr;
-    if(processor->canHandle(peersEntry)) {
-      processor->extractPeer(peers, peersEntry);
+    if(processor->canHandle(peerData)) {
+      processor->extractPeer(peers, peerData);
       break;
     }
   }
 }
 
-bool DelegatingPeerListProcessor::canHandle(const MetaEntry* peersEntry) const {
-  for(std::deque<SharedHandle<PeerListProcessor> >::const_iterator itr = processors.begin();
-      itr != processors.end(); itr++) {
-    if((*itr)->canHandle(peersEntry)) {
+bool DelegatingPeerListProcessor::canHandle(const bencode::BDE& peerData) const
+{
+  for(std::deque<SharedHandle<PeerListProcessor> >::const_iterator itr =
+	processors.begin(); itr != processors.end(); ++itr) {
+    if((*itr)->canHandle(peerData)) {
       return true;
     }
   }

+ 2 - 2
src/DelegatingPeerListProcessor.h

@@ -47,9 +47,9 @@ public:
   virtual ~DelegatingPeerListProcessor();
 
   virtual void extractPeer
-  (std::deque<SharedHandle<Peer> >& peers, const MetaEntry* peersEntry);
+  (std::deque<SharedHandle<Peer> >& peers, const bencode::BDE& peerData);
 
-  virtual bool canHandle(const MetaEntry* peersEntry) const;
+  virtual bool canHandle(const bencode::BDE& peerData) const;
 };
 
 } // namespace aria2

+ 8 - 4
src/PeerListProcessor.h

@@ -36,22 +36,26 @@
 #define _D_PEER_LIST_PROCESSOR_H_
 
 #include "common.h"
-#include "SharedHandle.h"
+
 #include <deque>
 
+#include "SharedHandle.h"
+
 namespace aria2 {
 
-class MetaEntry;
 class Peer;
+namespace bencode {
+class BDE;
+}
 
 class PeerListProcessor {
 public:
   virtual ~PeerListProcessor() {}
 
   virtual void extractPeer
-  (std::deque<SharedHandle<Peer> >& peers, const MetaEntry* peersEntry) = 0;
+  (std::deque<SharedHandle<Peer> >& peers, const bencode::BDE& peerData) = 0;
 
-  virtual bool canHandle(const MetaEntry* peersEntry) const = 0;
+  virtual bool canHandle(const bencode::BDE& peerData) const = 0;
 };
 
 typedef SharedHandle<PeerListProcessor> PeerListProcessorHandle;

+ 19 - 24
src/UTPexExtensionMessage.cc

@@ -34,17 +34,14 @@
 /* copyright --> */
 #include "UTPexExtensionMessage.h"
 #include "Peer.h"
-#include "Dictionary.h"
-#include "Data.h"
-#include "BencodeVisitor.h"
 #include "Util.h"
 #include "PeerMessageUtil.h"
 #include "PeerStorage.h"
 #include "CompactPeerListProcessor.h"
-#include "MetaFileUtil.h"
 #include "DlAbortEx.h"
 #include "message.h"
 #include "StringFormat.h"
+#include "bencode.h"
 
 namespace aria2 {
 
@@ -60,19 +57,20 @@ UTPexExtensionMessage::~UTPexExtensionMessage() {}
 
 std::string UTPexExtensionMessage::getBencodedData()
 {
-  SharedHandle<Dictionary> d(new Dictionary());
-  std::pair<std::string, std::string> freshPeerPair = createCompactPeerListAndFlag(_freshPeers);
-  std::pair<std::string, std::string> droppedPeerPair = createCompactPeerListAndFlag(_droppedPeers);
-  d->put("added", new Data(freshPeerPair.first));
-  d->put("added.f", new Data(freshPeerPair.second));
-  d->put("dropped", new Data(droppedPeerPair.first));
+  std::pair<std::string, std::string> freshPeerPair =
+    createCompactPeerListAndFlag(_freshPeers);
+  std::pair<std::string, std::string> droppedPeerPair =
+    createCompactPeerListAndFlag(_droppedPeers);
 
-  BencodeVisitor v;
-  d->accept(&v);
-  return v.getBencodedData();
+  bencode::BDE dict = bencode::BDE::dict();
+  dict["added"] = freshPeerPair.first;
+  dict["added.f"] = freshPeerPair.second;
+  dict["dropped"] = droppedPeerPair.first;
+  return bencode::encode(dict);
 }
 
-std::pair<std::string, std::string> UTPexExtensionMessage::createCompactPeerListAndFlag(const Peers& peers)
+std::pair<std::string, std::string>
+UTPexExtensionMessage::createCompactPeerListAndFlag(const Peers& peers)
 {
   std::string addrstring;
   std::string flagstring;
@@ -173,19 +171,16 @@ UTPexExtensionMessage::create(const unsigned char* data, size_t len)
 				 EXTENSION_NAME.c_str(), len).str());
   }
   UTPexExtensionMessageHandle msg(new UTPexExtensionMessage(*data));
-  SharedHandle<MetaEntry> root(MetaFileUtil::bdecoding(data+1, len-1));
-  if(root.isNull()) {
-    return msg;
-  }
-  const Dictionary* d = dynamic_cast<const Dictionary*>(root.get());
-  if(d) {
+
+  const bencode::BDE dict = bencode::decode(data+1, len-1);
+  if(dict.isDict()) {
     CompactPeerListProcessor proc;
-    const Data* added = dynamic_cast<const Data*>(d->get("added"));
-    if(added) {
+    const bencode::BDE& added = dict["added"];
+    if(added.isString()) {
       proc.extractPeer(msg->_freshPeers, added);
     }
-    const Data* dropped = dynamic_cast<const Data*>(d->get("dropped"));
-    if(dropped) {
+    const bencode::BDE& dropped = dict["dropped"];
+    if(dropped.isString()) {
       proc.extractPeer(msg->_droppedPeers, dropped);
     }
   }

+ 5 - 0
src/Util.h

@@ -172,6 +172,11 @@ public:
 
   static std::string toHex(const unsigned char* src, size_t len);
 
+  static std::string toHex(const char* src, size_t len)
+  {
+    return toHex(reinterpret_cast<const unsigned char*>(src), len);
+  }
+
   static std::string toHex(const std::string& src)
   {
     return toHex(reinterpret_cast<const unsigned char*>(src.c_str()), src.size());

+ 1 - 1
src/message.h

@@ -136,7 +136,7 @@
 #define MSG_TOO_SMALL_PAYLOAD_SIZE _("Too small payload size for %s, size=%d.")
 #define MSG_REMOVED_DEFUNCT_CONTROL_FILE _("Removed the defunct control file %s because the download file %s doesn't exist.")
 #define MSG_SHARE_RATIO_REPORT _("Your share ratio was %.1f, uploaded/downloaded=%sB/%sB")
-#define MSG_SOMETHING_MISSING_IN_TORRENT _("Missing %s in torrent metainfo.")
+#define MSG_MISSING_BT_INFO _("Missing %s in torrent metainfo.")
 #define MSG_NULL_TRACKER_RESPONSE _("Tracker returned null data.")
 #define MSG_WINSOCK_INIT_FAILD _("Windows socket library initialization failed")
 #define MSG_TIME_HAS_PASSED _("%d second(s) has passed. Stopping application.")

+ 5 - 5
test/DefaultBtContextTest.cc

@@ -372,7 +372,7 @@ void DefaultBtContextTest::testGetNodes()
     std::string memory =
       "d5:nodesl"
       "l11:192.168.0.1i6881ee"
-      "l11:192.168.0.24:6882e"
+      "l11:192.168.0.2i6882ee"
       "e4:infod4:name13:aria2.tar.bz26:lengthi262144e"
       "12:piece lengthi262144e"
       "6:pieces20:AAAAAAAAAAAAAAAAAAAA"
@@ -393,7 +393,7 @@ void DefaultBtContextTest::testGetNodes()
     std::string memory =
       "d5:nodesl"
       "l1: i6881ee"
-      "l11:192.168.0.24:6882e"
+      "l11:192.168.0.2i6882ee"
       "e4:infod4:name13:aria2.tar.bz26:lengthi262144e"
       "12:piece lengthi262144e"
       "6:pieces20:AAAAAAAAAAAAAAAAAAAA"
@@ -412,7 +412,7 @@ void DefaultBtContextTest::testGetNodes()
     std::string memory =
       "d5:nodesl"
       "l11:192.168.0.11:xe"
-      "l11:192.168.0.24:6882e"
+      "l11:192.168.0.2i6882ee"
       "e4:infod4:name13:aria2.tar.bz26:lengthi262144e"
       "12:piece lengthi262144e"
       "6:pieces20:AAAAAAAAAAAAAAAAAAAA"
@@ -431,7 +431,7 @@ void DefaultBtContextTest::testGetNodes()
     std::string memory =
       "d5:nodesl"
       "l11:192.168.0.1e"
-      "l11:192.168.0.24:6882e"
+      "l11:192.168.0.2i6882ee"
       "e4:infod4:name13:aria2.tar.bz26:lengthi262144e"
       "12:piece lengthi262144e"
       "6:pieces20:AAAAAAAAAAAAAAAAAAAA"
@@ -466,7 +466,7 @@ void DefaultBtContextTest::testGetNodes()
     std::string memory =
       "d5:nodesl"
       "ll11:192.168.0.1i6881eee"
-      "l11:192.168.0.24:6882e"
+      "l11:192.168.0.2i6882ee"
       "e4:infod4:name13:aria2.tar.bz26:lengthi262144e"
       "12:piece lengthi262144e"
       "6:pieces20:AAAAAAAAAAAAAAAAAAAA"

+ 11 - 12
test/DefaultPeerListProcessorTest.cc

@@ -1,9 +1,10 @@
 #include "DefaultPeerListProcessor.h"
-#include "MetaFileUtil.h"
+
+#include <cppunit/extensions/HelperMacros.h>
+
 #include "Exception.h"
-#include "Dictionary.h"
 #include "Peer.h"
-#include <cppunit/extensions/HelperMacros.h>
+#include "bencode.h"
 
 namespace aria2 {
 
@@ -30,13 +31,12 @@ void DefaultPeerListProcessorTest::testExtractPeer() {
   DefaultPeerListProcessor proc;
   std::string peersString = "d5:peersld2:ip11:192.168.0.17:peer id20:aria2-000000000000004:porti2006eeee";
 
-  SharedHandle<Dictionary> dic
-    (dynamic_cast<Dictionary*>(MetaFileUtil::bdecoding(peersString)));
+  const bencode::BDE dict = bencode::decode(peersString);
   
-  CPPUNIT_ASSERT(proc.canHandle(dic->get("peers")));
+  CPPUNIT_ASSERT(proc.canHandle(dict["peers"]));
 
   std::deque<SharedHandle<Peer> > peers;
-  proc.extractPeer(peers, dic->get("peers"));
+  proc.extractPeer(peers, dict["peers"]);
   CPPUNIT_ASSERT_EQUAL((size_t)1, peers.size());
   SharedHandle<Peer> peer = *peers.begin();
   CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer->ipaddr);
@@ -45,17 +45,16 @@ void DefaultPeerListProcessorTest::testExtractPeer() {
 
 void DefaultPeerListProcessorTest::testExtract2Peers() {
   DefaultPeerListProcessor proc;
-  std::string peersString = "d5:peersld2:ip11:192.168.0.17:peer id20:aria2-000000000000004:porti2006eed2:ip11:192.168.0.27:peer id20:aria2-000000000000004:porti2007eeee";
+  std::string peersString = "d5:peersld2:ip11:192.168.0.17:peer id20:aria2-000000000000004:porti65535eed2:ip11:192.168.0.27:peer id20:aria2-000000000000004:porti2007eeee";
 
-  SharedHandle<Dictionary> dic
-    (dynamic_cast<Dictionary*>(MetaFileUtil::bdecoding(peersString)));
+  const bencode::BDE dict = bencode::decode(peersString);
 
   std::deque<SharedHandle<Peer> > peers;
-  proc.extractPeer(peers, dic->get("peers"));
+  proc.extractPeer(peers, dict["peers"]);
   CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size());
   SharedHandle<Peer> peer = *peers.begin();
   CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer->ipaddr);
-  CPPUNIT_ASSERT_EQUAL((uint16_t)2006, peer->port);
+  CPPUNIT_ASSERT_EQUAL((uint16_t)65535, peer->port);
 
   peer = *(peers.begin()+1);
   CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.2"), peer->ipaddr);