From 6bbdd4afa49642a934cb21dd1ca95f9e9f576f81 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 3 Sep 2014 06:52:45 +0000 Subject: [PATCH] merged changes from RC_1_0 --- ChangeLog | 1 + bindings/python/src/session_settings.cpp | 1 + docs/examples.html | 789 +++++++++++++++++------ docs/examples.rst | 254 +------- docs/gen_reference_doc.py | 2 +- docs/manual.rst | 12 +- docs/reference-Session.html | 7 +- docs/style.css | 5 + include/libtorrent/alert.hpp | 4 +- include/libtorrent/create_torrent.hpp | 8 +- include/libtorrent/entry.hpp | 8 +- include/libtorrent/storage.hpp | 2 +- include/libtorrent/torrent_handle.hpp | 4 +- 13 files changed, 636 insertions(+), 461 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6a7f32de4..cd88f8922 100644 --- a/ChangeLog +++ b/ChangeLog @@ -27,6 +27,7 @@ * almost completely changed the storage interface (for custom storage) * added support for hashing pieces in multiple threads + * added missing force_proxy to python binding * anonymous_mode defaults to false * make DHT DOS detection more forgiving to bursts * support IPv6 multicast in local service discovery diff --git a/bindings/python/src/session_settings.cpp b/bindings/python/src/session_settings.cpp index 1329f1dbf..33f393ce1 100644 --- a/bindings/python/src/session_settings.cpp +++ b/bindings/python/src/session_settings.cpp @@ -135,6 +135,7 @@ void bind_session_settings() .def_readwrite("ignore_resume_timestamps", &session_settings::ignore_resume_timestamps) .def_readwrite("no_recheck_incomplete_resume", &session_settings::no_recheck_incomplete_resume) .def_readwrite("anonymous_mode", &session_settings::anonymous_mode) + .def_readwrite("force_proxy", &session_settings::force_proxy) .def_readwrite("tick_interval", &session_settings::tick_interval) .def_readwrite("report_web_seed_downloads", &session_settings::report_web_seed_downloads) .def_readwrite("share_mode_target", &session_settings::share_mode_target) diff --git a/docs/examples.html b/docs/examples.html index 421d6a2d1..a45d361ea 100644 --- a/docs/examples.html +++ b/docs/examples.html @@ -41,15 +41,17 @@ Author: Arvid Norberg, arvid@rasterbar.com +Version: +1.0.2

Table of contents

@@ -60,244 +62,613 @@ of a (little bit) more complete client, client_test. There are separate instructions for how to use it here if you'd like to try it. Note that building client_test also requires boost.regex and boost.program_options library.

-
-

dump_torrent

-

This is an example of a program that will take a torrent-file as a parameter and -print information about it to std out:

-
-#include <iostream>
-#include <fstream>
-#include <iterator>
-#include <iomanip>
-
-#include "libtorrent/entry.hpp"
-#include "libtorrent/bencode.hpp"
-#include "libtorrent/torrent_info.hpp"
-#include "libtorrent/lazy_entry.hpp"
-#include <boost/filesystem/operations.hpp>
-
-
-int main(int argc, char* argv[])
-{
-        using namespace libtorrent;
-        using namespace boost::filesystem;
-
-        if (argc != 2)
-        {
-                std::cerr << "usage: dump_torrent torrent-file\n";
-                return 1;
-        }
-#if BOOST_VERSION < 103400
-        boost::filesystem::path::default_name_check(boost::filesystem::no_check);
-#endif
-
-#ifndef BOOST_NO_EXCEPTIONS
-        try
-        {
-#endif
-
-                int size = file_size(argv[1]);
-                if (size > 10 * 1000000)
-                {
-                        std::cerr << "file too big (" << size << "), aborting\n";
-                        return 1;
-                }
-                std::vector<char> buf(size);
-                std::ifstream(argv[1], std::ios_base::binary).read(&buf[0], size);
-                lazy_entry e;
-                int ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e);
-
-                if (ret != 0)
-                {
-                        std::cerr << "invalid bencoding: " << ret << std::endl;
-                        return 1;
-                }
-
-                std::cout << "\n\n----- raw info -----\n\n";
-                std::cout << e << std::endl;
-
-                torrent_info t(e);
-
-                // print info about torrent
-                std::cout << "\n\n----- torrent file info -----\n\n";
-                std::cout << "nodes:\n";
-                typedef std::vector<std::pair<std::string, int> > node_vec;
-                node_vec const& nodes = t.nodes();
-                for (node_vec::const_iterator i = nodes.begin(), end(nodes.end());
-                        i != end; ++i)
-                {
-                        std::cout << i->first << ":" << i->second << "\n";
-                }
-                std::cout << "trackers:\n";
-                for (std::vector<announce_entry>::const_iterator i = t.trackers().begin();
-                        i != t.trackers().end(); ++i)
-                {
-                        std::cout << i->tier << ": " << i->url << "\n";
-                }
-
-                std::cout << "number of pieces: " << t.num_pieces() << "\n";
-                std::cout << "piece length: " << t.piece_length() << "\n";
-                std::cout << "info hash: " << t.info_hash() << "\n";
-                std::cout << "comment: " << t.comment() << "\n";
-                std::cout << "created by: " << t.creator() << "\n";
-                std::cout << "files:\n";
-                int index = 0;
-                for (torrent_info::file_iterator i = t.begin_files();
-                        i != t.end_files(); ++i, ++index)
-                {
-                        int first = t.map_file(index, 0, 1).piece;
-                        int last = t.map_file(index, i->size - 1, 1).piece;
-                        std::cout << "  " << std::setw(11) << i->size
-                                << " " << i->path.string() << "[ " << first << ", "
-                                << last << " ]\n";
-                }
-
-#ifndef BOOST_NO_EXCEPTIONS
-        }
-        catch (std::exception& e)
-        {
-                std::cout << e.what() << "\n";
-        }
-#endif
-
-        return 0;
-}
-
-

simple client

This is a simple client. It doesn't have much output to keep it simple:

-
-int main(int argc, char* argv[])
-{
-        using namespace libtorrent;
+
+#include <stdlib.h>
+#include <boost/make_shared.hpp>
+#include "libtorrent/entry.hpp"
+#include "libtorrent/bencode.hpp"
+#include "libtorrent/session.hpp"
+
+int main(int argc, char* argv[])
+{
+  using namespace libtorrent;
+  namespace lt = libtorrent;
 
-        if (argc != 2)
-        {
-                fputs("usage: ./simple_client torrent-file\n"
-                        "to stop the client, press return.\n", stderr);
-                return 1;
-        }
+  if (argc != 2)
+  {
+    fputs("usage: ./simple_client torrent-file\n"
+      "to stop the client, press return.\n", stderr);
+    return 1;
+  }
 
-        session s;
-        error_code ec;
-        s.listen_on(std::make_pair(6881, 6889), ec);
-        if (ec)
-        {
-                fprintf(stderr, "failed to open listen socket: %s\n", ec.message().c_str());
-                return 1;
-        }
-        add_torrent_params p;
-        p.save_path = "./";
-        p.ti = boost::make_shared<torrent_info>(argv[1], ec);
-        if (ec)
-        {
-                fprintf(stderr, "%s\n", ec.message().c_str());
-                return 1;
-        }
-        s.add_torrent(p, ec);
-        if (ec)
-        {
-                fprintf(stderr, "%s\n", ec.message().c_str());
-                return 1;
-        }
+  settings_pack sett;
+  sett.set_str(settings_pack::listen_interfaces, "0.0.0.0:6881");
+  lt::session s(sett);
+  error_code ec;
+  if (ec)
+  {
+    fprintf(stderr, "failed to open listen socket: %s\n", ec.message().c_str());
+    return 1;
+  }
+  add_torrent_params p;
+  p.save_path = "./";
+  p.ti = boost::make_shared<torrent_info>(std::string(argv[1]), boost::ref(ec), 0);
+  if (ec)
+  {
+    fprintf(stderr, "%s\n", ec.message().c_str());
+    return 1;
+  }
+  s.add_torrent(p, ec);
+  if (ec)
+  {
+    fprintf(stderr, "%s\n", ec.message().c_str());
+    return 1;
+  }
 
-        // wait for the user to end
-        char a;
-        scanf("%c\n", &a);
-        return 0;
-}
+  // wait for the user to end
+  char a;
+  scanf("%c\n", &a);
+  return 0;
+}
 

make_torrent

Shows how to create a torrent from a directory tree:

-
-#include <iostream>
-#include <fstream>
-#include <iterator>
-#include <iomanip>
-
-#include "libtorrent/entry.hpp"
+
+#include "libtorrent/entry.hpp"
 #include "libtorrent/bencode.hpp"
 #include "libtorrent/torrent_info.hpp"
 #include "libtorrent/file.hpp"
 #include "libtorrent/storage.hpp"
 #include "libtorrent/hasher.hpp"
 #include "libtorrent/create_torrent.hpp"
+#include "libtorrent/file.hpp"
+#include "libtorrent/file_pool.hpp"
+
+#include <boost/bind.hpp>
+
+using namespace libtorrent;
 
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-#include <boost/filesystem/fstream.hpp>
-#include <boost/bind.hpp>
+int load_file(std::string const& filename, std::vector<char>& v, libtorrent::error_code& ec, int limit = 8000000)
+{
+  ec.clear();
+  FILE* f = fopen(filename.c_str(), "rb");
+  if (f == NULL)
+  {
+    ec.assign(errno, boost::system::generic_category());
+    return -1;
+  }
 
-using namespace boost::filesystem;
-using namespace libtorrent;
+  int r = fseek(f, 0, SEEK_END);
+  if (r != 0)
+  {
+    ec.assign(errno, boost::system::generic_category());
+    fclose(f);
+    return -1;
+  }
+  long s = ftell(f);
+  if (s < 0)
+  {
+    ec.assign(errno, boost::system::generic_category());
+    fclose(f);
+    return -1;
+  }
 
-// do not include files and folders whose
+  if (s > limit)
+  {
+    fclose(f);
+    return -2;
+  }
+
+  r = fseek(f, 0, SEEK_SET);
+  if (r != 0)
+  {
+    ec.assign(errno, boost::system::generic_category());
+    fclose(f);
+    return -1;
+  }
+
+  v.resize(s);
+  if (s == 0)
+  {
+    fclose(f);
+    return 0;
+  }
+
+  r = fread(&v[0], 1, v.size(), f);
+  if (r < 0)
+  {
+    ec.assign(errno, boost::system::generic_category());
+    fclose(f);
+    return -1;
+  }
+
+  fclose(f);
+
+  if (r != s) return -3;
+
+  return 0;
+}
+
+// do not include files and folders whose
 // name starts with a .
-bool file_filter(boost::filesystem::path const& filename)
-{
-        if (filename.leaf()[0] == '.') return false;
-        std::cerr << filename << std::endl;
-        return true;
-}
+bool file_filter(std::string const& f)
+{
+  if (filename(f)[0] == '.') return false;
+  fprintf(stderr, "%s\n", f.c_str());
+  return true;
+}
 
-void print_progress(int i, int num)
-{
-        std::cerr << "\r" << (i+1) << "/" << num;
-}
+void print_progress(int i, int num)
+{
+  fprintf(stderr, "\r%d/%d", i+1, num);
+}
 
-int main(int argc, char* argv[])
-{
-        using namespace libtorrent;
-        using namespace boost::filesystem;
+void print_usage()
+{
+  fputs("usage: make_torrent FILE [OPTIONS]\n"
+    "\n"
+    "Generates a torrent file from the specified file\n"
+    "or directory and writes it to standard out\n\n"
+    "OPTIONS:\n"
+    "-m file     generate a merkle hash tree torrent.\n"
+    "            merkle torrents require client support\n"
+    "            the resulting full merkle tree is written to\n"
+    "            the specified file\n"
+    "-f          include sha-1 file hashes in the torrent\n"
+    "            this helps supporting mixing sources from\n"
+    "            other networks\n"
+    "-w url      adds a web seed to the torrent with\n"
+    "            the specified url\n"
+    "-t url      adds the specified tracker to the\n"
+    "            torrent. For multiple trackers, specify more\n"
+    "            -t options\n"
+    "-c comment  sets the comment to the specified string\n"
+    "-C creator  sets the created-by field to the specified string\n"
+    "-p bytes    enables padding files. Files larger\n"
+    "            than bytes will be piece-aligned\n"
+    "-s bytes    specifies a piece size for the torrent\n"
+    "            This has to be a multiple of 16 kiB\n"
+    "-l          Don't follow symlinks, instead encode them as\n"
+    "            links in the torrent file\n"
+    "-o file     specifies the output filename of the torrent file\n"
+    "            If this is not specified, the torrent file is\n"
+    "            printed to the standard out, except on windows\n"
+    "            where the filename defaults to a.torrent\n"
+    "-r file     add root certificate to the torrent, to verify\n"
+    "            the HTTPS tracker\n"
+    , stderr);
+}
 
-        int piece_size = 256 * 1024;
-        char const* creator_str = "libtorrent";
+int main(int argc, char* argv[])
+{
+  using namespace libtorrent;
 
-        path::default_name_check(no_check);
+  std::string creator_str = "libtorrent";
+  std::string comment_str;
 
-        if (argc != 4 && argc != 5)
-        {
-                std::cerr << "usage: make_torrent <output torrent-file> "
-                "<announce url> <file or directory to create torrent from> "
-                "[url-seed]\n";
-        return 1;
-}
+  if (argc < 2)
+  {
+    print_usage();
+    return 1;
+  }
 
-#ifndef BOOST_NO_EXCEPTIONS
-        try
-        {
-#endif
-                file_storage fs;
-                file_pool fp;
-                path full_path = complete(path(argv[3]));
+#ifndef BOOST_NO_EXCEPTIONS
+  try
+  {
+#endif
+    std::vector<std::string> web_seeds;
+    std::vector<std::string> trackers;
+    int pad_file_limit = -1;
+    int piece_size = 0;
+    int flags = 0;
+    std::string root_cert;
 
-                add_files(fs, full_path, file_filter);
+    std::string outfile;
+    std::string merklefile;
+#ifdef TORRENT_WINDOWS
+    // don't ever write binary data to the console on windows
+    // it will just be interpreted as text and corrupted
+    outfile = "a.torrent";
+#endif
+
+    for (int i = 2; i < argc; ++i)
+    {
+      if (argv[i][0] != '-')
+      {
+        print_usage();
+        return 1;
+      }
 
-                create_torrent t(fs, piece_size);
-                t.add_tracker(argv[2]);
-                set_piece_hashes(t, full_path.branch_path()
-                        , boost::bind(&print_progress, _1, t.num_pieces()));
-                std::cerr << std::endl;
-                t.set_creator(creator_str);
+      switch (argv[i][1])
+      {
+        case 'w':
+          ++i;
+          web_seeds.push_back(argv[i]);
+          break;
+        case 't':
+          ++i;
+          trackers.push_back(argv[i]);
+          break;
+        case 'p':
+          ++i;
+          pad_file_limit = atoi(argv[i]);
+          flags |= create_torrent::optimize;
+          break;
+        case 's':
+          ++i;
+          piece_size = atoi(argv[i]);
+          break;
+        case 'm':
+          ++i;
+          merklefile = argv[i];
+          flags |= create_torrent::merkle;
+          break;
+        case 'o':
+          ++i;
+          outfile = argv[i];
+          break;
+        case 'f':
+          flags |= create_torrent::calculate_file_hashes;
+          break;
+        case 'l':
+          flags |= create_torrent::symlinks;
+          break;
+        case 'C':
+          ++i;
+          creator_str = argv[i];
+          break;
+        case 'c':
+          ++i;
+          comment_str = argv[i];
+          break;
+        case 'r':
+          ++i;
+          root_cert = argv[i];
+          break;
+        default:
+          print_usage();
+          return 1;
+      }
+    }
 
-                if (argc == 5) t.add_url_seed(argv[4]);
+    file_storage fs;
+    std::string full_path = libtorrent::complete(argv[1]);
 
-                // create the torrent and print it to out
-                ofstream out(complete(path(argv[1])), std::ios_base::binary);
-                bencode(std::ostream_iterator<char>(out), t.generate());
-#ifndef BOOST_NO_EXCEPTIONS
-        }
-        catch (std::exception& e)
-        {
-                std::cerr << e.what() << "\n";
-        }
-#endif
+    add_files(fs, full_path, file_filter, flags);
+    if (fs.num_files() == 0)
+    {
+      fputs("no files specified.\n", stderr);
+      return 1;
+    }
 
-        return 0;
-}
+    create_torrent t(fs, piece_size, pad_file_limit, flags);
+    int tier = 0;
+    for (std::vector<std::string>::iterator i = trackers.begin()
+      , end(trackers.end()); i != end; ++i, ++tier)
+      t.add_tracker(*i, tier);
+
+    for (std::vector<std::string>::iterator i = web_seeds.begin()
+      , end(web_seeds.end()); i != end; ++i)
+      t.add_url_seed(*i);
+
+    error_code ec;
+    set_piece_hashes(t, parent_path(full_path)
+      , boost::bind(&print_progress, _1, t.num_pieces()), ec);
+    if (ec)
+    {
+      fprintf(stderr, "%s\n", ec.message().c_str());
+      return 1;
+    }
+
+    fprintf(stderr, "\n");
+    t.set_creator(creator_str.c_str());
+    if (!comment_str.empty())
+      t.set_comment(comment_str.c_str());
+
+    if (!root_cert.empty())
+    {
+      std::vector<char> pem;
+      load_file(root_cert, pem, ec, 10000);
+      if (ec)
+      {
+        fprintf(stderr, "failed to load root certificate for tracker: %s\n", ec.message().c_str());
+      }
+      else
+      {
+        t.set_root_cert(std::string(&pem[0], pem.size()));
+      }
+    }
+
+    // create the torrent and print it to stdout
+    std::vector<char> torrent;
+    bencode(back_inserter(torrent), t.generate());
+    FILE* output = stdout;
+    if (!outfile.empty())
+      output = fopen(outfile.c_str(), "wb+");
+    if (output == NULL)
+    {
+      fprintf(stderr, "failed to open file \"%s\": (%d) %s\n"
+        , outfile.c_str(), errno, strerror(errno));
+      return 1;
+    }
+    fwrite(&torrent[0], 1, torrent.size(), output);
+
+    if (output != stdout)
+      fclose(output);
+
+    if (!merklefile.empty())
+    {
+      output = fopen(merklefile.c_str(), "wb+");
+      if (output == NULL)
+      {
+        fprintf(stderr, "failed to open file \"%s\": (%d) %s\n"
+          , merklefile.c_str(), errno, strerror(errno));
+        return 1;
+      }
+      int ret = fwrite(&t.merkle_tree()[0], 20, t.merkle_tree().size(), output);
+      if (ret != int(t.merkle_tree().size()))
+      {
+        fprintf(stderr, "failed to write %s: (%d) %s\n"
+          , merklefile.c_str(), errno, strerror(errno));
+      }
+      fclose(output);
+    }
+
+#ifndef BOOST_NO_EXCEPTIONS
+  }
+  catch (std::exception& e)
+  {
+    fprintf(stderr, "%s\n", e.what());
+  }
+#endif
+
+  return 0;
+}
+
+
+
+

dump_torrent

+

This is an example of a program that will take a torrent-file as a parameter and +print information about it to std out:

+
+#include "libtorrent/entry.hpp"
+#include "libtorrent/bencode.hpp"
+#include "libtorrent/torrent_info.hpp"
+#include "libtorrent/lazy_entry.hpp"
+#include "libtorrent/magnet_uri.hpp"
+
+int load_file(std::string const& filename, std::vector<char>& v, libtorrent::error_code& ec, int limit = 8000000)
+{
+  ec.clear();
+  FILE* f = fopen(filename.c_str(), "rb");
+  if (f == NULL)
+  {
+    ec.assign(errno, boost::system::generic_category());
+    return -1;
+  }
+
+  int r = fseek(f, 0, SEEK_END);
+  if (r != 0)
+  {
+    ec.assign(errno, boost::system::generic_category());
+    fclose(f);
+    return -1;
+  }
+  long s = ftell(f);
+  if (s < 0)
+  {
+    ec.assign(errno, boost::system::generic_category());
+    fclose(f);
+    return -1;
+  }
+
+  if (s > limit)
+  {
+    fclose(f);
+    return -2;
+  }
+
+  r = fseek(f, 0, SEEK_SET);
+  if (r != 0)
+  {
+    ec.assign(errno, boost::system::generic_category());
+    fclose(f);
+    return -1;
+  }
+
+  v.resize(s);
+  if (s == 0)
+  {
+    fclose(f);
+    return 0;
+  }
+
+  r = fread(&v[0], 1, v.size(), f);
+  if (r < 0)
+  {
+    ec.assign(errno, boost::system::generic_category());
+    fclose(f);
+    return -1;
+  }
+
+  fclose(f);
+
+  if (r != s) return -3;
+
+  return 0;
+}
+
+int line_longer_than(libtorrent::lazy_entry const& e, int limit)
+{
+  using namespace libtorrent;
+
+  int line_len = 0;
+  switch (e.type())
+  {
+  case lazy_entry::list_t:
+    line_len += 4;
+    if (line_len > limit) return -1;
+    for (int i = 0; i < e.list_size(); ++i)
+    {
+      int ret = line_longer_than(*e.list_at(i), limit - line_len);
+      if (ret == -1) return -1;
+      line_len += ret + 2;
+    }
+    break;
+  case lazy_entry::dict_t:
+    line_len += 4;
+    if (line_len > limit) return -1;
+    for (int i = 0; i < e.dict_size(); ++i)
+    {
+      line_len += 4 + e.dict_at(i).first.size();
+      if (line_len > limit) return -1;
+      int ret = line_longer_than(*e.dict_at(i).second, limit - line_len);
+      if (ret == -1) return -1;
+      line_len += ret + 1;
+    }
+    break;
+  case lazy_entry::string_t:
+    line_len += 3 + e.string_length();
+    break;
+  case lazy_entry::int_t:
+  {
+    size_type val = e.int_value();
+    while (val > 0)
+    {
+      ++line_len;
+      val /= 10;
+    }
+    line_len += 2;
+  }
+  break;
+  case lazy_entry::none_t:
+    line_len += 4;
+    break;
+  }
+
+  if (line_len > limit) return -1;
+  return line_len;
+}
+
+int main(int argc, char* argv[])
+{
+  using namespace libtorrent;
+
+  if (argc < 2 || argc > 4)
+  {
+    fputs("usage: dump_torrent torrent-file [total-items-limit] [recursion-limit]\n", stderr);
+    return 1;
+  }
+
+  int item_limit = 1000000;
+  int depth_limit = 1000;
+
+  if (argc > 2) item_limit = atoi(argv[2]);
+  if (argc > 3) depth_limit = atoi(argv[3]);
+
+  std::vector<char> buf;
+  error_code ec;
+  int ret = load_file(argv[1], buf, ec, 40 * 1000000);
+  if (ret == -1)
+  {
+    fprintf(stderr, "file too big, aborting\n");
+    return 1;
+  }
+
+  if (ret != 0)
+  {
+    fprintf(stderr, "failed to load file: %s\n", ec.message().c_str());
+    return 1;
+  }
+  lazy_entry e;
+  int pos = -1;
+  printf("decoding. recursion limit: %d total item count limit: %d\n"
+    , depth_limit, item_limit);
+  ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec, &pos
+    , depth_limit, item_limit);
+
+  printf("\n\n----- raw info -----\n\n%s\n", print_entry(e).c_str());
+
+  if (ret != 0)
+  {
+    fprintf(stderr, "failed to decode: '%s' at character: %d\n", ec.message().c_str(), pos);
+    return 1;
+  }
+
+  torrent_info t(e, ec);
+  if (ec)
+  {
+    fprintf(stderr, "%s\n", ec.message().c_str());
+    return 1;
+  }
+  e.clear();
+  std::vector<char>().swap(buf);
+
+  // print info about torrent
+  printf("\n\n----- torrent file info -----\n\n"
+    "nodes:\n");
+
+  typedef std::vector<std::pair<std::string, int> > node_vec;
+  node_vec const& nodes = t.nodes();
+  for (node_vec::const_iterator i = nodes.begin(), end(nodes.end());
+    i != end; ++i)
+  {
+    printf("%s: %d\n", i->first.c_str(), i->second);
+  }
+  puts("trackers:\n");
+  for (std::vector<announce_entry>::const_iterator i = t.trackers().begin();
+    i != t.trackers().end(); ++i)
+  {
+    printf("%2d: %s\n", i->tier, i->url.c_str());
+  }
+
+  char ih[41];
+  to_hex((char const*)&t.info_hash()[0], 20, ih);
+  printf("number of pieces: %d\n"
+    "piece length: %d\n"
+    "info hash: %s\n"
+    "comment: %s\n"
+    "created by: %s\n"
+    "magnet link: %s\n"
+    "name: %s\n"
+    "number of files: %d\n"
+    "files:\n"
+    , t.num_pieces()
+    , t.piece_length()
+    , ih
+    , t.comment().c_str()
+    , t.creator().c_str()
+    , make_magnet_uri(t).c_str()
+    , t.name().c_str()
+    , t.num_files());
+  file_storage const& st = t.files();
+  for (int i = 0; i < st.num_files(); ++i)
+  {
+    int first = st.map_file(i, 0, 0).piece;
+    int last = st.map_file(i, (std::max)(size_type(st.file_size(i))-1, size_type(0)), 0).piece;
+    int flags = st.file_flags(i);
+    printf(" %8" PRIx64 " %11" PRId64 " %c%c%c%c [ %5d, %5d ] %7u %s %s %s%s\n"
+      , st.file_offset(i)
+      , st.file_size(i)
+      , ((flags & file_storage::flag_pad_file)?'p':'-')
+      , ((flags & file_storage::flag_executable)?'x':'-')
+      , ((flags & file_storage::flag_hidden)?'h':'-')
+      , ((flags & file_storage::flag_symlink)?'l':'-')
+      , first, last
+      , boost::uint32_t(st.mtime(i))
+      , st.hash(i) != sha1_hash(0) ? to_hex(st.hash(i).to_string()).c_str() : ""
+      , st.file_path(i).c_str()
+      , (flags & file_storage::flag_symlink) ? "-> " : ""
+      , (flags & file_storage::flag_symlink) ? st.symlink(i).c_str() : "");
+  }
+
+  return 0;
+}
 
diff --git a/docs/examples.rst b/docs/examples.rst index 731577d28..6c22b6d61 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -3,6 +3,7 @@ libtorrent Examples =================== :Author: Arvid Norberg, arvid@rasterbar.com +:Version: 1.0.2 .. contents:: Table of contents :depth: 2 @@ -18,243 +19,34 @@ instructions for how to use it here__ if you'd like to try it. Note that buildin __ client_test.html -dump_torrent ------------- - -This is an example of a program that will take a torrent-file as a parameter and -print information about it to std out:: - - #include - #include - #include - #include - - #include "libtorrent/entry.hpp" - #include "libtorrent/bencode.hpp" - #include "libtorrent/torrent_info.hpp" - #include "libtorrent/lazy_entry.hpp" - #include - - - int main(int argc, char* argv[]) - { - using namespace libtorrent; - using namespace boost::filesystem; - - if (argc != 2) - { - std::cerr << "usage: dump_torrent torrent-file\n"; - return 1; - } - #if BOOST_VERSION < 103400 - boost::filesystem::path::default_name_check(boost::filesystem::no_check); - #endif - - #ifndef BOOST_NO_EXCEPTIONS - try - { - #endif - - int size = file_size(argv[1]); - if (size > 10 * 1000000) - { - std::cerr << "file too big (" << size << "), aborting\n"; - return 1; - } - std::vector buf(size); - std::ifstream(argv[1], std::ios_base::binary).read(&buf[0], size); - lazy_entry e; - int ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e); - - if (ret != 0) - { - std::cerr << "invalid bencoding: " << ret << std::endl; - return 1; - } - - std::cout << "\n\n----- raw info -----\n\n"; - std::cout << e << std::endl; - - torrent_info t(e); - - // print info about torrent - std::cout << "\n\n----- torrent file info -----\n\n"; - std::cout << "nodes:\n"; - typedef std::vector > node_vec; - node_vec const& nodes = t.nodes(); - for (node_vec::const_iterator i = nodes.begin(), end(nodes.end()); - i != end; ++i) - { - std::cout << i->first << ":" << i->second << "\n"; - } - std::cout << "trackers:\n"; - for (std::vector::const_iterator i = t.trackers().begin(); - i != t.trackers().end(); ++i) - { - std::cout << i->tier << ": " << i->url << "\n"; - } - - std::cout << "number of pieces: " << t.num_pieces() << "\n"; - std::cout << "piece length: " << t.piece_length() << "\n"; - std::cout << "info hash: " << t.info_hash() << "\n"; - std::cout << "comment: " << t.comment() << "\n"; - std::cout << "created by: " << t.creator() << "\n"; - std::cout << "files:\n"; - int index = 0; - for (torrent_info::file_iterator i = t.begin_files(); - i != t.end_files(); ++i, ++index) - { - int first = t.map_file(index, 0, 1).piece; - int last = t.map_file(index, i->size - 1, 1).piece; - std::cout << " " << std::setw(11) << i->size - << " " << i->path.string() << "[ " << first << ", " - << last << " ]\n"; - } - - #ifndef BOOST_NO_EXCEPTIONS - } - catch (std::exception& e) - { - std::cout << e.what() << "\n"; - } - #endif - - return 0; - } - simple client ------------- -This is a simple client. It doesn't have much output to keep it simple:: +This is a simple client. It doesn't have much output to keep it simple: - int main(int argc, char* argv[]) - { - using namespace libtorrent; - - if (argc != 2) - { - fputs("usage: ./simple_client torrent-file\n" - "to stop the client, press return.\n", stderr); - return 1; - } - - session s; - error_code ec; - s.listen_on(std::make_pair(6881, 6889), ec); - if (ec) - { - fprintf(stderr, "failed to open listen socket: %s\n", ec.message().c_str()); - return 1; - } - add_torrent_params p; - p.save_path = "./"; - p.ti = boost::make_shared(argv[1], ec); - if (ec) - { - fprintf(stderr, "%s\n", ec.message().c_str()); - return 1; - } - s.add_torrent(p, ec); - if (ec) - { - fprintf(stderr, "%s\n", ec.message().c_str()); - return 1; - } - - // wait for the user to end - char a; - scanf("%c\n", &a); - return 0; - } +.. include:: ../examples/simple_client.cpp + :code: c++ + :tab-width: 2 + :start-after: */ make_torrent ------------ -Shows how to create a torrent from a directory tree:: +Shows how to create a torrent from a directory tree: + +.. include:: ../examples/make_torrent.cpp + :code: c++ + :tab-width: 2 + :start-after: */ + +dump_torrent +------------ + +This is an example of a program that will take a torrent-file as a parameter and +print information about it to std out: + +.. include:: ../examples/dump_torrent.cpp + :code: c++ + :tab-width: 2 + :start-after: */ - #include - #include - #include - #include - - #include "libtorrent/entry.hpp" - #include "libtorrent/bencode.hpp" - #include "libtorrent/torrent_info.hpp" - #include "libtorrent/file.hpp" - #include "libtorrent/storage.hpp" - #include "libtorrent/hasher.hpp" - #include "libtorrent/create_torrent.hpp" - - #include - #include - #include - #include - - using namespace boost::filesystem; - using namespace libtorrent; - - // do not include files and folders whose - // name starts with a . - bool file_filter(boost::filesystem::path const& filename) - { - if (filename.leaf()[0] == '.') return false; - std::cerr << filename << std::endl; - return true; - } - - void print_progress(int i, int num) - { - std::cerr << "\r" << (i+1) << "/" << num; - } - - int main(int argc, char* argv[]) - { - using namespace libtorrent; - using namespace boost::filesystem; - - int piece_size = 256 * 1024; - char const* creator_str = "libtorrent"; - - path::default_name_check(no_check); - - if (argc != 4 && argc != 5) - { - std::cerr << "usage: make_torrent " - " " - "[url-seed]\n"; - return 1; - } - - #ifndef BOOST_NO_EXCEPTIONS - try - { - #endif - file_storage fs; - file_pool fp; - path full_path = complete(path(argv[3])); - - add_files(fs, full_path, file_filter); - - create_torrent t(fs, piece_size); - t.add_tracker(argv[2]); - set_piece_hashes(t, full_path.branch_path() - , boost::bind(&print_progress, _1, t.num_pieces())); - std::cerr << std::endl; - t.set_creator(creator_str); - - if (argc == 5) t.add_url_seed(argv[4]); - - // create the torrent and print it to out - ofstream out(complete(path(argv[1])), std::ios_base::binary); - bencode(std::ostream_iterator(out), t.generate()); - #ifndef BOOST_NO_EXCEPTIONS - } - catch (std::exception& e) - { - std::cerr << e.what() << "\n"; - } - #endif - - return 0; - } - diff --git a/docs/gen_reference_doc.py b/docs/gen_reference_doc.py index 01baf5651..05a6b7014 100644 --- a/docs/gen_reference_doc.py +++ b/docs/gen_reference_doc.py @@ -775,7 +775,7 @@ def linkify_symbols(string): # print ' literal: "%s"' % l ret.append(l) continue - if l.endswith('::'): + if l.endswith('::') or '.. code::' in l: # print ' start literal: "%s"' % l in_literal = True words = l.split(' ') diff --git a/docs/manual.rst b/docs/manual.rst index 2cbc549eb..db3b1bdd4 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -882,17 +882,9 @@ SSL torrents Torrents may have an SSL root (CA) certificate embedded in them. Such torrents are called *SSL torrents*. An SSL torrent talks to all bittorrent peers over -SSL. The protocols are layered like this:: +SSL. The protocols are layered like this: - +-----------------------+ - | BitTorrent protocol | - +-----------------------+ - | SSL | - +-----------+-----------+ - | TCP | uTP | - | +-----------+ - | | UDP | - +-----------+-----------+ +.. image:: utp_stack.png During the SSL handshake, both peers need to authenticate by providing a certificate that is signed by the CA certificate found in the .torrent file. diff --git a/docs/reference-Session.html b/docs/reference-Session.html index e4471599e..b2dec773c 100644 --- a/docs/reference-Session.html +++ b/docs/reference-Session.html @@ -852,9 +852,10 @@ included. This flag is on by default. See void post_session_stats (); -

This function will post a session_stats_alert object, containing a snapshot of -the performance counters from the internals of libtorrent. To interpret these counters, -query the session via session_stats_metrics().

+

This function will post a session_stats_alert object, containing a +snapshot of the performance counters from the internals of libtorrent. +To interpret these counters, query the session via +session_stats_metrics().

For more information, see the session statistics section.

diff --git a/docs/style.css b/docs/style.css index 4f6b1c066..5cc77cda3 100644 --- a/docs/style.css +++ b/docs/style.css @@ -366,3 +366,8 @@ li p, li li { font-size: 100%; } * html #table-of-contents ul ul { height: 1%; } /* End hide from IE-mac */ +.keyword { font-weight: bold } +.string { color: #771; } +.comment { font-style: italic; color: #559; } +.preproc { font-style: italic; color: #959; } +.number { color: #595; } diff --git a/include/libtorrent/alert.hpp b/include/libtorrent/alert.hpp index 14a284a66..d86b94d74 100644 --- a/include/libtorrent/alert.hpp +++ b/include/libtorrent/alert.hpp @@ -187,7 +187,9 @@ namespace libtorrent { // in the alert. It can be used to determine the run-time type of an alert* in // order to cast to that alert type and access specific members. // - // e.g:: + // e.g: + // + // .. code:: c++ // // std::auto_ptr a = ses.pop_alert(); // switch (a->type()) diff --git a/include/libtorrent/create_torrent.hpp b/include/libtorrent/create_torrent.hpp index 9eedc5958..33b77f21d 100644 --- a/include/libtorrent/create_torrent.hpp +++ b/include/libtorrent/create_torrent.hpp @@ -81,7 +81,9 @@ POSSIBILITY OF SUCH DAMAGE. // All of these classes and functions are declared by including // ``libtorrent/create_torrent.hpp``. // -// example:: +// example: +// +// .. code:: c++ // // file_storage fs; // @@ -184,7 +186,9 @@ namespace libtorrent // // If anything goes wrong during torrent generation, this function will return // an empty ``entry`` structure. You can test for this condition by querying the - // type of the entry:: + // type of the entry: + // + // .. code:: c++ // // file_storage fs; // // add file ... diff --git a/include/libtorrent/entry.hpp b/include/libtorrent/entry.hpp index 720f87927..edf7ce37d 100644 --- a/include/libtorrent/entry.hpp +++ b/include/libtorrent/entry.hpp @@ -160,7 +160,9 @@ namespace libtorrent // have. // // The typical code to get info from a torrent file will then look like - // this:: + // this: + // + // .. code:: c++ // // entry torrent_file; // // ... @@ -176,7 +178,9 @@ namespace libtorrent // } // // - // The following code is equivalent, but a little bit shorter:: + // The following code is equivalent, but a little bit shorter: + // + // .. code:: c++ // // entry torrent_file; // // ... diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index 49259ad28..7d1e8f2b8 100644 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -88,7 +88,7 @@ POSSIBILITY OF SUCH DAMAGE. // ``std::map``, i.e. in RAM. It's not necessarily very useful in practice, but // illustrates the basics of implementing a custom storage. // -//:: +// .. code:: c++ // // struct temp_storage : storage_interface // { diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index 3e234c046..2ac9e83b8 100644 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -682,7 +682,9 @@ namespace libtorrent // download as well as when closing down. // // Example code to pause and save resume data for all torrents and wait - // for the alerts:: + // for the alerts: + // + // .. code:: c++ // // extern int outstanding_resume_data; // global counter of outstanding resume data // std::vector handles = ses.get_torrents();