Changeset 1144


Ignore:
Timestamp:
03/15/10 12:42:05 (4 years ago)
Author:
rakshasa
Message:
  • Added '-D' flag which turns of redirects for deprecated commands. Use this to ensure your scripts/webui.
  • Applied the magnet-uri patch.
Location:
trunk
Files:
2 added
56 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/libtorrent/src/dht/dht_node.cc

    r1040 r1144  
    4141#include "torrent/object.h" 
    4242 
    43 // For SACompact... 
    44 #include "download/download_info.h" 
     43#include "net/address_list.h" // For SA. 
    4544 
    4645#include "dht_node.h" 
  • trunk/libtorrent/src/dht/dht_router.cc

    r1138 r1144  
    4242 
    4343#include "torrent/dht_manager.h" 
     44#include "torrent/download_info.h" 
    4445#include "torrent/exceptions.h" 
    4546#include "utils/sha1.h" 
  • trunk/libtorrent/src/dht/dht_server.cc

    r1140 r1144  
    4343#include "torrent/exceptions.h" 
    4444#include "torrent/connection_manager.h" 
     45#include "torrent/download_info.h" 
    4546#include "torrent/object.h" 
    4647#include "torrent/object_stream.h" 
  • trunk/libtorrent/src/dht/dht_server.h

    r1138 r1144  
    4545#include "net/socket_datagram.h" 
    4646#include "net/throttle_node.h" 
    47 #include "download/download_info.h"  // for SocketAddressCompact 
    4847#include "torrent/hash_string.h" 
    4948#include "torrent/object_raw_bencode.h" 
  • trunk/libtorrent/src/dht/dht_tracker.h

    r1138 r1144  
    4343#include <rak/socket_address.h> 
    4444 
    45 #include "download/download_info.h"  // for SocketAddressCompact 
     45#include "net/address_list.h" // For SA. 
    4646#include "torrent/object_raw_bencode.h" 
    4747 
  • trunk/libtorrent/src/download/Makefile.am

    r1010 r1144  
    1515        download_constructor.cc \ 
    1616        download_constructor.h \ 
    17         download_info.h \ 
    1817        download_main.cc \ 
    1918        download_main.h \ 
  • trunk/libtorrent/src/download/download_constructor.cc

    r1138 r1144  
    8282 
    8383void 
    84 DownloadConstructor::initialize(const Object& b) { 
     84DownloadConstructor::initialize(Object& b) { 
     85  if (!b.has_key_map("info") && b.has_key_string("magnet-uri")) 
     86    parse_magnet_uri(b, b.get_key_string("magnet-uri")); 
     87 
    8588  if (b.has_key_string("encoding")) 
    8689    m_defaultEncoding = b.get_key_string("encoding"); 
    8790 
    88   m_download->info()->set_private(b.get_key("info").has_key_value("private") &&  
    89                                   b.get_key("info").get_key_value("private") == 1); 
     91  m_download->info()->change_flags(DownloadInfo::flag_private, 
     92                                   b.get_key("info").has_key_value("private") &&  
     93                                   b.get_key("info").get_key_value("private") == 1); 
    9094 
    9195  parse_name(b.get_key("info")); 
     
    137141    throw input_error("Download has unordered info dictionary."); 
    138142 
    139   uint32_t chunkSize = b.get_key_value("piece length"); 
    140  
    141   if (chunkSize <= (1 << 10) || chunkSize > (128 << 20)) 
    142     throw input_error("Torrent has an invalid \"piece length\"."); 
     143  uint32_t chunkSize; 
     144 
     145  if (b.has_key_value("meta_download") && b.get_key_value("meta_download")) 
     146    m_download->info()->set_flags(DownloadInfo::flag_meta_download); 
     147 
     148  if (m_download->info()->is_meta_download()) { 
     149    if (b.get_key_string("pieces").length() != HashString::size_data) 
     150      throw input_error("Meta-download has invalid piece data."); 
     151 
     152    chunkSize = 1; 
     153    parse_single_file(b, chunkSize); 
     154 
     155  } else { 
     156    chunkSize = b.get_key_value("piece length"); 
     157 
     158    if (chunkSize <= (1 << 10) || chunkSize > (128 << 20)) 
     159      throw input_error("Torrent has an invalid \"piece length\"."); 
     160  } 
    143161 
    144162  if (b.has_key("length")) { 
     
    149167    fileList->set_root_dir("./" + m_download->info()->name()); 
    150168 
    151   } else { 
     169  } else if (!m_download->info()->is_meta_download()) { 
    152170    throw input_error("Torrent must have either length or files entry."); 
    153171  } 
    154172 
    155   if (fileList->size_bytes() == 0) 
     173  if (fileList->size_bytes() == 0 && !m_download->info()->is_meta_download()) 
    156174    throw input_error("Torrent has zero length."); 
    157175 
     
    240258 
    241259  FileList* fileList = m_download->main()->file_list(); 
    242   fileList->initialize(b.get_key_value("length"), chunkSize); 
     260  fileList->initialize(chunkSize == 1 ? 1 : b.get_key_value("length"), chunkSize); 
    243261  fileList->set_multi_file(false); 
    244262 
     
    344362} 
    345363 
    346 } 
     364static const char* 
     365parse_base32_sha1(const char* pos, HashString& hash) { 
     366  HashString::iterator hashItr = hash.begin(); 
     367 
     368  static const int base_shift = 8+8-5; 
     369  int shift = base_shift; 
     370  uint16_t decoded = 0; 
     371 
     372  while (*pos) { 
     373    char c = *pos++; 
     374    uint16_t value; 
     375 
     376    if (c >= 'A' && c <= 'Z') 
     377      value = c - 'A'; 
     378    else if (c >= 'a' && c <= 'z') 
     379      value = c - 'a'; 
     380    else if (c >= '2' && c <= '7') 
     381      value = 26 + c - '2'; 
     382    else if (c == '&') 
     383      break; 
     384    else 
     385      return NULL; 
     386 
     387    decoded |= (value << shift); 
     388    if (shift <= 8) { 
     389      // Too many characters for a base32 SHA1. 
     390      if (hashItr == hash.end()) 
     391        return NULL; 
     392 
     393      *hashItr++ = (decoded >> 8); 
     394      decoded <<= 8; 
     395      shift += 3; 
     396    } else { 
     397      shift -= 5; 
     398    } 
     399  } 
     400 
     401  return hashItr != hash.end() || shift != base_shift ? NULL : pos; 
     402} 
     403 
     404void 
     405DownloadConstructor::parse_magnet_uri(Object& b, const std::string& uri) { 
     406  if (std::strncmp(uri.c_str(), "magnet:?", 8)) 
     407    throw input_error("Invalid magnet URI."); 
     408 
     409  const char* pos = uri.c_str() + 8; 
     410 
     411  Object trackers(Object::create_list()); 
     412  HashString hash; 
     413  bool hashValid = false; 
     414 
     415  while (*pos) { 
     416    const char* tagStart = pos; 
     417    while (*pos != '=') 
     418      if (!*pos++) 
     419        break; 
     420 
     421    raw_string tag(tagStart, pos - tagStart); 
     422    pos++; 
     423 
     424    // hash may be base32 encoded (optional in BEP 0009 and common practice) 
     425    if (raw_bencode_equal_c_str(tag, "xt")) { 
     426      if (strncmp(pos, "urn:btih:", 9)) 
     427        throw input_error("Invalid magnet URI."); 
     428 
     429      pos += 9; 
     430 
     431      const char* nextPos = parse_base32_sha1(pos, hash); 
     432      if (nextPos != NULL) { 
     433        pos = nextPos; 
     434        hashValid = true; 
     435        continue; 
     436      } 
     437    } 
     438 
     439    // everything else, including sometimes the hash, is url encoded. 
     440    std::string decoded; 
     441    while (*pos) { 
     442      char c = *pos++; 
     443      if (c == '%') { 
     444        if (sscanf(pos, "%02hhx", &c) != 1) 
     445          throw input_error("Invalid magnet URI."); 
     446 
     447        pos += 2; 
     448 
     449      } else if (c == '&') { 
     450        break; 
     451      } 
     452 
     453      decoded.push_back(c); 
     454    } 
     455 
     456    if (raw_bencode_equal_c_str(tag, "xt")) { 
     457      // url-encoded hash as per magnet URN specs 
     458      if (decoded.length() == hash.size_data) { 
     459        hash = *HashString::cast_from(decoded); 
     460        hashValid = true; 
     461 
     462      // hex-encoded hash as per BEP 0009 
     463      } else if (decoded.length() == hash.size_data * 2) { 
     464        std::string::iterator hexItr = decoded.begin(); 
     465        for (HashString::iterator itr = hash.begin(), last = hash.end(); itr != last; itr++, hexItr += 2) 
     466          *itr = (rak::hexchar_to_value(*hexItr) << 4) + rak::hexchar_to_value(*(hexItr + 1)); 
     467        hashValid = true; 
     468 
     469      } else { 
     470        throw input_error("Invalid magnet URI."); 
     471      } 
     472 
     473    } else if (raw_bencode_equal_c_str(tag, "tr")) { 
     474      trackers.insert_back(Object::create_list()).insert_back(decoded); 
     475    } 
     476    // could also handle "dn" = display name (torrent name), but we can't really use that 
     477  } 
     478 
     479  if (!hashValid) 
     480    throw input_error("Invalid magnet URI."); 
     481 
     482  Object& info = b.insert_key("info", Object::create_map()); 
     483  info.insert_key("pieces", hash.str()); 
     484  info.insert_key("name", rak::transform_hex(hash.str()) + ".meta"); 
     485  info.insert_key("meta_download", (int64_t)1); 
     486 
     487  if (!trackers.as_list().empty()) { 
     488    b.insert_preserve_copy("announce", trackers.as_list().begin()->as_list().begin()->as_string()); 
     489    b.insert_preserve_type("announce-list", trackers); 
     490  } 
     491} 
     492 
     493} 
  • trunk/libtorrent/src/download/download_constructor.h

    r1013 r1144  
    5656  DownloadConstructor() : m_download(NULL), m_encodingList(NULL) {} 
    5757 
    58   void                initialize(const Object& b); 
     58  void                initialize(Object& b); 
    5959 
    6060  void                set_download(DownloadWrapper* d)         { m_download = d; } 
     
    6565  void                parse_tracker(const Object& b); 
    6666  void                parse_info(const Object& b); 
     67  void                parse_magnet_uri(Object& b, const std::string& uri); 
    6768 
    6869  void                add_tracker_group(const Object& b); 
  • trunk/libtorrent/src/download/download_main.cc

    r1091 r1144  
    5959#include "chunk_selector.h" 
    6060#include "chunk_statistics.h" 
    61 #include "download_info.h" 
    6261#include "download_main.h" 
    6362#include "download_manager.h" 
     
    6564 
    6665namespace torrent { 
     66 
     67DownloadInfo::DownloadInfo() : 
     68  m_flags(flag_compact | flag_accepting_new_peers | flag_pex_enabled | flag_pex_active), 
     69 
     70  m_upRate(60), 
     71  m_downRate(60), 
     72  m_skipRate(60), 
     73   
     74  m_uploadedBaseline(0), 
     75  m_completedBaseline(0), 
     76  m_sizePex(0), 
     77  m_maxSizePex(8), 
     78  m_metadataSize(0), 
     79   
     80  m_loadDate(rak::timer::current_seconds()) { 
     81} 
    6782 
    6883DownloadMain::DownloadMain() : 
     
    155170  m_chunkStatistics->initialize(file_list()->size_chunks()); 
    156171 
    157   info()->set_open(true); 
     172  info()->set_flags(DownloadInfo::flag_open); 
    158173} 
    159174 
     
    166181    return; 
    167182 
    168   info()->set_open(false); 
     183  info()->unset_flags(DownloadInfo::flag_open); 
    169184 
    170185  // Don't close the tracker manager here else it will cause STOPPED 
     
    191206    throw internal_error("Tried to start an active download"); 
    192207 
    193   info()->set_active(true); 
     208  info()->set_flags(DownloadInfo::flag_active); 
    194209  m_lastConnectedSize = 0; 
    195210 
     
    207222  // Set this early so functions like receive_connect_peers() knows 
    208223  // not to eat available peers. 
    209   info()->set_active(false); 
     224  info()->unset_flags(DownloadInfo::flag_active); 
    210225 
    211226  m_slotStopHandshakes(this); 
     
    355370      m_connectionList->size() < m_connectionList->min_size() / 2 && 
    356371      m_peerList.available_list()->size() < m_peerList.available_list()->max_size() / 4) { 
    357     m_info->set_pex_active(true); 
     372    m_info->set_flags(DownloadInfo::flag_pex_active); 
    358373 
    359374    // Only set PEX_ENABLE if we don't have max_size_pex set to zero. 
     
    365380//              m_peerList.available_list()->size() >= m_peerList.available_list()->max_size() / 2) { 
    366381    togglePex = PeerConnectionBase::PEX_DISABLE; 
    367     m_info->set_pex_active(false); 
     382    m_info->unset_flags(DownloadInfo::flag_pex_active); 
    368383  } 
    369384 
     
    456471} 
    457472 
    458 } 
     473void 
     474DownloadMain::set_metadata_size(size_t size) { 
     475  if (m_info->is_meta_download()) { 
     476    if (m_fileList.size_bytes() < 2) 
     477      file_list()->reset_filesize(size); 
     478    else if (size != m_fileList.size_bytes()) 
     479      throw communication_error("Peer-supplied metadata size mismatch."); 
     480 
     481  } else if (m_info->metadata_size() && m_info->metadata_size() != size) { 
     482      throw communication_error("Peer-supplied metadata size mismatch."); 
     483  } 
     484 
     485  m_info->set_metadata_size(size); 
     486} 
     487 
     488} 
  • trunk/libtorrent/src/download/download_main.h

    r1091 r1144  
    4444#include "globals.h" 
    4545 
    46 #include "download_info.h" 
    4746#include "delegator.h" 
    4847 
     
    5049#include "download/available_list.h" 
    5150#include "net/data_buffer.h" 
     51#include "torrent/download_info.h" 
    5252#include "torrent/data/file_list.h" 
    5353#include "torrent/peer/peer_list.h" 
     
    116116 
    117117  bool                want_pex_msg()                             { return m_info->is_pex_active() && m_peerList.available_list()->want_more(); };  
     118 
     119  void                set_metadata_size(size_t s); 
    118120 
    119121  // Carefull with these. 
  • trunk/libtorrent/src/download/download_wrapper.cc

    r1129 r1144  
    102102  info()->mutable_local_id().assign(id.c_str()); 
    103103 
    104   info()->slot_completed() = rak::make_mem_fun(m_main.file_list(), &FileList::completed_bytes); 
    105   info()->slot_left()      = rak::make_mem_fun(m_main.file_list(), &FileList::left_bytes); 
     104  info()->slot_left() = sigc::mem_fun(m_main.file_list(), &FileList::left_bytes); 
     105  info()->slot_completed() = sigc::mem_fun(m_main.file_list(), &FileList::completed_bytes); 
    106106 
    107107  m_main.slot_hash_check_add(rak::make_mem_fun(this, &DownloadWrapper::check_chunk_hash)); 
     
    277277      // If PEX was disabled since the last peer exchange, deactivate it now. 
    278278      } else if (info()->is_pex_active()) { 
    279         info()->set_pex_active(false); 
     279        info()->unset_flags(DownloadInfo::flag_pex_active); 
    280280 
    281281        for (ConnectionList::iterator itr = m_main.connection_list()->begin(); itr != m_main.connection_list()->end(); ++itr) 
  • trunk/libtorrent/src/download/download_wrapper.h

    r1016 r1144  
    4343 
    4444#include "data/chunk_handle.h" 
    45 #include "download/download_info.h" 
    4645 
    4746#include "download_main.h" 
  • trunk/libtorrent/src/net/address_list.cc

    r1138 r1144  
    3939#include <algorithm> 
    4040#include <rak/functional.h> 
    41  
    42 #include "download/download_info.h"  // for SocketAddressCompact 
    4341 
    4442#include "address_list.h" 
  • trunk/libtorrent/src/net/address_list.h

    r1138 r1144  
    5454 
    5555  void                        parse_address_compact(raw_string s); 
    56   void                        parse_address_compact(const std::string& s) { 
    57     return parse_address_compact(raw_string(s.data(), s.size())); 
    58   } 
     56  void                        parse_address_compact(const std::string& s); 
    5957 
    6058private: 
     
    7674}; 
    7775 
     76inline void 
     77AddressList::parse_address_compact(const std::string& s) { 
     78  return parse_address_compact(raw_string(s.data(), s.size())); 
     79} 
     80 
     81// Move somewhere else. 
     82struct SocketAddressCompact { 
     83  SocketAddressCompact() {} 
     84  SocketAddressCompact(uint32_t a, uint16_t p) : addr(a), port(p) {} 
     85  SocketAddressCompact(const rak::socket_address_inet* sa) : addr(sa->address_n()), port(sa->port_n()) {} 
     86 
     87  operator rak::socket_address () const { 
     88    rak::socket_address sa; 
     89    sa.sa_inet()->clear(); 
     90    sa.sa_inet()->set_port_n(port); 
     91    sa.sa_inet()->set_address_n(addr); 
     92 
     93    return sa; 
     94  } 
     95 
     96  uint32_t addr; 
     97  uint16_t port; 
     98 
     99  const char*         c_str() const { return reinterpret_cast<const char*>(this); } 
     100} __attribute__ ((packed)); 
     101 
    78102} 
    79103 
  • trunk/libtorrent/src/net/data_buffer.h

    r1062 r1144  
    4949 
    5050  DataBuffer          clone() const        { DataBuffer d = *this; d.m_owned = false; return d; } 
     51  DataBuffer          release()            { DataBuffer d = *this; set(NULL, NULL, false); return d; } 
    5152 
    5253  char*               data() const         { return m_data; } 
     
    7172inline void 
    7273DataBuffer::clear() { 
    73   if (!empty()) 
     74  if (!empty() && m_owned) 
    7475    delete[] m_data; 
    7576 
  • trunk/libtorrent/src/net/socket_base.cc

    r1013 r1144  
    4848namespace torrent { 
    4949 
    50 char* SocketBase::m_nullBuffer = new char[1 << 17]; 
     50char* SocketBase::m_nullBuffer = new char[SocketBase::null_buffer_size]; 
    5151 
    5252SocketBase::~SocketBase() { 
  • trunk/libtorrent/src/net/socket_base.h

    r1013 r1144  
    6969  void operator = (const SocketBase&); 
    7070 
     71  static const size_t null_buffer_size = 1 << 17; 
     72 
    7173  static char*        m_nullBuffer; 
    7274}; 
  • trunk/libtorrent/src/protocol/Makefile.am

    r1058 r1144  
    1818        peer_connection_leech.cc \ 
    1919        peer_connection_leech.h \ 
     20        peer_connection_metadata.cc \ 
     21        peer_connection_metadata.h \ 
    2022        peer_factory.cc \ 
    2123        peer_factory.h \ 
  • trunk/libtorrent/src/protocol/extensions.cc

    r1143 r1144  
    4444#include "download/available_list.h" 
    4545#include "download/download_main.h" 
     46#include "download/download_manager.h" 
     47#include "download/download_wrapper.h" 
    4648#include "protocol/peer_connection_base.h" 
    4749#include "torrent/connection_manager.h" 
     
    5860const ExtHandshakeMessage::key_list_type ExtHandshakeMessage::keys = { 
    5961  { key_e,            "e" }, 
     62  { key_m_utMetadata, "m::ut_metadata" }, 
    6063  { key_m_utPex,      "m::ut_pex" }, 
     64  { key_metadataSize, "metadata_size" }, 
    6165  { key_p,            "p" }, 
    6266  { key_reqq,         "reqq" }, 
     
    6973}; 
    7074 
     75// DEBUG: Add type info. 
     76template <> 
     77const ExtMetadataMessage::key_list_type ExtMetadataMessage::keys = { 
     78  { key_msgType,      "msg_type" }, 
     79  { key_piece,        "piece" }, 
     80  { key_totalSize,    "total_size" }, 
     81}; 
     82 
    7183struct message_type { 
    7284  const char* key; 
     
    7688const message_type message_keys[] = {  
    7789  { "HANDSHAKE", key_handshake_LAST }, 
    78   { "ut_pex", key_m_utPex } 
     90  { "ut_pex", key_m_utPex }, 
     91  { "metadata_size", key_m_utMetadata } 
    7992}; 
    8093 
     
    134147  message[key_reqq] = 2048;  // maximum request queue size 
    135148 
     149  if (!m_download->info()->is_meta_download()) 
     150    message[key_metadataSize] = m_download->info()->metadata_size(); 
     151 
    136152  message[key_m_utPex] = is_local_enabled(UT_PEX) ? UT_PEX : 0; 
     153  message[key_m_utMetadata] = UT_METADATA; 
    137154 
    138155  char buffer[1024]; 
     
    201218void 
    202219ProtocolExtension::read_start(int type, uint32_t length, bool skip) { 
    203   if (is_default() || (type >= FIRST_INVALID) || length > (1 << 14)) 
     220  if (is_default() || (type >= FIRST_INVALID) || length > (1 << 15)) 
    204221    throw communication_error("Received invalid extension message."); 
    205222 
     
    221238} 
    222239 
    223 void 
     240bool 
    224241ProtocolExtension::read_done() { 
     242  bool result = true; 
     243 
    225244  try { 
    226245    switch(m_readType) { 
    227     case SKIP_EXTENSION: 
    228       delete [] m_read; 
    229       m_read = NULL; 
    230       return; 
    231  
    232     case HANDSHAKE: 
    233       parse_handshake(); 
    234       break; 
    235  
    236     case UT_PEX: 
    237       parse_ut_pex(); 
    238       break; 
    239  
     246    case SKIP_EXTENSION: break; 
     247    case HANDSHAKE: result = parse_handshake(); break; 
     248    case UT_PEX:    result = parse_ut_pex(); break; 
     249    case UT_METADATA: result = parse_ut_metadata(); break; 
    240250    default: 
    241251      throw internal_error("ProtocolExtension::read_done called with invalid extension type."); 
     
    253263  m_readType = FIRST_INVALID; 
    254264  m_flags |= flag_received_ext; 
     265 
     266  return result; 
    255267} 
    256268 
     
    266278} 
    267279 
    268 void 
     280bool 
    269281ProtocolExtension::parse_handshake() { 
    270282  ExtHandshakeMessage message; 
     
    304316    m_maxQueueLength = message[key_reqq].as_value(); 
    305317 
     318  if (message[key_metadataSize].is_value()) 
     319    m_download->set_metadata_size(message[key_metadataSize].as_value()); 
     320 
    306321  m_flags &= ~flag_initial_handshake; 
    307 } 
    308  
    309 void 
     322 
     323  return true; 
     324} 
     325 
     326bool 
    310327ProtocolExtension::parse_ut_pex() { 
    311328  // Ignore message if we're still in the handshake (no connection 
     
    317334  // TODO: Check if pex is enabled? 
    318335  if (!message[key_pex_added].is_raw_string()) 
    319     return; 
     336    return true; 
    320337 
    321338  raw_string peers = message[key_pex_added].as_raw_string(); 
    322339 
    323340  if (peers.empty()) 
    324     return; 
     341    return true; 
    325342 
    326343  // TODO: Sort the list before adding it. 
     
    331348  
    332349  m_download->peer_list()->insert_available(&l); 
    333 } 
    334  
    335 } 
     350 
     351  return true; 
     352} 
     353 
     354bool 
     355ProtocolExtension::parse_ut_metadata() { 
     356  ExtMetadataMessage message; 
     357 
     358  // Piece data comes after bencoded extension message. 
     359  const char* dataStart = static_map_read_bencode(m_read, m_readPos, message); 
     360 
     361  switch(message[key_msgType].as_value()) { 
     362  case 0: 
     363    // Can't process new request while still having data to send. 
     364    if (has_pending_message()) 
     365      return false; 
     366 
     367    send_metadata_piece(message[key_piece].as_value()); 
     368    break; 
     369 
     370  case 1: 
     371    if (m_connection == NULL) 
     372      break; 
     373 
     374    m_connection->receive_metadata_piece(message[key_piece].as_value(), dataStart, m_readPos - dataStart); 
     375    break; 
     376 
     377  case 2: 
     378    if (m_connection == NULL) 
     379      break; 
     380 
     381    m_connection->receive_metadata_piece(message[key_piece].as_value(), NULL, 0); 
     382    break; 
     383  }; 
     384 
     385  return true; 
     386} 
     387 
     388void 
     389ProtocolExtension::send_metadata_piece(size_t piece) { 
     390  // Reject out-of-range piece, or if we don't have the complete metadata yet. 
     391  size_t metadataSize = m_download->info()->metadata_size(); 
     392  size_t pieceEnd = (metadataSize + metadata_piece_size - 1) >> metadata_piece_shift; 
     393 
     394  if (m_download->info()->is_meta_download() || piece >= pieceEnd) { 
     395    // reject: { "msg_type" => 2, "piece" => ... } 
     396    m_pendingType = UT_METADATA; 
     397    m_pending = build_bencode(40, "d8:msg_typei2e5:piecei%zuee", piece); 
     398    return; 
     399  } 
     400 
     401  // These messages will be rare, so we'll just build the 
     402  // metadata here instead of caching it uselessly. 
     403  char* buffer = new char[metadataSize]; 
     404  object_buffer_t result = object_write_bencode_c(object_write_to_buffer, NULL, object_buffer_t(buffer, buffer + metadataSize),  
     405                                                 &(*manager->download_manager()->find(m_download->info()))->bencode()->get_key("info")); 
     406 
     407  // data: { "msg_type" => 1, "piece" => ..., "total_size" => ... } followed by piece data (outside of dictionary) 
     408  size_t length = piece == pieceEnd - 1 ? m_download->info()->metadata_size() % metadata_piece_size : metadata_piece_size; 
     409  m_pendingType = UT_METADATA; 
     410  m_pending = build_bencode(length + 128, "d8:msg_typei1e5:piecei%zue10:total_sizei%zuee", piece, metadataSize); 
     411 
     412  memcpy(m_pending.end(), buffer + (piece << metadata_piece_shift), length); 
     413  m_pending.set(m_pending.data(), m_pending.end() + length, m_pending.owned()); 
     414  delete [] buffer; 
     415} 
     416 
     417bool 
     418ProtocolExtension::request_metadata_piece(const Piece* p) { 
     419  if (p->offset() % metadata_piece_size) 
     420    throw internal_error("ProtocolExtension::request_metadata_piece got misaligned piece offset."); 
     421 
     422  if (has_pending_message()) 
     423    return false; 
     424 
     425  m_pendingType = UT_METADATA; 
     426  m_pending = build_bencode(40, "d8:msg_typei0e5:piecei%uee", (unsigned)(p->offset() >> metadata_piece_shift)); 
     427  return true; 
     428} 
     429 
     430} 
  • trunk/libtorrent/src/protocol/extensions.h

    r1141 r1144  
    4545#include "torrent/object_static_map.h" 
    4646 
    47 #include "download/download_info.h" 
     47#include "torrent/download_info.h" 
     48#include "net/address_list.h" 
    4849#include "net/data_buffer.h" 
    4950 
     
    6263    HANDSHAKE = 0, 
    6364    UT_PEX, 
     65    UT_METADATA, 
    6466 
    6567    FIRST_INVALID,    // first invalid message ID 
     
    8385  static const int    extension_count = FIRST_INVALID - HANDSHAKE - 1; 
    8486 
     87  // Fixed size of a metadata piece (16 KB). 
     88  static const size_t metadata_piece_shift = 14; 
     89  static const size_t metadata_piece_size  = 1 << metadata_piece_shift; 
     90 
    8591  ProtocolExtension(); 
    8692  ~ProtocolExtension() { delete [] m_read; } 
     
    9399 
    94100  void                set_info(PeerInfo* peerInfo, DownloadMain* download) { m_peerInfo = peerInfo; m_download = download; } 
     101  void                set_connection(PeerConnectionBase* c)                { m_connection = c; } 
    95102 
    96103  DataBuffer          generate_handshake_message(); 
     
    114121  // Handle reading extension data from peer. 
    115122  void                read_start(int type, uint32_t length, bool skip); 
    116   void                read_done(); 
     123  bool                read_done(); 
    117124 
    118125  char*               read_position()                  { return m_readPos; } 
     
    134141  void                reset()                          { std::memset(&m_idMap, 0, sizeof(m_idMap)); } 
    135142 
     143  bool                request_metadata_piece(const Piece* p); 
     144 
     145  // To handle cases where the extension protocol needs to send a reply. 
     146  bool                has_pending_message() const      { return m_pendingType != HANDSHAKE; } 
     147  MessageType         pending_message_type() const     { return m_pendingType; } 
     148  DataBuffer          pending_message_data()           { return m_pending.release(); } 
     149  void                clear_pending_message()          { if (m_pending.empty()) m_pendingType = HANDSHAKE; } 
     150 
    136151private: 
    137   void                parse_handshake(); 
    138   void                parse_ut_pex(); 
     152  bool                parse_handshake(); 
     153  bool                parse_ut_pex(); 
     154  bool                parse_ut_metadata(); 
    139155 
    140156  static DataBuffer   build_bencode(size_t maxLength, const char* format, ...) ATTRIBUTE_PRINTF(2); 
    141157 
    142158  void                peer_toggle_remote(int type, bool active); 
     159  void                send_metadata_piece(size_t piece); 
    143160 
    144161  // Map of IDs peer uses for each extension message type, excluding 
     
    151168  PeerInfo*           m_peerInfo; 
    152169  DownloadMain*       m_download; 
     170  PeerConnectionBase* m_connection; 
    153171 
    154172  uint8_t             m_readType; 
     
    156174  char*               m_read; 
    157175  char*               m_readPos; 
     176 
     177  MessageType         m_pendingType; 
     178  DataBuffer          m_pending; 
    158179}; 
    159180 
     
    164185enum ext_handshake_keys { 
    165186  key_e, 
     187  key_m_utMetadata, 
    166188  key_m_utPex, 
     189  key_metadataSize, 
    167190  key_p, 
    168191  key_reqq, 
     
    176199}; 
    177200 
     201enum ext_metadata_keys { 
     202  key_msgType, 
     203  key_piece, 
     204  key_totalSize, 
     205  key_metadata_LAST 
     206}; 
     207 
    178208typedef static_map_type<ext_handshake_keys, key_handshake_LAST> ExtHandshakeMessage; 
    179209typedef static_map_type<ext_pex_keys, key_pex_LAST> ExtPEXMessage; 
     210typedef static_map_type<ext_metadata_keys, key_metadata_LAST> ExtMetadataMessage; 
    180211 
    181212// 
     
    190221  m_peerInfo(NULL), 
    191222  m_download(NULL), 
     223  m_connection(NULL), 
    192224  m_readType(FIRST_INVALID), 
    193   m_read(NULL) { 
     225  m_read(NULL), 
     226  m_pendingType(HANDSHAKE) { 
    194227 
    195228  reset(); 
     229  set_local_enabled(UT_METADATA); 
    196230} 
    197231 
  • trunk/libtorrent/src/protocol/handshake.cc

    r1142 r1144  
    3737#include "config.h" 
    3838 
    39 #include "download/download_info.h" 
    4039#include "download/download_main.h" 
    4140#include "net/throttle_list.h" 
    4241#include "torrent/dht_manager.h" 
     42#include "torrent/download_info.h" 
    4343#include "torrent/exceptions.h" 
    4444#include "torrent/error.h" 
     
    751751    case READ_MESSAGE: 
    752752    case POST_HANDSHAKE: 
     753      // For meta-downloads, we aren't interested in the bitfield or 
     754      // extension messages here, PCMetadata handles all that. The 
     755      // bitfield only refers to the single-chunk meta-data, so fake that. 
     756      if (m_download->info()->is_meta_download()) { 
     757        m_bitfield.set_size_bits(1); 
     758        m_bitfield.allocate(); 
     759        m_bitfield.set(0); 
     760        read_done(); 
     761        break; 
     762      } 
     763 
    753764      fill_read_buffer(5); 
    754765 
     
    10571068  m_peerInfo->mutable_id().assign((const char*)m_readBuffer.position()); 
    10581069  m_readBuffer.consume(20); 
     1070 
     1071  // For meta downloads, we require support of the extension protocol. 
     1072  if (m_download->info()->is_meta_download() && !m_peerInfo->supports_extensions()) 
     1073    throw handshake_error(ConnectionManager::handshake_dropped, e_handshake_unwanted_connection); 
    10591074} 
    10601075 
  • trunk/libtorrent/src/protocol/handshake_manager.cc

    r1089 r1144  
    4141#include "torrent/exceptions.h" 
    4242#include "torrent/error.h" 
    43 #include "download/download_info.h" 
    4443#include "download/download_main.h" 
    4544#include "torrent/connection_manager.h" 
     45#include "torrent/download_info.h" 
    4646#include "torrent/peer/peer_info.h" 
    4747#include "torrent/peer/client_list.h" 
  • trunk/libtorrent/src/protocol/peer_connection_base.cc

    r1105 r1144  
    4848#include "download/chunk_selector.h" 
    4949#include "download/chunk_statistics.h" 
    50 #include "download/download_info.h" 
    5150#include "download/download_main.h" 
    5251#include "net/socket_base.h" 
    5352#include "torrent/connection_manager.h" 
     53#include "torrent/download_info.h" 
    5454#include "torrent/throttle.h" 
    5555#include "torrent/peer/peer_info.h" 
     
    9494    delete m_extensions; 
    9595 
    96   if (m_extensionMessage.owned()) 
    97     m_extensionMessage.clear(); 
     96  m_extensionMessage.clear(); 
    9897} 
    9998 
     
    116115  m_encryption = *encryptionInfo; 
    117116  m_extensions = extensions; 
     117 
     118  m_extensions->set_connection(this); 
    118119 
    119120  m_peerChunks.set_peer_info(m_peerInfo); 
     
    582583  } 
    583584 
    584   if (m_extensions->is_complete()) 
    585     m_extensions->read_done(); 
     585  // If extension can't be processed yet (due to a pending write), 
     586  // disable reads until the pending message is completely sent. 
     587  if (m_extensions->is_complete() && !m_extensions->is_invalid() && !m_extensions->read_done()) { 
     588    manager->poll()->remove_read(this); 
     589    return false; 
     590  } 
    586591 
    587592  return m_extensions->is_complete(); 
     
    694699    return false; 
    695700 
    696   // clear() deletes the buffer, only do that if we made a copy, 
    697   // otherwise the buffer is shared among all connections. 
    698   if (m_extensionMessage.owned()) 
    699     m_extensionMessage.clear(); 
    700   else  
    701     m_extensionMessage.set(NULL, NULL, false); 
     701  m_extensionMessage.clear(); 
     702 
     703  // If we have an unprocessed message, process it now and enable reads again. 
     704  if (m_extensions->is_complete() && !m_extensions->is_invalid()) { 
     705    // DEBUG: What, this should fail when we block, no? 
     706    if (!m_extensions->read_done()) 
     707      throw internal_error("PeerConnectionBase::up_extension could not process complete extension message."); 
     708 
     709    manager->poll()->insert_read(this); 
     710  } 
    702711 
    703712  return true; 
     
    858867} 
    859868 
    860 } 
     869// Extension protocol needs to send a reply. 
     870bool 
     871PeerConnectionBase::send_ext_message() { 
     872  write_prepare_extension(m_extensions->pending_message_type(), m_extensions->pending_message_data()); 
     873  m_extensions->clear_pending_message(); 
     874  return true; 
     875} 
     876 
     877void 
     878PeerConnectionBase::receive_metadata_piece(uint32_t piece, const char* data, uint32_t length) { 
     879} 
     880 
     881} 
  • trunk/libtorrent/src/protocol/peer_connection_base.h

    r1058 r1144  
    141141  void                write_insert_poll_safe(); 
    142142 
     143  // Communication with the protocol extensions 
     144  virtual void        receive_metadata_piece(uint32_t piece, const char* data, uint32_t length); 
     145 
    143146protected: 
    144147  static const uint32_t extension_must_encrypt = ~uint32_t(); 
     
    180183 
    181184  bool                send_pex_message(); 
     185  bool                send_ext_message(); 
    182186 
    183187  DownloadMain*       m_download; 
  • trunk/libtorrent/src/protocol/peer_connection_leech.cc

    r1143 r1144  
    4545#include "download/chunk_selector.h" 
    4646#include "download/chunk_statistics.h" 
    47 #include "download/download_info.h" 
    4847#include "download/download_main.h" 
    4948#include "torrent/dht_manager.h" 
     49#include "torrent/download_info.h" 
    5050#include "torrent/peer/connection_list.h" 
    5151#include "torrent/peer/peer_info.h" 
     
    334334    } 
    335335 
    336     if (down_extension()) 
    337       m_down->set_state(ProtocolRead::IDLE); 
    338  
     336    if (!down_extension()) 
     337      return false; 
     338 
     339    if (m_extensions->has_pending_message()) 
     340      write_insert_poll_safe(); 
     341 
     342    m_down->set_state(ProtocolRead::IDLE); 
    339343    return true; 
    340344 
     
    434438          return; 
    435439 
     440        if (m_extensions->has_pending_message()) 
     441          write_insert_poll_safe(); 
     442 
    436443        m_down->set_state(ProtocolRead::IDLE); 
    437444        break; 
     
    547554      send_pex_message()) { 
    548555    // Don't do anything else if send_pex_message() succeeded. 
     556 
     557  } else if (m_extensions->has_pending_message() && m_up->can_write_extension() && 
     558             send_ext_message()) { 
     559    // Same. 
    549560 
    550561  } else if (!m_upChoke.choked() && 
  • trunk/libtorrent/src/protocol/peer_factory.cc

    r1058 r1144  
    3939#include "peer_factory.h" 
    4040#include "peer_connection_leech.h" 
     41#include "peer_connection_metadata.h" 
    4142 
    4243namespace torrent { 
     
    6364} 
    6465 
     66PeerConnectionBase* 
     67createPeerConnectionMetadata(bool encrypted) { 
     68  PeerConnectionBase* pc = new PeerConnectionMetadata; 
     69 
     70  return pc; 
    6571} 
     72 
     73} 
  • trunk/libtorrent/src/protocol/peer_factory.h

    r1058 r1144  
    4545PeerConnectionBase* createPeerConnectionSeed(bool encrypted); 
    4646PeerConnectionBase* createPeerConnectionInitialSeed(bool encrypted); 
     47PeerConnectionBase* createPeerConnectionMetadata(bool encrypted); 
    4748 
    4849} 
  • trunk/libtorrent/src/torrent/Makefile.am

    r1136 r1144  
    1717        download.cc \ 
    1818        download.h \ 
     19        download_info.h \ 
    1920        error.cc \ 
    2021        error.h \ 
     
    6667        dht_manager.h \ 
    6768        download.h \ 
     69        download_info.h \ 
    6870        error.h \ 
    6971        exceptions.h \ 
  • trunk/libtorrent/src/torrent/data/file_list.cc

    r1089 r1144  
    467467  m_isOpen = true; 
    468468  m_frozenRootDir = m_rootDir; 
     469 
     470  // For meta-downloads, if the file exists, we have to assume that 
     471  // it is either 0 or 1 length or the correct size. If the size 
     472  // turns out wrong later, a storage_error will be thrown elsewhere 
     473  // to alert the user in this (unlikely) case. 
     474  // 
     475  // DEBUG: Make this depend on a flag... 
     476  if (size_bytes() < 2) { 
     477    rak::file_stat stat; 
     478 
     479    // This probably recurses into open() once, but that is harmless. 
     480    if (stat.update((*begin())->frozen_path()) && stat.size() > 1) 
     481      return reset_filesize(stat.size()); 
     482  } 
    469483} 
    470484 
     
    662676} 
    663677 
    664 } 
     678void 
     679FileList::reset_filesize(int64_t size) { 
     680  close(); 
     681  m_chunkSize = size; 
     682  m_torrentSize = size; 
     683  (*begin())->set_size_bytes(size); 
     684  (*begin())->set_range(m_chunkSize); 
     685  open(open_no_create); 
     686} 
     687 
     688} 
  • trunk/libtorrent/src/torrent/data/file_list.h

    r1085 r1144  
    168168  void                update_completed() LIBTORRENT_NO_EXPORT; 
    169169 
     170  // Used for meta downloads; we only know the 
     171  // size after the first extension handshake. 
     172  void                reset_filesize(int64_t) LIBTORRENT_NO_EXPORT; 
     173 
    170174private: 
    171175  bool                open_file(File* node, const Path& lastPath, int flags) LIBTORRENT_NO_EXPORT; 
  • trunk/libtorrent/src/torrent/download.cc

    r1129 r1144  
    5353#include "protocol/peer_connection_base.h" 
    5454#include "protocol/peer_factory.h" 
    55 #include "download/download_info.h" 
    5655#include "peer/peer_info.h" 
    5756#include "tracker/tracker_manager.h" 
     57#include "torrent/download_info.h" 
    5858#include "torrent/data/file.h" 
    5959#include "torrent/peer/connection_list.h" 
     
    6767namespace torrent { 
    6868 
     69const DownloadInfo* 
     70Download::info() const { return m_ptr->info(); } 
     71 
    6972void 
    7073Download::open(int flags) { 
     
    124127  if (!(flags & start_keep_baseline)) { 
    125128    m_ptr->info()->set_uploaded_baseline(m_ptr->info()->up_rate()->total()); 
    126     m_ptr->info()->set_completed_baseline(m_ptr->info()->slot_completed()()); 
     129    m_ptr->info()->set_completed_baseline(m_ptr->main()->file_list()->completed_bytes()); 
    127130  } 
    128131 
     
    186189} 
    187190 
    188 bool 
    189 Download::is_open() const { 
    190   return m_ptr->info()->is_open(); 
    191 } 
    192  
    193 bool 
    194 Download::is_active() const { 
    195   return m_ptr->info()->is_active(); 
    196 } 
     191// bool 
     192// Download::is_open() const { 
     193//   return m_ptr->info()->is_open(); 
     194// } 
     195 
     196// bool 
     197// Download::is_active() const { 
     198//   return m_ptr->info()->is_active(); 
     199// } 
    197200 
    198201bool 
     
    206209} 
    207210 
    208 bool 
    209 Download::is_private() const { 
    210   return m_ptr->info()->is_private(); 
    211 } 
    212  
    213 bool 
    214 Download::is_pex_active() const { 
    215   return m_ptr->info()->is_pex_active(); 
    216 } 
    217  
    218 bool 
    219 Download::is_pex_enabled() const { 
    220   return m_ptr->info()->is_pex_enabled(); 
    221 } 
     211// bool 
     212// Download::is_private() const { 
     213//   return m_ptr->info()->is_private(); 
     214// } 
     215 
     216// bool 
     217// Download::is_pex_active() const { 
     218//   return m_ptr->info()->is_pex_active(); 
     219// } 
     220 
     221// bool 
     222// Download::is_pex_enabled() const { 
     223//   return m_ptr->info()->is_pex_enabled(); 
     224// } 
    222225 
    223226void 
    224227Download::set_pex_enabled(bool enabled) { 
    225   m_ptr->info()->set_pex_enabled(enabled); 
    226 } 
     228  m_ptr->info()->change_flags(DownloadInfo::flag_pex_enabled, enabled); 
     229} 
     230 
     231// bool 
     232// Download::is_meta_download() const { 
     233//   return m_ptr->info()->is_meta_download(); 
     234// } 
    227235 
    228236const std::string& 
     
    510518void 
    511519Download::set_connection_type(ConnectionType t) { 
     520  if (m_ptr->info()->is_meta_download()) { 
     521    m_ptr->main()->connection_list()->slot_new_connection(&createPeerConnectionMetadata); 
     522    return; 
     523  } 
     524 
    512525  switch (t) { 
    513526  case CONNECTION_LEECH: 
     
    518531    break; 
    519532  case CONNECTION_INITIAL_SEED: 
    520     if (is_active() && m_ptr->main()->initial_seeding() == NULL) 
     533    if (info()->is_active() && m_ptr->main()->initial_seeding() == NULL) 
    521534      throw input_error("Can't switch to initial seeding: download is active."); 
    522535    m_ptr->main()->connection_list()->slot_new_connection(&createPeerConnectionInitialSeed); 
  • trunk/libtorrent/src/torrent/download.h

    r1129 r1144  
    5050 
    5151class ConnectionList; 
     52class DownloadInfo; 
    5253 
    5354// Download is safe to copy and destory as it is just a pointer to an 
     
    6970 
    7071  Download(DownloadWrapper* d = NULL) : m_ptr(d) {} 
     72 
     73  const DownloadInfo* info() const; 
    7174 
    7275  // Not active atm. Opens and prepares/closes the files. 
     
    9093  bool                is_valid() const { return m_ptr; } 
    9194 
    92   bool                is_open() const; 
    93   bool                is_active() const; 
     95//   bool                is_open() const; 
     96//   bool                is_active() const; 
    9497 
    9598  bool                is_hash_checked() const; 
    9699  bool                is_hash_checking() const; 
    97100 
    98   bool                is_private() const; 
    99   bool                is_pex_active() const; 
    100   bool                is_pex_enabled() const; 
     101//   bool                is_private() const; 
     102//   bool                is_pex_active() const; 
     103//   bool                is_pex_enabled() const; 
    101104  void                set_pex_enabled(bool enabled); 
     105 
     106//   bool                is_meta_download() const; 
    102107 
    103108  // Returns "" if the object is not valid. 
     
    186191    CONNECTION_SEED, 
    187192    CONNECTION_INITIAL_SEED, 
     193    CONNECTION_METADATA, 
    188194  } ConnectionType; 
    189195 
  • trunk/libtorrent/src/torrent/download_info.h

    r1129 r1144  
    4141#include <string> 
    4242#include <inttypes.h> 
    43 #include <rak/functional.h> 
    4443#include <rak/socket_address.h> 
    45 #include <rak/timer.h> 
    4644#include <sigc++/signal.h> 
    4745 
    48 #include "torrent/rate.h" 
    49 #include "torrent/hash_string.h" 
     46#include <torrent/rate.h> 
     47#include <torrent/hash_string.h> 
    5048 
    5149namespace torrent { 
     
    5351class FileList; 
    5452class DownloadMain; 
    55 class Rate; 
    5653 
    5754// This will become a Download 'handle' of kinds. 
     
    5956class DownloadInfo { 
    6057public: 
    61   typedef rak::const_mem_fun0<FileList, uint64_t>                      slot_stat_type; 
    62  
     58  typedef sigc::slot0<uint64_t>                                        slot_stat_type; 
    6359  typedef sigc::signal1<void, const std::string&>                      signal_string_type; 
    6460  typedef sigc::signal1<void, uint32_t>                                signal_chunk_type; 
     
    7268  }; 
    7369 
    74   DownloadInfo() : 
    75     m_isOpen(false), 
    76     m_isActive(false), 
    77     m_isCompact(true), 
    78     m_isAcceptingNewPeers(true), 
    79     m_isPrivate(false), 
    80     m_pexEnabled(true), 
    81     m_pexActive(true), 
     70  static const int flag_open                = (1 << 0); 
     71  static const int flag_active              = (1 << 1); 
     72  static const int flag_compact             = (1 << 2); 
     73  static const int flag_accepting_new_peers = (1 << 3); 
     74  static const int flag_private             = (1 << 4); 
     75  static const int flag_meta_download       = (1 << 5); 
     76  static const int flag_pex_enabled         = (1 << 6); 
     77  static const int flag_pex_active          = (1 << 7); 
    8278 
    83     m_upRate(60), 
    84     m_downRate(60), 
    85     m_skipRate(60), 
    86  
    87     m_uploadedBaseline(0), 
    88     m_completedBaseline(0), 
    89     m_sizePex(0), 
    90     m_maxSizePex(8), 
    91  
    92     m_loadDate(rak::timer::current_seconds()) { 
    93   } 
     79  DownloadInfo(); 
    9480 
    9581  const std::string&  name() const                                 { return m_name; } 
     
    10591  HashString&         mutable_local_id()                           { return m_localId; } 
    10692 
    107   bool                is_open() const                              { return m_isOpen; } 
    108   void                set_open(bool s)                             { m_isOpen = s; } 
     93  bool                is_open() const                              { return m_flags & flag_open; } 
     94  bool                is_active() const                            { return m_flags & flag_active; } 
     95  bool                is_compact() const                           { return m_flags & flag_compact; } 
     96  bool                is_accepting_new_peers() const               { return m_flags & flag_accepting_new_peers; } 
     97  bool                is_private() const                           { return m_flags & flag_private; } 
     98  bool                is_meta_download() const                     { return m_flags & flag_meta_download; } 
     99  bool                is_pex_enabled() const                       { return m_flags & flag_pex_enabled; } 
     100  bool                is_pex_active() const                        { return m_flags & flag_pex_active; } 
    109101 
    110   bool                is_active() const                            { return m_isActive; } 
    111   void                set_active(bool s)                           { m_isActive = s; } 
     102  void                set_flags(int flags)                         { m_flags |= flags; } 
     103  void                unset_flags(int flags)                       { m_flags &= ~flags; } 
     104  void                change_flags(int flags, bool state)          { if (state) set_flags(flags); else unset_flags(flags); } 
    112105 
    113   bool                is_compact() const                           { return m_isCompact; } 
    114   void                set_compact(bool s)                          { m_isCompact = s; } 
    115  
    116   bool                is_accepting_new_peers() const               { return m_isAcceptingNewPeers; } 
    117   void                set_accepting_new_peers(bool s)              { m_isAcceptingNewPeers = s; } 
    118  
    119   bool                is_private() const                           { return m_isPrivate; } 
    120   void                set_private(bool p)                          { m_isPrivate = p; if (p) m_pexEnabled = false; } 
    121  
    122   bool                is_pex_enabled() const                       { return m_pexEnabled; } 
    123   void                set_pex_enabled(bool enabled)                { m_pexEnabled = enabled && !m_isPrivate; } 
    124  
    125   bool                is_pex_active() const                        { return m_pexActive; } 
    126   void                set_pex_active(bool active)                  { m_pexActive = active; } 
     106  void                set_private()                                { set_flags(flag_private); unset_flags(flag_pex_enabled); } 
     107  void                set_pex_enabled()                            { if (!is_private()) set_flags(flag_pex_enabled); } 
    127108 
    128109  Rate*               up_rate()                                    { return &m_upRate; } 
     
    137118  uint64_t            completed_adjusted() const                   { return std::max<int64_t>(m_slotStatCompleted() - completed_baseline(), 0); } 
    138119  void                set_completed_baseline(uint64_t b)           { m_completedBaseline = b; } 
     120 
     121  size_t              metadata_size() const                        { return m_metadataSize; } 
     122  void                set_metadata_size(size_t size)               { m_metadataSize = size; } 
    139123 
    140124  uint32_t            size_pex() const                             { return m_sizePex; } 
     
    152136  uint32_t            udp_tries() const                            { return 2; } 
    153137 
     138  slot_stat_type&     slot_left()                                  { return m_slotStatLeft; } 
    154139  slot_stat_type&     slot_completed()                             { return m_slotStatCompleted; } 
    155   slot_stat_type&     slot_left()                                  { return m_slotStatLeft; } 
    156140 
    157141  signal_string_type& signal_network_log()                         { return m_signalNetworkLog; } 
     
    165149  HashString          m_localId; 
    166150 
    167   // TODO: Use flags. 
    168   bool                m_isOpen; 
    169   bool                m_isActive; 
    170   bool                m_isCompact; 
    171   bool                m_isAcceptingNewPeers; 
    172   bool                m_isPrivate; 
    173   bool                m_pexEnabled; 
    174   bool                m_pexActive; 
     151  int                 m_flags; 
    175152 
    176153  Rate                m_upRate; 
     
    182159  uint32_t            m_sizePex; 
    183160  uint32_t            m_maxSizePex; 
     161  size_t              m_metadataSize; 
    184162 
    185163  uint32_t            m_loadDate; 
    186164 
     165  slot_stat_type      m_slotStatLeft; 
    187166  slot_stat_type      m_slotStatCompleted; 
    188   slot_stat_type      m_slotStatLeft; 
    189167 
    190168  signal_string_type  m_signalNetworkLog; 
     
    193171}; 
    194172 
    195 // Move somewhere else. 
    196 struct SocketAddressCompact { 
    197   SocketAddressCompact() {} 
    198   SocketAddressCompact(uint32_t a, uint16_t p) : addr(a), port(p) {} 
    199   SocketAddressCompact(const rak::socket_address_inet* sa) : addr(sa->address_n()), port(sa->port_n()) {} 
    200  
    201   operator rak::socket_address () const { 
    202     rak::socket_address sa; 
    203     sa.sa_inet()->clear(); 
    204     sa.sa_inet()->set_port_n(port); 
    205     sa.sa_inet()->set_address_n(addr); 
    206  
    207     return sa; 
    208   } 
    209  
    210   uint32_t addr; 
    211   uint16_t port; 
    212  
    213   const char*         c_str() const { return reinterpret_cast<const char*>(this); } 
    214 } __attribute__ ((packed)); 
    215  
    216173} 
    217174 
  • trunk/libtorrent/src/torrent/object_stream.cc

    r1143 r1144  
    624624} 
    625625 
     626object_buffer_t 
     627object_write_to_size(void* data, object_buffer_t buffer) { 
     628  *reinterpret_cast<uint64_t*>(data) += std::distance(buffer.first, buffer.second); 
     629 
     630  return buffer; 
     631} 
     632 
    626633// 
    627634// static_map operations: 
  • trunk/libtorrent/src/torrent/object_stream.h

    r1140 r1144  
    7373object_buffer_t object_write_to_sha1(void* data, object_buffer_t buffer) LIBTORRENT_EXPORT; 
    7474object_buffer_t object_write_to_stream(void* data, object_buffer_t buffer) LIBTORRENT_EXPORT; 
     75// Measures bencode size, 'data' is uint64_t*. 
     76object_buffer_t object_write_to_size(void* data, object_buffer_t buffer) LIBTORRENT_EXPORT; 
    7577 
    7678// 
  • trunk/libtorrent/src/torrent/peer/connection_list.cc

    r1035 r1144  
    4141 
    4242#include "download/choke_manager.h" 
    43 #include "download/download_info.h" 
    4443#include "download/download_main.h" 
    4544#include "net/address_list.h" 
    4645#include "protocol/peer_connection_base.h" 
    4746#include "torrent/exceptions.h" 
     47#include "torrent/download_info.h" 
    4848 
    4949#include "connection_list.h" 
     
    8585  base_type::push_back(peerConnection); 
    8686 
    87   m_download->info()->set_accepting_new_peers(size() < m_maxSize); 
     87  m_download->info()->change_flags(DownloadInfo::flag_accepting_new_peers, size() < m_maxSize); 
    8888  m_signalConnected(peerConnection); 
    8989 
     
    104104  base_type::pop_back(); 
    105105 
    106   m_download->info()->set_accepting_new_peers(size() < m_maxSize); 
    107  
     106  m_download->info()->change_flags(DownloadInfo::flag_accepting_new_peers, size() < m_maxSize); 
    108107  m_signalDisconnected(peerConnection); 
    109108 
     
    144143    erase(--end(), flags); 
    145144 
    146   m_download->info()->set_accepting_new_peers(size() < m_maxSize); 
     145  m_download->info()->change_flags(DownloadInfo::flag_accepting_new_peers, size() < m_maxSize); 
    147146} 
    148147 
     
    207206 
    208207  m_maxSize = v; 
    209   m_download->info()->set_accepting_new_peers(size() < m_maxSize); 
     208  m_download->info()->change_flags(DownloadInfo::flag_accepting_new_peers, size() < m_maxSize); 
    210209  m_download->upload_choke_manager()->balance(); 
    211210} 
  • trunk/libtorrent/src/torrent/resume.cc

    r1129 r1144  
    4040#include <rak/socket_address.h> 
    4141 
    42 // For SocketAddressCompact. 
    43 #include "download/download_info.h" 
    4442#include "peer/peer_info.h" 
    4543#include "peer/peer_list.h" 
     
    4846#include "data/file_list.h" 
    4947#include "data/transfer_list.h" 
     48#include "net/address_list.h" 
    5049 
    5150#include "common.h" 
    5251#include "bitfield.h" 
    5352#include "download.h" 
     53#include "download_info.h" 
    5454#include "object.h" 
    5555#include "tracker.h" 
     
    240240      filesItr->insert_key("mtime", (int64_t)fs.modified_time()); 
    241241 
    242     } else if (!download.is_active()) { 
     242    } else if (!download.info()->is_active()) { 
    243243 
    244244      // When stopped, all chunks should have received sync, thus the 
  • trunk/libtorrent/src/torrent/torrent.cc

    r1113 r1144  
    321321  ctor.initialize(*object); 
    322322 
    323   std::string infoHash = object_sha1(&object->get_key("info")); 
     323  std::string infoHash; 
     324  if (download->info()->is_meta_download()) 
     325    infoHash = object->get_key("info").get_key("pieces").as_string(); 
     326  else 
     327    infoHash = object_sha1(&object->get_key("info")); 
    324328 
    325329  if (manager->download_manager()->find(infoHash) != manager->download_manager()->end()) 
    326330    throw input_error("Info hash already used by another torrent."); 
     331 
     332  if (!download->info()->is_meta_download()) { 
     333    char buffer[1024]; 
     334    uint64_t metadata_size = 0; 
     335    object_write_bencode_c(&object_write_to_size, &metadata_size, object_buffer_t(buffer, buffer + sizeof(buffer)), &object->get_key("info")); 
     336    download->main()->set_metadata_size(metadata_size); 
     337  } 
    327338 
    328339  download->set_hash_queue(manager->hash_queue()); 
  • trunk/libtorrent/src/torrent/tracker_list.cc

    r1032 r1144  
    3939#include <rak/functional.h> 
    4040 
    41 #include "download/download_info.h" 
     41#include "torrent/download_info.h" 
    4242#include "net/address_list.h" 
    4343#include "tracker/tracker_manager.h" 
  • trunk/libtorrent/src/tracker/tracker_dht.cc

    r1138 r1144  
    4242#include "dht/dht_router.h" 
    4343#include "torrent/connection_manager.h" 
     44#include "torrent/download_info.h" 
    4445#include "torrent/dht_manager.h" 
    4546#include "torrent/exceptions.h" 
  • trunk/libtorrent/src/tracker/tracker_http.cc

    r1097 r1144  
    4242#include <rak/string_manip.h> 
    4343 
    44 #include "download/download_info.h" 
    4544#include "net/address_list.h" 
    4645#include "torrent/connection_manager.h" 
     46#include "torrent/download_info.h" 
    4747#include "torrent/exceptions.h" 
    4848#include "torrent/http.h" 
  • trunk/libtorrent/src/tracker/tracker_manager.cc

    r1062 r1144  
    3737#include "config.h" 
    3838 
    39 #include "download/download_info.h" 
     39#include "torrent/download_info.h" 
    4040#include "torrent/exceptions.h" 
    4141#include "torrent/tracker.h" 
  • trunk/libtorrent/src/tracker/tracker_udp.cc

    r1128 r1144  
    4343#include <cstdio> 
    4444 
    45 #include "download/download_info.h" 
    4645#include "net/address_list.h" 
    4746#include "torrent/exceptions.h" 
    4847#include "torrent/connection_manager.h" 
     48#include "torrent/download_info.h" 
    4949#include "torrent/poll.h" 
    5050#include "torrent/tracker_list.h" 
  • trunk/rtorrent/src/command_download.cc

    r1131 r1144  
    337337  char host[1024]; 
    338338 
    339   if (download->download()->is_private()) 
     339  if (download->download()->info()->is_private()) 
    340340    throw torrent::input_error("Download is private."); 
    341341 
     
    601601  ADD_CD_STRING("add_peer",        std::ptr_fun(&apply_d_add_peer)); 
    602602 
    603   ADD_CD_VALUE("is_open",          rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::is_open))); 
    604   ADD_CD_VALUE("is_active",        rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::is_active))); 
     603  ADD_CD_VALUE("is_open",          rak::on(std::mem_fun(&core::Download::info), std::mem_fun(&torrent::DownloadInfo::is_open))); 
     604  ADD_CD_VALUE("is_active",        rak::on(std::mem_fun(&core::Download::info), std::mem_fun(&torrent::DownloadInfo::is_active))); 
    605605  ADD_CD_VALUE("is_hash_checked",  rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::is_hash_checked))); 
    606606  ADD_CD_VALUE("is_hash_checking", rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::is_hash_checking))); 
    607607  ADD_CD_VALUE("is_multi_file",    rak::on(std::mem_fun(&core::Download::file_list), std::mem_fun(&torrent::FileList::is_multi_file))); 
    608   ADD_CD_VALUE("is_private",       rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::is_private))); 
    609   ADD_CD_VALUE("is_pex_active",    rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::is_pex_active))); 
     608  ADD_CD_VALUE("is_private",       rak::on(std::mem_fun(&core::Download::info), std::mem_fun(&torrent::DownloadInfo::is_private))); 
     609  ADD_CD_VALUE("is_pex_active",    rak::on(std::mem_fun(&core::Download::info), std::mem_fun(&torrent::DownloadInfo::is_pex_active))); 
    610610 
    611611  ADD_CD_VARIABLE_STRING_PUBLIC("custom1", "rtorrent", "custom1"); 
     
    677677  ADD_CD_VALUE_UNI("peers_accounted",     rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::peers_accounted))); 
    678678 
    679   ADD_CD_VALUE_MEM_BI("peer_exchange", &core::Download::download, &torrent::Download::set_pex_enabled, &torrent::Download::is_pex_enabled); 
    680  
    681679  ADD_CD_VALUE_MEM_UNI("up_rate",      &torrent::Download::mutable_up_rate, &torrent::Rate::rate); 
    682680  ADD_CD_VALUE_MEM_UNI("up_total",     &torrent::Download::mutable_up_rate, &torrent::Rate::total); 
     
    723721  // NEWISH: 
    724722  CMD_D_VOID("d.initialize_logs",         &cmd_d_initialize_logs); 
    725 } 
     723 
     724  CMD_D_VOID_SLOT("d.peer_exchange",      rak::on(std::mem_fun(&core::Download::info), std::mem_fun(&torrent::DownloadInfo::is_pex_enabled))); 
     725  CMD_D_VALUE_SLOT("d.peer_exchange.set", rak::on2(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::set_pex_enabled))); 
     726} 
  • trunk/rtorrent/src/command_helpers.h

    r1131 r1144  
    226226  CMD_D_SLOT(key, call_unknown, rpc::object_fn(slot), "i:", "") 
    227227 
     228#define CMD_D_VOID_SLOT(key, slot) \ 
     229  CMD_D_SLOT(key, call_unknown, rpc::object_void_fn<core::Download*>(slot), "i:", "") 
     230 
     231#define CMD_D_VALUE_SLOT(key, slot) \ 
     232  CMD_D_SLOT(key, call_value, rpc::object_value_fn<core::Download*>(slot), "i:i", "") 
     233 
    228234#define CMD_FUNC_SINGLE(key, command) \ 
    229235  rpc::commands.insert_type(key, new rpc::CommandFunction(command), &rpc::CommandFunction::call, rpc::CommandMap::flag_public_xmlrpc, NULL, NULL); 
  • trunk/rtorrent/src/core/dht_manager.cc

    r1138 r1144  
    195195 
    196196    for (itr = control->core()->download_list()->begin(), end = control->core()->download_list()->end(); itr != end; ++itr) 
    197       if ((*itr)->is_active() && !(*itr)->download()->is_private()) 
     197      if ((*itr)->download()->info()->is_active() && !(*itr)->download()->info()->is_private()) 
    198198        break; 
    199199       
  • trunk/rtorrent/src/core/download.cc

    r1129 r1144  
    160160void 
    161161Download::set_throttle_name(const std::string& throttleName) { 
    162   if (m_download.is_active()) 
     162  if (m_download.info()->is_active()) 
    163163    throw torrent::input_error("Cannot set throttle on active download."); 
    164164 
  • trunk/rtorrent/src/core/download.h

    r1129 r1144  
    4040#include <sigc++/connection.h> 
    4141#include <torrent/download.h> 
     42#include <torrent/download_info.h> 
    4243#include <torrent/hash_string.h> 
    4344#include <torrent/tracker_list.h> 
     
    7172  ~Download(); 
    7273 
    73   bool                is_open() const                          { return m_download.is_open(); } 
    74   bool                is_active() const                        { return m_download.is_active(); } 
     74  const torrent::DownloadInfo* info() const                             { return m_download.info(); } 
     75 
     76  bool                is_open() const                          { return m_download.info()->is_open(); } 
     77  bool                is_active() const                        { return m_download.info()->is_active(); } 
    7578  bool                is_done() const                          { return m_download.file_list()->is_done(); } 
    7679  bool                is_downloading() const                   { return is_active() && !is_done(); } 
     
    8083  // return true when the torrent is closed. Remove this redundant 
    8184  // test in the next milestone. 
    82   bool                is_hash_checked() const                  { return m_download.is_open() && m_download.is_hash_checked(); } 
     85  bool                is_hash_checked() const                  { return is_open() && m_download.is_hash_checked(); } 
    8386  bool                is_hash_checking() const                 { return m_download.is_hash_checking(); } 
    8487 
  • trunk/rtorrent/src/core/download_factory.cc

    r1140 r1144  
    8888} 
    8989 
     90bool 
     91is_magnet_uri(const std::string& uri) { 
     92  return 
     93    std::strncmp(uri.c_str(), "magnet:?", 8) == 0; 
     94} 
     95 
    9096DownloadFactory::DownloadFactory(Manager* m) : 
    9197  m_manager(m), 
     
    154160    m_variables["tied_to_file"] = (int64_t)false; 
    155161 
     162  } else if (is_magnet_uri(m_uri)) { 
     163    // DEBUG: Use m_object. 
     164    m_stream = new std::stringstream(); 
     165    *m_stream << "d10:magnet-uri" << m_uri.length() << ":" << m_uri << "e"; 
     166 
     167    m_variables["tied_to_file"] = (int64_t)false; 
     168    receive_loaded(); 
     169 
    156170  } else { 
    157171    std::fstream stream(rak::path_expand(m_uri).c_str(), std::ios::in | std::ios::binary); 
     
    204218 
    205219  torrent::Object* root = download->bencode(); 
     220 
     221  if (download->download()->info()->is_meta_download()) { 
     222    torrent::Object& meta = root->insert_key("rtorrent_meta_download", torrent::Object::create_map()); 
     223    meta.insert_key("start", m_start); 
     224    meta.insert_key("print_log", m_printLog); 
     225  
     226    torrent::Object::list_type& commands = meta.insert_key("commands", torrent::Object::create_list()).as_list(); 
     227 
     228    for (command_list_type::iterator itr = m_commands.begin(); itr != m_commands.end(); ++itr) 
     229      commands.push_back(*itr); 
     230  } 
    206231 
    207232  if (m_session) { 
     
    261286 
    262287  if (!m_session && m_variables["tied_to_file"].as_value()) 
    263     rpc::call_command("d.set_tied_to_file", m_uri, rpc::make_target(download)); 
    264  
    265   rpc::call_command("d.set_peer_exchange", rpc::call_command_value("get_peer_exchange"), rpc::make_target(download)); 
     288    rpc::call_command("d.set_tied_to_file", m_uri.empty() ? m_variables["tied_file"] : m_uri, rpc::make_target(download)); 
     289 
     290  rpc::call_command("d.peer_exchange.set", rpc::call_command_value("get_peer_exchange"), rpc::make_target(download)); 
    266291 
    267292  torrent::resume_load_addresses(*download->download(), resumeObject); 
  • trunk/rtorrent/src/core/download_factory.h

    r1133 r1144  
    114114 
    115115bool is_network_uri(const std::string& uri); 
     116bool is_magnet_uri(const std::string& uri); 
    116117 
    117118} 
  • trunk/rtorrent/src/core/download_list.cc

    r1133 r1144  
    3838 
    3939#include <algorithm> 
     40#include <fstream> 
    4041#include <iostream> 
    4142#include <sigc++/adaptors/bind.h> 
    4243#include <rak/functional.h> 
    4344#include <rak/string_manip.h> 
     45#include <torrent/data/file.h> 
    4446#include <torrent/exceptions.h> 
    4547#include <torrent/download.h> 
     
    237239  check_contains(download); 
    238240 
    239   if (download->download()->is_open()) 
     241  if (download->download()->info()->is_open()) 
    240242    return; 
    241243   
     
    262264void 
    263265DownloadList::close_directly(Download* download) { 
    264   if (download->download()->is_active()) { 
     266  if (download->download()->info()->is_active()) { 
    265267    download->download()->stop(torrent::Download::stop_skip_tracker); 
    266268 
     
    269271  } 
    270272 
    271   if (download->download()->is_open()) 
     273  if (download->download()->info()->is_open()) 
    272274    download->download()->close(); 
    273275} 
     
    321323  try { 
    322324 
    323     if (download->download()->is_active()) 
     325    if (download->download()->info()->is_active()) 
    324326      return; 
    325327 
     
    370372 
    371373    // If the DHT server is set to auto, start it now. 
    372     if (!download->download()->is_private()) 
     374    if (!download->download()->info()->is_private()) 
    373375      control->dht_manager()->auto_start(); 
    374376 
     
    406408    } 
    407409 
    408     if (!download->download()->is_active()) 
     410    if (!download->download()->info()->is_active()) 
    409411      return; 
    410412 
     
    475477  int64_t hashing = rpc::call_command_value("d.get_hashing", rpc::make_target(download)); 
    476478  rpc::call_command_set_value("d.set_hashing", Download::variable_hashing_stopped, rpc::make_target(download)); 
     479 
     480  if (download->is_done() && download->download()->info()->is_meta_download()) 
     481    return process_meta_download(download); 
    477482 
    478483  switch (hashing) { 
     
    567572  check_contains(download); 
    568573 
     574  if (download->download()->info()->is_meta_download()) 
     575    return process_meta_download(download); 
     576 
    569577  rpc::call_command("d.set_complete", (int64_t)1, rpc::make_target(download)); 
    570578 
     
    600608} 
    601609 
    602 } 
     610void 
     611DownloadList::process_meta_download(Download* download) { 
     612  rpc::call_command("d.stop", torrent::Object(), rpc::make_target(download)); 
     613  rpc::call_command("d.close", torrent::Object(), rpc::make_target(download)); 
     614 
     615  std::string metafile = (*download->file_list()->begin())->frozen_path(); 
     616  std::fstream file(metafile.c_str(), std::ios::in | std::ios::binary); 
     617  if (!file.is_open()) { 
     618    control->core()->push_log("Could not read download metadata."); 
     619    return; 
     620  } 
     621 
     622  torrent::Object* bencode = new torrent::Object(torrent::Object::create_map()); 
     623  file >> bencode->insert_key("info", torrent::Object()); 
     624  if (file.fail()) { 
     625    delete bencode; 
     626    control->core()->push_log("Could not create download, the input is not a valid torrent."); 
     627    return; 
     628  } 
     629  file.close(); 
     630 
     631  // Steal the keys we still need. The old download has no use for them. 
     632  bencode->insert_key("rtorrent_meta_download", torrent::Object()).swap(download->bencode()->get_key("rtorrent_meta_download")); 
     633  if (download->bencode()->has_key("announce")) 
     634    bencode->insert_key("announce", torrent::Object()).swap(download->bencode()->get_key("announce")); 
     635  if (download->bencode()->has_key("announce-list")) 
     636    bencode->insert_key("announce-list", torrent::Object()).swap(download->bencode()->get_key("announce-list")); 
     637 
     638  erase_ptr(download); 
     639  control->core()->try_create_download_from_meta_download(bencode, metafile); 
     640} 
     641 
     642} 
  • trunk/rtorrent/src/core/download_list.h

    r1133 r1144  
    163163  void                received_finished(Download* d); 
    164164  void                confirm_finished(Download* d); 
     165 
     166  void                process_meta_download(Download* d); 
    165167}; 
    166168 
  • trunk/rtorrent/src/core/manager.cc

    r1131 r1144  
    4040#include <cstring> 
    4141#include <fstream> 
     42#include <sstream> 
    4243#include <unistd.h> 
    4344#include <sys/select.h> 
     
    5354#include <torrent/error.h> 
    5455#include <torrent/exceptions.h> 
     56#include <torrent/object_stream.h> 
    5557#include <torrent/resume.h> 
    5658#include <torrent/tracker_list.h> 
     
    396398      !(flags & create_raw_data) && 
    397399      !is_network_uri(uri) && 
     400      !is_magnet_uri(uri) && 
    398401      !file_status_cache()->insert(uri, 0)) 
    399402    return; 
     
    414417    f->load(uri); 
    415418 
     419  f->commit(); 
     420} 
     421 
     422void 
     423Manager::try_create_download_from_meta_download(torrent::Object* bencode, const std::string& metafile) { 
     424  DownloadFactory* f = new DownloadFactory(this); 
     425 
     426  f->variables()["tied_to_file"] = (int64_t)true; 
     427  f->variables()["tied_file"] = metafile; 
     428 
     429  torrent::Object& meta = bencode->get_key("rtorrent_meta_download"); 
     430  torrent::Object::list_type& commands = meta.get_key_list("commands"); 
     431  for (torrent::Object::list_type::const_iterator itr = commands.begin(); itr != commands.end(); ++itr) 
     432    f->commands().insert(f->commands().end(), itr->as_string()); 
     433 
     434  f->set_start(meta.get_key_value("start")); 
     435  f->set_print_log(meta.get_key_value("print_log")); 
     436  f->slot_finished(sigc::bind(sigc::ptr_fun(&rak::call_delete_func<core::DownloadFactory>), f)); 
     437 
     438  // Bit of a waste to create the bencode repesentation here 
     439  // only to have the DownloadFactory decode it. 
     440  std::stringstream s; 
     441  s.imbue(std::locale::classic()); 
     442  s << *bencode; 
     443  f->load_raw_data(s.str()); 
    416444  f->commit(); 
    417445} 
  • trunk/rtorrent/src/core/manager.h

    r1101 r1144  
    129129  void                try_create_download(const std::string& uri, int flags, const command_list_type& commands); 
    130130  void                try_create_download_expand(const std::string& uri, int flags, command_list_type commands = command_list_type()); 
     131  void                try_create_download_from_meta_download(torrent::Object* bencode, const std::string& metafile); 
    131132 
    132133private: 
  • trunk/rtorrent/src/display/utils.cc

    r1092 r1144  
    133133char* 
    134134print_download_info(char* first, char* last, core::Download* d) { 
    135   if (!d->download()->is_open()) 
     135  if (!d->download()->info()->is_open()) 
    136136    first = print_buffer(first, last, "[CLOSED]  "); 
    137   else if (!d->download()->is_active()) 
     137  else if (!d->download()->info()->is_active()) 
    138138    first = print_buffer(first, last, "[OPEN]    "); 
    139139  else 
     
    152152                       (double)d->download()->up_rate()->total() / (1 << 20)); 
    153153 
    154   if (d->download()->is_active() && !d->is_done()) { 
     154  if (d->download()->info()->is_active() && !d->is_done()) { 
    155155    first = print_buffer(first, last, " "); 
    156156    first = print_download_percentage_done(first, last, d); 
  • trunk/rtorrent/src/main.cc

    r1139 r1144  
    8787    optionParser.insert_flag('h', sigc::ptr_fun(&print_help)); 
    8888    optionParser.insert_flag('n', OptionParser::Slot()); 
     89    optionParser.insert_flag('D', OptionParser::Slot()); 
    8990 
    9091    optionParser.insert_option('b', sigc::bind<0>(sigc::ptr_fun(&rpc::call_command_set_string), "bind")); 
     
    303304 
    304305    // Deprecated commands. Don't use these anymore. 
     306 
     307    if (!OptionParser::has_flag('D', argc, argv)) { 
    305308 
    306309    rpc::parse_command_multiple 
     
    348351       "method.insert = get_max_memory_usage,redirect|const,pieces.memory.max\n" 
    349352       "method.insert = set_max_memory_usage,redirect|const,pieces.memory.max.set\n" 
     353 
     354       "method.insert = d.get_peer_exchange,redirect|const,d.peer_exchange\n" 
    350355    ); 
     356 
     357    } 
    351358 
    352359    if (OptionParser::has_flag('n', argc, argv)) 
  • trunk/rtorrent/src/ui/download.cc

    r1131 r1144  
    164164  element->push_column("Chunks:",           te_command("cat=$d.get_completed_chunks=,\" / \",$d.get_size_chunks=,\" * \",$d.get_chunk_size=")); 
    165165  element->push_column("Priority:",         te_command("d.get_priority=")); 
    166   element->push_column("Peer exchange:",    te_command("cat=$if=$d.get_peer_exchange=\\,enabled\\,disabled,\\ ," 
     166  element->push_column("Peer exchange:",    te_command("cat=$if=$d.peer_exchange=\\,enabled\\,disabled,\\ ," 
    167167                                                       "$if=$d.is_pex_active=\\,active\\,$d.is_private=\\,private\\,inactive," 
    168168                                                       "\\ (,$d.get_size_pex=,/,$d.get_max_size_pex=,)")); 
Note: See TracChangeset for help on using the changeset viewer.