mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-06 18:22:32 +00:00
Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 65906a033a | |||
| dd5e0df05c | |||
| 00ef7d4be2 | |||
| e64f9fe324 | |||
| 9d3f6645be | |||
| 285827e611 | |||
| 7fa1166baa | |||
| 43ba43252e | |||
| 207375c0cc | |||
| 4a5bc86643 | |||
| 1039497a1a | |||
| 36a39e91c8 | |||
| d35a8d68e6 | |||
| bb1cdfc0e7 | |||
| b0c68aa398 | |||
| 1492d39a3a | |||
| 8dcf2bc609 | |||
| 7022722c64 | |||
| 2829a73d8b | |||
| 43c36db5fc | |||
| 9ed8fe8fd8 | |||
| 95cc070ecc | |||
| d43d08404a | |||
| c92becbb7c | |||
| 20887b1ccb | |||
| 3bd111e498 | |||
| f8ec1ca95e | |||
| d9976af767 | |||
| c649e49a42 | |||
| 9b0d74bd68 | |||
| 09dd1ce9c8 | |||
| eb45508ab9 | |||
| a1ff6f5710 | |||
| 756e3bd5ae | |||
| ce97bf583d | |||
| dd8281204f | |||
| 420f03b40b | |||
| 9ac43c2b40 | |||
| 25448320aa | |||
| 788442de6a | |||
| 4492715737 | |||
| f1a4c13c41 | |||
| e11ac9abe3 | |||
| 34aba86d67 | |||
| 5175414333 | |||
| 2b15c4a1fa | |||
| 84c0d516ef | |||
| 8b663dd169 | |||
| c48b7f5b93 | |||
| 4c06e7a923 | |||
| e3918f5d84 | |||
| 0948b5f86a | |||
| bb8d677f6e | |||
| dc6208ccc9 | |||
| 18d19e3dee | |||
| f0517e2748 | |||
| 47089bce70 | |||
| 64cb3d11a0 | |||
| 12347843a9 | |||
| 41589f06c2 | |||
| a51f367671 | |||
| ac4afeb4bc | |||
| 8d562d53fc | |||
| 1a79eec876 | |||
| c803970628 | |||
| 5f2f046165 | |||
| ad862f4b44 | |||
| 6c25e64c26 |
@@ -11,6 +11,12 @@ jobs:
|
||||
- name: Update Packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get install -y \
|
||||
bear \
|
||||
clang-tidy \
|
||||
libcurl4-openssl-dev
|
||||
- name: Fetch libtorrent
|
||||
run: |
|
||||
git clone https://github.com/rakshasa/libtorrent
|
||||
@@ -35,9 +41,6 @@ jobs:
|
||||
run: |
|
||||
git remote add upstream "https://github.com/${{ github.event.pull_request.base.repo.full_name }}"
|
||||
git fetch --no-tags --no-recurse-submodules upstream "${{ github.event.pull_request.base.ref }}"
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get install -y bear clang-tidy libcurl4-openssl-dev
|
||||
- name: Configure Project
|
||||
run: |
|
||||
libtoolize
|
||||
|
||||
@@ -11,6 +11,11 @@ jobs:
|
||||
- name: Update Packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get install -y \
|
||||
libcppunit-dev \
|
||||
libcurl4-openssl-dev
|
||||
- name: Fetch libtorrent
|
||||
run: |
|
||||
git clone https://github.com/rakshasa/libtorrent
|
||||
@@ -35,11 +40,6 @@ jobs:
|
||||
run: |
|
||||
git remote add upstream "https://github.com/${{ github.event.pull_request.base.repo.full_name }}"
|
||||
git fetch --no-tags --no-recurse-submodules upstream "${{ github.event.pull_request.base.ref }}"
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get install -y \
|
||||
libcppunit-dev \
|
||||
libcurl4-openssl-dev
|
||||
- name: Configure Project
|
||||
run: |
|
||||
libtoolize
|
||||
@@ -53,4 +53,12 @@ jobs:
|
||||
make
|
||||
- name: Run Unit Tests
|
||||
run: |
|
||||
ls /usr/local/lib/
|
||||
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib"
|
||||
make check
|
||||
- name: Archive test/test-suite.log
|
||||
if: success() || failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-suite.log
|
||||
path: test/test-suite.log
|
||||
|
||||
-85
@@ -1,85 +0,0 @@
|
||||
language: cpp
|
||||
|
||||
env:
|
||||
global:
|
||||
- MAKEFLAGS="-j 12"
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- compiler: clang
|
||||
env: COMPILER=clang++ SKIP_CHECK=true
|
||||
- compiler: clang
|
||||
env: COMPILER=clang++
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libcppunit-dev
|
||||
- compiler: clang
|
||||
env: COMPILER=clang++-3.6
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.6
|
||||
packages:
|
||||
- clang-3.6
|
||||
- libcppunit-dev
|
||||
- compiler: clang
|
||||
env: COMPILER=clang++-3.7
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.7
|
||||
packages:
|
||||
- clang-3.7
|
||||
- libcppunit-dev
|
||||
- compiler: clang
|
||||
env: COMPILER=clang++-3.8
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.8
|
||||
packages:
|
||||
- clang-3.8
|
||||
- libcppunit-dev
|
||||
- compiler: gcc
|
||||
env: COMPILER=g++-4.7 SKIP_CHECK=true
|
||||
addons:
|
||||
apt:
|
||||
sources: ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.7
|
||||
- compiler: gcc
|
||||
env: COMPILER=g++-4.7
|
||||
addons:
|
||||
apt:
|
||||
sources: ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.7
|
||||
- libcppunit-dev
|
||||
- compiler: gcc
|
||||
env: COMPILER=g++-4.8
|
||||
addons:
|
||||
apt:
|
||||
sources: ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.8
|
||||
- libcppunit-dev
|
||||
|
||||
# TODO: Use the same branch name if libtorrent has it.
|
||||
before_install:
|
||||
- git clone https://github.com/rakshasa/libtorrent.git
|
||||
- |
|
||||
pushd libtorrent \
|
||||
&& (git checkout ${TRAVIS_BRANCH} || true) \
|
||||
&& ./autogen.sh \
|
||||
&& CXX="$COMPILER" ./configure --prefix=/usr \
|
||||
&& make \
|
||||
&& sudo make install \
|
||||
&& popd
|
||||
|
||||
script:
|
||||
- ./autogen.sh && CXX="$COMPILER" ./configure && make
|
||||
- if [ ! $SKIP_CHECK ]; then make check; fi
|
||||
+3
-2
@@ -3,13 +3,14 @@ SUBDIRS = \
|
||||
src \
|
||||
test
|
||||
|
||||
nobase_dist_pkgdata_DATA = \
|
||||
lua/rtorrent.lua
|
||||
|
||||
EXTRA_DIST= \
|
||||
rtorrent.lua \
|
||||
rak/address_info.h \
|
||||
rak/algorithm.h \
|
||||
rak/error_number.h \
|
||||
rak/file_stat.h \
|
||||
rak/fs_stat.h \
|
||||
rak/path.h \
|
||||
rak/partial_queue.h \
|
||||
rak/regex.h \
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
BUILDING
|
||||
|
||||
Run "aclocal -I scripts && autoconf -i && autoheader && automake --add-missing"
|
||||
to generate the configure scripts if necessary. The man page "doc/rtorrent.1"
|
||||
must be generated with "docbook2man rtorrent.1.xml" if it is missing.
|
||||
|
||||
Note that rtorrent follows the development of libtorrent closely, and
|
||||
thus the versions must be in sync. This should not be nessesary in the
|
||||
future, when the library API stabilizes.
|
||||
|
||||
USAGE
|
||||
|
||||
See the man page or website for instructions.
|
||||
|
||||
LICENSE
|
||||
|
||||
GNU GPL, see COPYING. "libtorrent/src/utils/sha_fast.{cc,h}" is
|
||||
originally from the Mozilla NSS and is under a triple license; MPL,
|
||||
LGPL and GPL. An exception to non-NSS code has been added for linking
|
||||
to OpenSSL as requested by Debian, though the author considers that
|
||||
library to be part of the Operative System and thus linking is allowed
|
||||
according to the GPL.
|
||||
|
||||
Use whatever fits your purpose, the code required to compile with
|
||||
Mozilla's NSS implementation of SHA1 has been retained and can be
|
||||
compiled if the user wishes to avoid using OpenSSL.
|
||||
|
||||
DEPENDENCIES
|
||||
|
||||
libcurl >= 7.12.0
|
||||
ncurses
|
||||
|
||||
CONTACT
|
||||
|
||||
Jari Sundell
|
||||
|
||||
Skomakerveien 33
|
||||
3185 Skoppum, NORWAY
|
||||
|
||||
Send bug reports, suggestions and patches to
|
||||
<sundell.software@gmail.com> or to the mailinglist.
|
||||
@@ -1,40 +1,88 @@
|
||||
[](https://paypal.me/jarisundelljp)
|
||||
|
||||
RTorrent BitTorrent Client
|
||||
========
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
A ncurses-based command line torrent client for high performance.
|
||||
|
||||
To learn how to use rTorrent visit the [Wiki](https://github.com/rakshasa/rtorrent/wiki).
|
||||
|
||||
Stable
|
||||
------
|
||||
|
||||
* [https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.13.8.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.13.8.tar.gz)
|
||||
* [https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.9.8.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.9.8.tar.gz)
|
||||
|
||||
Unstable
|
||||
------
|
||||
|
||||
* [https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.14.0.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.14.0.tar.gz)
|
||||
* [https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.10.0.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.10.0.tar.gz)
|
||||
Download the [latest stable release](https://github.com/rakshasa/rtorrent/releases/latest)
|
||||
|
||||
Related Projects
|
||||
----------------
|
||||
|
||||
* [https://github.com/rakshasa/rbedit](https://github.com/rakshasa/rbedit): A dependency-free bencode editor.
|
||||
* [https://github.com/rakshasa/rbedit](https://github.com/rakshasa/rbedit): A dependency-free bencode editor.
|
||||
|
||||
Donate to rTorrent development
|
||||
------------------------------
|
||||
|
||||
* [Paypal](https://paypal.me/jarisundellno)
|
||||
* [Patreon](https://www.patreon.com/rtorrent)
|
||||
* [SubscribeStar](https://www.subscribestar.com/rtorrent)
|
||||
* Bitcoin: 1MpmXm5AHtdBoDaLZstJw8nupJJaeKu8V8
|
||||
* Ethereum: 0x9AB1e3C3d8a875e870f161b3e9287Db0E6DAfF78
|
||||
* Litecoin: LdyaVR67LBnTf6mAT4QJnjSG2Zk67qxmfQ
|
||||
* Cardano: addr1qytaslmqmk6dspltw06sp0zf83dh09u79j49ceh5y26zdcccgq4ph7nmx6kgmzeldauj43254ey97f3x4xw49d86aguqwfhlte
|
||||
* [Paypal](https://paypal.me/jarisundellno)
|
||||
* [Patreon](https://www.patreon.com/rtorrent)
|
||||
* [SubscribeStar](https://www.subscribestar.com/rtorrent)
|
||||
* Bitcoin: 1MpmXm5AHtdBoDaLZstJw8nupJJaeKu8V8
|
||||
* Ethereum: 0x9AB1e3C3d8a875e870f161b3e9287Db0E6DAfF78
|
||||
* Litecoin: LdyaVR67LBnTf6mAT4QJnjSG2Zk67qxmfQ
|
||||
* Cardano: addr1qytaslmqmk6dspltw06sp0zf83dh09u79j49ceh5y26zdcccgq4ph7nmx6kgmzeldauj43254ey97f3x4xw49d86aguqwfhlte
|
||||
|
||||
|
||||
Help keep rTorrent development going by donating to its creator.
|
||||
|
||||
|
||||
BUILDING
|
||||
--------
|
||||
|
||||
Jump into the github cloned directory
|
||||
|
||||
```
|
||||
cd rtorrent
|
||||
```
|
||||
|
||||
## Install build dependencies
|
||||
|
||||
Install [libtorrent](https://libtorrent.org/) with the same version rTorrent.
|
||||
|
||||
Generate configure scripts:
|
||||
|
||||
```
|
||||
autoreconf -ivf
|
||||
```
|
||||
|
||||
Optionally, generate man pages:
|
||||
|
||||
```
|
||||
docbook2man rtorrent.1.xml
|
||||
```
|
||||
|
||||
Man pages output to "doc/rtorrent.1".
|
||||
|
||||
RTorrent follows the development of [libtorrent](https://libtorrent.org/) closely, and thus the versions must be in sync.
|
||||
|
||||
## USAGE
|
||||
|
||||
Refer to User Guide: https://github.com/rakshasa/rtorrent/wiki/User-Guide
|
||||
|
||||
## LICENSE
|
||||
|
||||
GNU GPL, see COPYING. "libtorrent/src/utils/sha_fast.{cc,h}" is
|
||||
originally from the Mozilla NSS and is under a triple license; MPL,
|
||||
LGPL and GPL. An exception to non-NSS code has been added for linking to OpenSSL as requested by Debian, though the author considers that library to be part of the Operative System and thus linking is allowed according to the GPL.
|
||||
|
||||
Use whatever fits your purpose, the code required to compile with
|
||||
Mozilla's NSS implementation of SHA1 has been retained and can be
|
||||
compiled if the user wishes to avoid using OpenSSL.
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
* libcurl >= 7.12.0
|
||||
* libtorrent = (same version)
|
||||
* ncurses
|
||||
|
||||
## BUILD DEPENDENCIES
|
||||
|
||||
* libtoolize
|
||||
* aclocal
|
||||
* autoconf
|
||||
* autoheader
|
||||
* automake
|
||||
|
||||
+7
-17
@@ -1,6 +1,6 @@
|
||||
m4_pattern_allow([PKG_CHECK_EXISTS])
|
||||
|
||||
AC_INIT([rtorrent],[0.15.4],[sundell.software@gmail.com])
|
||||
AC_INIT([rtorrent],[0.16.0],[sundell.software@gmail.com])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIRS([scripts])
|
||||
@@ -10,7 +10,8 @@ AM_PROG_AR
|
||||
LT_INIT
|
||||
|
||||
AC_PROG_CXX
|
||||
AC_DEFINE([API_VERSION], [14], [api version])
|
||||
|
||||
AC_DEFINE([API_VERSION], [16], [api version])
|
||||
|
||||
# Filter out unwanted flags added by autoconf on some systems, e.g. MacOS.
|
||||
TORRENT_REMOVE_UNWANTED(CXX, $CXX, -std=c++11 -std=gnu++11)
|
||||
@@ -25,15 +26,9 @@ RAK_ENABLE_DEBUG
|
||||
RAK_ENABLE_EXTRA_DEBUG
|
||||
RAK_ENABLE_WERROR
|
||||
|
||||
TORRENT_DISABLE_IPV6
|
||||
|
||||
TORRENT_ENABLE_ARCH
|
||||
TORRENT_WITH_SYSROOT
|
||||
|
||||
TORRENT_WITHOUT_VARIABLE_FDSET
|
||||
TORRENT_WITHOUT_STATVFS
|
||||
TORRENT_WITHOUT_STATFS
|
||||
|
||||
AC_ARG_ENABLE(execinfo,
|
||||
AS_HELP_STRING([--disable-execinfo],
|
||||
[disable libexecinfo [[default=enable]]]),
|
||||
@@ -52,9 +47,8 @@ if test "x$ax_cv_ncursesw" != xyes && test "x$ax_cv_ncurses" != xyes; then
|
||||
AC_MSG_ERROR([requires either NcursesW or Ncurses library])
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES([LIBCURL], [libcurl],, [LIBCURL_CHECK_CONFIG])
|
||||
PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"])
|
||||
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.15.4])
|
||||
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.16.0])
|
||||
|
||||
AC_LANG_PUSH(C++)
|
||||
TORRENT_WITH_XMLRPC_C
|
||||
@@ -67,18 +61,14 @@ if test ${with_xmlrpc_c+y} && test ${with_xmlrpc_tinyxml2+y}; then
|
||||
AC_MSG_ERROR([--with-xmlrpc-c and --with-xmlrpc-tinyxml2 cannot be used together. Please choose only one])
|
||||
fi
|
||||
|
||||
AC_DEFINE(HAVE_CONFIG_H, 1, true if config.h was included)
|
||||
AC_DEFINE(USER_AGENT, [std::string(PACKAGE "/" VERSION "/") + torrent::version()], Http user agent)
|
||||
|
||||
AC_CHECK_FUNCS(posix_memalign)
|
||||
|
||||
dnl Only update global build variables immediately before generating the output,
|
||||
dnl to avoid affecting the global build environment for other autoconf checks.
|
||||
LIBS="$PTHREAD_LIBS $CURSES_LIB $CURSES_LIBS $LIBCURL $LIBCURL_LIBS $DEPENDENCIES_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $CURSES_LIB $CURSES_LIBS $DEPENDENCIES_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
|
||||
|
||||
TORRENT_CHECK_CACHELINE()
|
||||
TORRENT_CHECK_POPCOUNT()
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
|
||||
+1
-1
@@ -556,4 +556,4 @@ log messages, but may be useful to debug connection problems.
|
||||
.SH "AUTHORS"
|
||||
.PP
|
||||
|
||||
Jari "Rakshasa" Sundell <jaris@ifi.uio.no>
|
||||
Jari "Rakshasa" Sundell
|
||||
|
||||
@@ -1112,7 +1112,7 @@ log messages, but may be useful to debug connection problems.
|
||||
<para>
|
||||
<simplelist type="vert">
|
||||
|
||||
<member>Jari "Rakshasa" Sundell <email>jaris@ifi.uio.no</email></member>
|
||||
<member>Jari "Rakshasa" Sundell <email>sundell.software@gmail.com</email></member>
|
||||
|
||||
</simplelist>
|
||||
</para>
|
||||
|
||||
@@ -119,6 +119,10 @@
|
||||
#
|
||||
#ui.torrent_list.layout.set = "full"
|
||||
|
||||
# Set navigation keymap style ("vi", "emacs"). Default is "emacs".
|
||||
#
|
||||
#ui.keymap.style.set = "emacs"
|
||||
|
||||
# Run rTorrent as a daemon, controlled via XMLRPC.
|
||||
#
|
||||
#system.daemon.set = false
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
--[[
|
||||
A minimal rTorrent configuration that provides the basic features
|
||||
you want to have in addition to the built-in defaults.
|
||||
|
||||
See https://github.com/rakshasa/rtorrent/wiki/CONFIG-Template
|
||||
for an up-to-date version.
|
||||
|
||||
How to use this file:
|
||||
|
||||
1. Copy to destination, remove '-example' suffix
|
||||
2. Create rtorrent.rc, containing single command, which executes THIS file.
|
||||
For example:
|
||||
|
||||
lua.execute = (cat, (system.env, HOME), "/.config/rtorrent/rtorrent.rc.lua")
|
||||
|
||||
]]--
|
||||
|
||||
--[[ Bootstrap START ]]--
|
||||
|
||||
local rtorrent = require('rtorrent')
|
||||
rc = rtorrent.autocall
|
||||
|
||||
--[[ Helper functions ]]--
|
||||
|
||||
local function makeArgs(cmdline)
|
||||
return 'sh', '-c', "'"..table.concat(cmdline, "' '").."'"
|
||||
end
|
||||
|
||||
-- Instance layout (base paths)
|
||||
local home = os.getenv('HOME')
|
||||
|
||||
local cfg = {}
|
||||
cfg.basedir = home..'/rtorrent/'
|
||||
cfg.download = cfg.basedir..'download/'
|
||||
cfg.logs = cfg.basedir..'log/'
|
||||
cfg.logfile = cfg.logs..'rtorrent-'..rc.system.time()..'.log'
|
||||
cfg.session = cfg.basedir..'.session/'
|
||||
cfg.watch = cfg.basedir..'watch/'
|
||||
|
||||
rc.method.insert('cfg.download', 'private|const|string', cfg.download)
|
||||
rc.method.insert('cfg.logs', 'private|const|string', cfg.logs)
|
||||
rc.method.insert('cfg.logfile', 'private|const|string', cfg.logfile)
|
||||
rc.method.insert('cfg.session', 'private|const|string', cfg.session)
|
||||
rc.method.insert('cfg.watch', 'private|const|string', cfg.watch)
|
||||
|
||||
-- Create instance directories
|
||||
rc.execute.throw(
|
||||
makeArgs({'mkdir', '-p',
|
||||
cfg.download,
|
||||
cfg.logs,
|
||||
cfg.session,
|
||||
cfg.watch..'/load',
|
||||
cfg.watch..'/start'}))
|
||||
|
||||
-- Listening port for incoming peer traffic (fixed; you can also randomize it)
|
||||
rc.network.port_range = '50000-50000'
|
||||
rc.network.port_random = false
|
||||
|
||||
-- Tracker-less torrent and UDP tracker support
|
||||
-- (conservative settings for 'private' trackers, change for 'public')
|
||||
rc.dht.mode = 'disable'
|
||||
rc.protocol.pex = false
|
||||
rc.trackers.use_udp = false
|
||||
|
||||
-- Peer settings
|
||||
rc.throttle.max_uploads = 100
|
||||
rc.throttle.max_uploads.global = 250
|
||||
|
||||
rc.throttle.min_peers.normal = 20
|
||||
rc.throttle.max_peers.normal = 60
|
||||
rc.throttle.min_peers.seed = 30
|
||||
rc.throttle.max_peers.seed = 80
|
||||
rc.trackers.numwant = 80
|
||||
|
||||
rc.protocol.encryption.set('allow_incoming', 'try_outgoing', 'enable_retry')
|
||||
|
||||
-- Limits for file handle resources, this is optimized for
|
||||
-- an `ulimit` of 1024 (a common default). You MUST leave
|
||||
-- a ceiling of handles reserved for rTorrent's internal needs!
|
||||
rc.network.http.max_open = 50
|
||||
rc.network.max_open_files = 600
|
||||
rc.network.max_open_sockets = 300
|
||||
|
||||
-- Memory resource usage (increase if you have a large number of items loaded,
|
||||
-- and/or the available resources to spend)
|
||||
rc.pieces.memory.max = '1800M'
|
||||
rc.network.xmlrpc.size_limit = '4M'
|
||||
|
||||
-- Basic operational settings (no need to change these)
|
||||
rc.session.path = cfg.session
|
||||
rc.directory.default = cfg.download
|
||||
rc.log.execute(cfg.logs.."execute.log")
|
||||
--rc.log.xmlrpc(cfg.logs.."xmlrpc.log")
|
||||
rc.execute.nothrow(
|
||||
"sh", "-c", table.concat(
|
||||
{"echo >", rc.session.path(), "rtorrent.pid", " ", rc.system.pid()
|
||||
}))
|
||||
|
||||
-- Other operational settings (check & adapt)
|
||||
rc.encoding.add('utf8')
|
||||
rc.system.umask = 0027
|
||||
rc.system.cwd = rc.directory.default()
|
||||
rc.network.http.dns_cache_timeout = 25
|
||||
rc.schedule2('monitor_diskspace', '15', '60', 'close_low_diskspace=1000M')
|
||||
--rc.pieces.hash.on_completion = false
|
||||
--rc.view.sort_current('seeding', 'greater=d.ratio=')
|
||||
--rc.keys.layout = 'qwerty'
|
||||
--rc.network.http.capath = '/etc/ssl/certs'
|
||||
--rc.network.http.ssl_verify_peer = 0
|
||||
--rc.network.http.ssl_verify_host = 0
|
||||
--rc.network.rpc.use_xmlrpc = true
|
||||
--rc.network.rpc.use_jsonrpc = true
|
||||
|
||||
-- Some additional values and commands
|
||||
-- NOTE: just common names, not commands
|
||||
rc.method.insert('system.startup_time', 'value|const', rc.system.time())
|
||||
rc.method.insert('d.data_path', 'simple',
|
||||
[[if=(d.is_multi_file),
|
||||
(cat, (d.directory), /),
|
||||
(cat, (d.directory), /, (d.name))]])
|
||||
rc.method.insert('d.session_file', 'simple', 'cat=(session.path), (d.hash), .torrent')
|
||||
|
||||
-- Watch directories (add more as you like, but use unique schedule names)
|
||||
rc.schedule2('watch_start', '10', '10', 'load.start_verbose=(cat, (cfg.watch), "start/*.torrent")')
|
||||
rc.schedule2('watch_load', '11', '10', 'load.verbose=(cat, (cfg.watch), "load/*.torrent")')
|
||||
|
||||
-- Run the rTorrent process as a daemon in the background
|
||||
-- (and control via XMLRPC sockets)
|
||||
--rc.system.daemon = true
|
||||
--rc.network.scgi.open_local(cfg.session..'rtorrent.sock')
|
||||
--rc.execute.nothrow('chmod', '770', cfg.session..'rtorrent.sock')
|
||||
|
||||
-- Logging:
|
||||
-- Levels = critical error warn notice info debug
|
||||
-- Groups = connection_* dht_* peer_* rpc_* storage_* thread_* tracker_* torrent_*
|
||||
rc.print('Logging to '..rc.cfg.logfile())
|
||||
rc.log.open_file('log', rc.cfg.logfile())
|
||||
rc.log.add_output('info', 'log')
|
||||
--rc.log.add_output('tracker_debug', 'log')
|
||||
|
||||
--[[ END of rtorrent.rc.lua ]]--
|
||||
@@ -0,0 +1,127 @@
|
||||
-- The "rtorrent" table is passed in by the C++ code, modify and
|
||||
-- return it for loading.
|
||||
local args = {...}
|
||||
local rtorrent = args[1]
|
||||
local math = require('math')
|
||||
|
||||
-- Autocall
|
||||
-- Passes an empty first argument implicitly, as "".
|
||||
-- Allows syntax like:
|
||||
-- - `rtorrent.autocall.system.hostname()` or
|
||||
-- - `rtorrent.autocall.session.directory.set("/tmp/")`
|
||||
-- Has assignment operator, syntax sugar for `.set()` with single argument
|
||||
-- - `rtorrent.autocall.session.directory = "/tmp/"`
|
||||
-- Autocall-chains can be reused as aliases:
|
||||
-- ```lua
|
||||
-- a = rtorrent.autocall.system
|
||||
-- a.hostname() -- same as `rtorrent.autocall.system.hostname()`
|
||||
-- a.pid() -- same as `rtorrent.autocall.system.pid()`
|
||||
local mt = {}
|
||||
function mt.__call (t, ...)
|
||||
name = table.concat(rawget(t, "__namestack"), ".")
|
||||
tg = rawget(t, "__target") or ""
|
||||
success, ret = pcall(rtorrent.call, name, tg, ...)
|
||||
if not success then error(name..": "..ret, 2) end
|
||||
return ret
|
||||
end
|
||||
function mt.__index (t, key)
|
||||
ns = {table.unpack(rawget(t, "__namestack") or {})}
|
||||
tg = rawget(t, "__target") or nil
|
||||
table.insert(ns, key)
|
||||
return setmetatable({__namestack=ns, __target=tg}, mt)
|
||||
end
|
||||
function mt.__newindex (t, key, value)
|
||||
t[key].set(value)
|
||||
end
|
||||
rtorrent["autocall"] = setmetatable({}, mt)
|
||||
|
||||
-- Target-object
|
||||
-- Sets first argment for Autocall, for commands that require target.
|
||||
-- Second argument allows to add prefix to command.
|
||||
-- Allows syntax like:
|
||||
-- - `rtorrent.Target("some_infohash").d.name()` or
|
||||
-- - `rtorrent.Target:new("some_infohash").d.name()`
|
||||
-- Also can be stored as variable
|
||||
local Target = setmetatable({
|
||||
new = function (self, target, prefix)
|
||||
return self(target, prefix)
|
||||
end;
|
||||
}, {
|
||||
__call = function (self, target, prefix)
|
||||
return setmetatable(
|
||||
{__namestack={prefix}, __target=target}, mt)
|
||||
end
|
||||
})
|
||||
rtorrent["Target"] = Target
|
||||
|
||||
-- Some aliases for Target-commands
|
||||
for i, p in ipairs({ "d", "f", "p", "t", "load" }) do
|
||||
rtorrent[p] = function (target) return Target(target, p) end
|
||||
end
|
||||
|
||||
-- Insert Lua method
|
||||
-- Allow insert global lua-finction `func_name` at rtorrent slot `name`
|
||||
-- @param name string rtorrent's slot
|
||||
-- @param func_name string name of global lua-function
|
||||
-- @param method_args number|string[]|number[]
|
||||
-- rtorrent's arguments like `(d.name)` to be passed to lua-function when it be
|
||||
-- called by rtorrent:
|
||||
--
|
||||
-- 1) non-negative integer - number of first arguments to be passed
|
||||
--
|
||||
-- example:
|
||||
-- rtorrent.insert_lua_method('d.watch_handler', 'watch_handler', 1)
|
||||
--
|
||||
-- gives following rtorrent event handler:
|
||||
-- d.watch_handler=$argument.0
|
||||
--
|
||||
-- 2) table (array) of strings - concrete rtorrent strings, passed in specified
|
||||
-- order
|
||||
--
|
||||
-- example:
|
||||
-- rtorrent.insert_lua_method('d.watch_handler', 'watch_handler', { '$argument.0=' })
|
||||
--
|
||||
-- gives following rtorrent event handler:
|
||||
-- d.watch_handler=$argument.0
|
||||
--
|
||||
-- 3) table (array) of non-negative integer - indexes, converted to
|
||||
-- $argument.0, $argument.1 ..., passed in specified order
|
||||
--
|
||||
-- example:
|
||||
-- rtorrent.insert_lua_method('d.watch_handler', 'watch_handler', { 1, 0 })
|
||||
-- or:
|
||||
-- rtorrent.insert_lua_method('d.watch_handler', 'watch_handler', { [1]=1, [2]=0 })
|
||||
--
|
||||
-- gives following rtorrent event handler:
|
||||
-- d.watch_handler=$argument.1,$argument.0
|
||||
--
|
||||
-- NOTE: first argement of func_name is always target, may be empty string
|
||||
rtorrent["insert_lua_method"] = function (name, func_name, method_args)
|
||||
local args = {}
|
||||
|
||||
if method_args == nil then method_args = 0 end
|
||||
|
||||
if math.type(method_args) == 'integer' and method_args >= 0 then
|
||||
for i = 1, method_args do
|
||||
args[i] = "$argument." .. i-1 .. "="
|
||||
end
|
||||
elseif type(method_args) == 'table' then
|
||||
for i, v in ipairs(method_args) do
|
||||
if type(v) == 'string' then
|
||||
args[i] = v
|
||||
elseif math.type(v) == 'integer' and v >= 0 then
|
||||
args[i] = "$argument." .. v .. "="
|
||||
else
|
||||
error("Incorrect arguments")
|
||||
end
|
||||
end
|
||||
else
|
||||
error("Incorrect arguments")
|
||||
end
|
||||
|
||||
local arg_str = table.concat(args, ",")
|
||||
if #arg_str > 0 then arg_str = ","..arg_str end
|
||||
rtorrent.autocall.method.insert(name, "simple", 'lua.execute.str="return '..func_name..'(...)"'..arg_str)
|
||||
end
|
||||
|
||||
return rtorrent
|
||||
+1
-4
@@ -29,10 +29,7 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell
|
||||
|
||||
// Wrapper for addrinfo with focus on zero-copy conversion to and from
|
||||
// the c-type and wrapper.
|
||||
|
||||
+3
-6
@@ -29,16 +29,13 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RAK_ALGORITHM_H
|
||||
#define RAK_ALGORITHM_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
|
||||
namespace rak {
|
||||
@@ -115,7 +112,7 @@ advance_backward(_InputIter __first, _InputIter __last, _Distance __distance) {
|
||||
}
|
||||
|
||||
template <typename _Value>
|
||||
struct compare_base : public std::function<bool(_Value, _Value)> {
|
||||
struct compare_base {
|
||||
bool operator () (const _Value& complete, const _Value& base) const {
|
||||
return !complete.compare(0, base.size(), base);
|
||||
}
|
||||
|
||||
+1
-4
@@ -29,10 +29,7 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
#ifndef RAK_ERROR_NUMBER_H
|
||||
#define RAK_ERROR_NUMBER_H
|
||||
|
||||
+2
-4
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RAK_FILE_STAT_H
|
||||
#define RAK_FILE_STAT_H
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
// rak - Rakshasa's toolbox
|
||||
// Copyright (C) 2005-2007, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RAK_FS_STAT_H
|
||||
#define RAK_FS_STAT_H
|
||||
|
||||
#include <string>
|
||||
#include <cinttypes>
|
||||
|
||||
#include <rak/error_number.h>
|
||||
|
||||
#if HAVE_SYS_VFS_H
|
||||
#include <sys/vfs.h>
|
||||
#endif
|
||||
#if HAVE_SYS_STATVFS_H
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
#if HAVE_SYS_STATFS_H
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#if HAVE_SYS_MOUNT_H
|
||||
#include <sys/mount.h>
|
||||
#endif
|
||||
|
||||
namespace rak {
|
||||
|
||||
class fs_stat {
|
||||
public:
|
||||
|
||||
typedef FS_STAT_SIZE_TYPE blocksize_type;
|
||||
typedef FS_STAT_COUNT_TYPE blockcount_type;
|
||||
typedef FS_STAT_STRUCT fs_stat_type;
|
||||
|
||||
bool update(int fd) { return FS_STAT_FD; }
|
||||
bool update(const char* fn) { return FS_STAT_FN; }
|
||||
bool update(const std::string& filename) { return update(filename.c_str()); }
|
||||
|
||||
blocksize_type blocksize() { return FS_STAT_BLOCK_SIZE; }
|
||||
blockcount_type blocks_avail() { return m_stat.f_bavail; }
|
||||
int64_t bytes_avail() { return (int64_t) blocksize() * m_stat.f_bavail; }
|
||||
|
||||
private:
|
||||
fs_stat_type m_stat;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+2
-4
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RAK_PARTIAL_QUEUE_H
|
||||
#define RAK_PARTIAL_QUEUE_H
|
||||
|
||||
+2
-4
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
// Various functions for manipulating file paths. Also consider making
|
||||
// a directory iterator.
|
||||
|
||||
+3
-5
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
// This is a hacked up whole string pattern matching. Replace with
|
||||
// TR1's regex when that becomes widely available. It is intended for
|
||||
@@ -50,7 +48,7 @@
|
||||
|
||||
namespace rak {
|
||||
|
||||
class regex : public std::function<bool (std::string)> {
|
||||
class regex {
|
||||
public:
|
||||
regex() {}
|
||||
regex(const std::string& p) : m_pattern(p) {}
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
// Wrappers for the various sockaddr types with focus on zero-copy
|
||||
// casting between the original type and the wrapper class.
|
||||
@@ -393,7 +391,7 @@ socket_address::copy(const socket_address& src, size_t length) {
|
||||
inline void
|
||||
socket_address::copy_sockaddr(const sockaddr* src) {
|
||||
std::memset(this, 0, sizeof(socket_address));
|
||||
std::memcpy(this, src, socket_address::cast_from(src)->length());
|
||||
std::memcpy(static_cast<void*>(this), src, socket_address::cast_from(src)->length());
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
||||
+2
-4
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RAK_STRING_MANIP_H
|
||||
#define RAK_STRING_MANIP_H
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RAK_UNORDERED_VECTOR_H
|
||||
#define RAK_UNORDERED_VECTOR_H
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
-- the "rtorrent" table is passed in by the C++ code, modify and
|
||||
-- return it for loading.
|
||||
local args = {...}
|
||||
local rtorrent = args[1]
|
||||
|
||||
-- Autocall
|
||||
-- Allows syntax like `rtorrent.autocall.system.hostname()`
|
||||
local mt = {}
|
||||
function mt.__call (t, ...)
|
||||
name = table.concat(rawget(t, "__namestack"), ".")
|
||||
success, ret = pcall(rtorrent.call, name, ...)
|
||||
if not success then error(name..": "..ret, 2) end
|
||||
return ret
|
||||
end
|
||||
function mt.__index (t, key)
|
||||
ns = rawget(t, "__namestack") or {}
|
||||
table.insert(ns, key)
|
||||
return setmetatable({__namestack=ns}, mt)
|
||||
end
|
||||
rtorrent["autocall"] = setmetatable({}, mt)
|
||||
|
||||
-- Autocall-config Same as autocall, but passes an empty first target
|
||||
-- implicitly, for syntax like `rtorrent.autocall_config.session.directory.set("/tmp/")`
|
||||
local mt = {}
|
||||
function mt.__call (t, ...)
|
||||
name = table.concat(rawget(t, "__namestack"), ".")
|
||||
success, ret = pcall(rtorrent.call, name, "", ...)
|
||||
if not success then error(name..": "..ret, 2) end
|
||||
return ret
|
||||
end
|
||||
function mt.__index (t, key)
|
||||
ns = rawget(t, "__namestack")
|
||||
if ns == nil then
|
||||
if _G[key] ~= nil then return _G[key] end
|
||||
ns = {}
|
||||
end
|
||||
table.insert(ns, key)
|
||||
return setmetatable({__namestack=ns}, mt)
|
||||
end
|
||||
rtorrent["autocall_config"] = setmetatable({}, mt)
|
||||
|
||||
return rtorrent
|
||||
+1
-128
@@ -118,19 +118,6 @@ AC_DEFUN([TORRENT_WITHOUT_KQUEUE], [
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([TORRENT_WITHOUT_VARIABLE_FDSET], [
|
||||
AC_ARG_WITH(variable-fdset,
|
||||
AS_HELP_STRING([--without-variable-fdset],[do not use non-portable variable sized fd_set's]),
|
||||
[
|
||||
if test "$withval" = "yes"; then
|
||||
AC_DEFINE(USE_VARIABLE_FDSET, 1, defined when we allow the use of fd_set's of any size)
|
||||
fi
|
||||
], [
|
||||
AC_DEFINE(USE_VARIABLE_FDSET, 1, defined when we allow the use of fd_set's of any size)
|
||||
])
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([TORRENT_CHECK_FALLOCATE], [
|
||||
AC_MSG_CHECKING(for fallocate)
|
||||
|
||||
@@ -170,121 +157,6 @@ AC_DEFUN([TORRENT_WITH_POSIX_FALLOCATE], [
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([TORRENT_CHECK_STATVFS], [
|
||||
AC_CHECK_HEADERS(sys/vfs.h sys/statvfs.h sys/statfs.h)
|
||||
|
||||
AC_MSG_CHECKING(for statvfs)
|
||||
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#if HAVE_SYS_VFS_H
|
||||
#include <sys/vfs.h>
|
||||
#endif
|
||||
#if HAVE_SYS_STATVFS_H
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
#if HAVE_SYS_STATFS_H
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
]], [[
|
||||
struct statvfs s; fsblkcnt_t c;
|
||||
statvfs("", &s);
|
||||
fstatvfs(0, &s);
|
||||
]])],[
|
||||
AC_DEFINE(FS_STAT_FD, [fstatvfs(fd, &m_stat) == 0], Function to determine filesystem stats from fd)
|
||||
AC_DEFINE(FS_STAT_FN, [statvfs(fn, &m_stat) == 0], Function to determine filesystem stats from filename)
|
||||
AC_DEFINE(FS_STAT_STRUCT, [struct statvfs], Type of second argument to statfs function)
|
||||
AC_DEFINE(FS_STAT_SIZE_TYPE, [unsigned long], Type of block size member in stat struct)
|
||||
AC_DEFINE(FS_STAT_COUNT_TYPE, [fsblkcnt_t], Type of block count member in stat struct)
|
||||
AC_DEFINE(FS_STAT_BLOCK_SIZE, [(m_stat.f_frsize)], Determine the block size)
|
||||
AC_MSG_RESULT(ok)
|
||||
have_stat_vfs=yes
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
have_stat_vfs=no
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([TORRENT_CHECK_STATFS], [
|
||||
AC_CHECK_HEADERS(sys/statfs.h sys/param.h sys/mount.h)
|
||||
|
||||
AC_MSG_CHECKING(for statfs)
|
||||
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#if HAVE_SYS_STATFS_H
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#if HAVE_SYS_MOUNT_H
|
||||
#include <sys/mount.h>
|
||||
#endif
|
||||
]], [[
|
||||
struct statfs s;
|
||||
statfs("", &s);
|
||||
fstatfs(0, &s);
|
||||
]])],[
|
||||
AC_DEFINE(FS_STAT_FD, [fstatfs(fd, &m_stat) == 0], Function to determine filesystem stats from fd)
|
||||
AC_DEFINE(FS_STAT_FN, [statfs(fn, &m_stat) == 0], Function to determine filesystem stats from filename)
|
||||
AC_DEFINE(FS_STAT_STRUCT, [struct statfs], Type of second argument to statfs function)
|
||||
AC_DEFINE(FS_STAT_SIZE_TYPE, [long], Type of block size member in stat struct)
|
||||
AC_DEFINE(FS_STAT_COUNT_TYPE, [long], Type of block count member in stat struct)
|
||||
AC_DEFINE(FS_STAT_BLOCK_SIZE, [(m_stat.f_bsize)], Determine the block size)
|
||||
AC_MSG_RESULT(ok)
|
||||
have_stat_vfs=yes
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
have_stat_vfs=no
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([TORRENT_DISABLED_STATFS], [
|
||||
AC_DEFINE(FS_STAT_FD, [(errno = ENOSYS) == 0], Function to determine filesystem stats from fd)
|
||||
AC_DEFINE(FS_STAT_FN, [(errno = ENOSYS) == 0], Function to determine filesystem stats from filename)
|
||||
AC_DEFINE(FS_STAT_STRUCT, [struct {blocksize_type f_bsize; blockcount_type f_bavail;}], Type of second argument to statfs function)
|
||||
AC_DEFINE(FS_STAT_SIZE_TYPE, [int], Type of block size member in stat struct)
|
||||
AC_DEFINE(FS_STAT_COUNT_TYPE, [int], Type of block count member in stat struct)
|
||||
AC_DEFINE(FS_STAT_BLOCK_SIZE, [(4096)], Determine the block size)
|
||||
AC_MSG_RESULT(No filesystem stats available)
|
||||
])
|
||||
|
||||
AC_DEFUN([TORRENT_WITHOUT_STATVFS], [
|
||||
AC_ARG_WITH(statvfs,
|
||||
AS_HELP_STRING([--without-statvfs],[don't try to use statvfs to find free diskspace]),
|
||||
[
|
||||
if test "$withval" = "yes"; then
|
||||
TORRENT_CHECK_STATVFS
|
||||
else
|
||||
have_stat_vfs=no
|
||||
fi
|
||||
],
|
||||
[
|
||||
TORRENT_CHECK_STATVFS
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([TORRENT_WITHOUT_STATFS], [
|
||||
AC_ARG_WITH(statfs,
|
||||
AS_HELP_STRING([--without-statfs],[don't try to use statfs to find free diskspace]),
|
||||
[
|
||||
if test "$have_stat_vfs" = "no"; then
|
||||
if test "$withval" = "yes"; then
|
||||
TORRENT_CHECK_STATFS
|
||||
else
|
||||
TORRENT_DISABLED_STATFS
|
||||
fi
|
||||
fi
|
||||
],
|
||||
[
|
||||
if test "$have_stat_vfs" = "no"; then
|
||||
TORRENT_CHECK_STATFS
|
||||
if test "$have_stat_vfs" = "no"; then
|
||||
TORRENT_DISABLED_STATFS
|
||||
fi
|
||||
fi
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([TORRENT_WITH_ADDRESS_SPACE], [
|
||||
AC_ARG_WITH(address-space,
|
||||
AS_HELP_STRING([--with-address-space=MB],[change the default address space size [[default=1024mb]]]),
|
||||
@@ -412,6 +284,7 @@ AC_DEFUN([TORRENT_WITH_LUA], [
|
||||
AX_LUA_LIBS
|
||||
AX_LUA_HEADERS
|
||||
AC_DEFINE(HAVE_LUA, 1, Use LUA.)
|
||||
AC_DEFINE(LUA_DATADIR, [PACKAGE_DATADIR "/lua"], [LUA data directory])
|
||||
LIBS="$LIBS $LUA_LIB"
|
||||
CXXFLAGS="$CXXFLAGS $LUA_INCLUDE"
|
||||
fi
|
||||
|
||||
@@ -23,6 +23,7 @@ AC_DEFUN([TORRENT_WITH_SYSROOT], [
|
||||
|
||||
AC_DEFUN([TORRENT_REMOVE_UNWANTED],
|
||||
[
|
||||
AC_REQUIRE([AC_PROG_GREP])
|
||||
values_to_check=`for i in $2; do echo $i; done`
|
||||
unwanted_values=`for i in $3; do echo $i; done`
|
||||
if test -z "${unwanted_values}"; then
|
||||
|
||||
+1
-8
@@ -5,12 +5,6 @@ rtorrent_LDADD = libsub_root.a @PTHREAD_LIBS@
|
||||
rtorrent_SOURCES = main.cc
|
||||
|
||||
libsub_root_a_SOURCES = \
|
||||
core/curl_get.cc \
|
||||
core/curl_get.h \
|
||||
core/curl_socket.cc \
|
||||
core/curl_socket.h \
|
||||
core/curl_stack.cc \
|
||||
core/curl_stack.h \
|
||||
core/dht_manager.cc \
|
||||
core/dht_manager.h \
|
||||
core/download.cc \
|
||||
@@ -19,7 +13,6 @@ libsub_root_a_SOURCES = \
|
||||
core/download_factory.h \
|
||||
core/download_list.cc \
|
||||
core/download_list.h \
|
||||
core/download_slot_map.h \
|
||||
core/download_store.cc \
|
||||
core/download_store.h \
|
||||
core/http_queue.cc \
|
||||
@@ -202,4 +195,4 @@ libsub_root_a_SOURCES = \
|
||||
thread_worker.h
|
||||
|
||||
|
||||
AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir)
|
||||
AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir) -DPACKAGE_DATADIR=\"$(pkgdatadir)\"
|
||||
|
||||
+22
-24
@@ -265,12 +265,12 @@ retrieve_d_custom_map(core::Download* download, bool keys_only, const torrent::O
|
||||
throw torrent::bencode_error("d.custom.keys/items takes no arguments.");
|
||||
|
||||
torrent::Object result = keys_only ? torrent::Object::create_list() : torrent::Object::create_map();
|
||||
torrent::Object::map_type& entries = download->bencode()->get_key("rtorrent").get_key("custom").as_map();
|
||||
|
||||
for (torrent::Object::map_type::const_iterator itr = entries.begin(), last = entries.end(); itr != last; itr++) {
|
||||
if (keys_only) result.as_list().push_back(itr->first);
|
||||
else result.as_map()[itr->first] = itr->second;
|
||||
}
|
||||
for (const auto& entry : download->bencode()->get_key("rtorrent").get_key("custom").as_map())
|
||||
if (keys_only)
|
||||
result.as_list().push_back(entry.first);
|
||||
else
|
||||
result.as_map()[entry.first] = entry.second;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -353,25 +353,23 @@ f_multicall(core::Download* download, const torrent::Object::list_type& args) {
|
||||
bool use_regex = true;
|
||||
|
||||
if (args.front().is_list())
|
||||
std::transform(args.front().as_list().begin(), args.front().as_list().end(),
|
||||
std::back_inserter(regex_list),
|
||||
std::bind(&torrent::Object::as_string_c, std::placeholders::_1));
|
||||
for (const auto& o : args.front().as_list())
|
||||
regex_list.push_back(o.as_string_c());
|
||||
else if (args.front().is_string() && !args.front().as_string().empty())
|
||||
regex_list.push_back(args.front().as_string());
|
||||
else
|
||||
use_regex = false;
|
||||
|
||||
for (torrent::FileList::const_iterator itr = download->file_list()->begin(), last = download->file_list()->end(); itr != last; itr++) {
|
||||
for (const auto& file : *download->file_list()) {
|
||||
if (use_regex &&
|
||||
std::find_if(regex_list.begin(), regex_list.end(),
|
||||
std::bind(&rak::regex::operator(), std::placeholders::_1, (*itr)->path()->as_string())) == regex_list.end())
|
||||
std::none_of(regex_list.begin(), regex_list.end(), [&file](const auto& r) { return r(file->path()->as_string()); }))
|
||||
continue;
|
||||
|
||||
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
|
||||
|
||||
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
|
||||
const std::string& cmd = cItr->as_string();
|
||||
row.push_back(rpc::parse_command(rpc::make_target(itr->get()), cmd.c_str(), cmd.c_str() + cmd.size()).first);
|
||||
row.push_back(rpc::parse_command(rpc::make_target(file.get()), cmd.c_str(), cmd.c_str() + cmd.size()).first);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,14 +419,13 @@ p_multicall(core::Download* download, const torrent::Object::list_type& args) {
|
||||
torrent::Object resultRaw = torrent::Object::create_list();
|
||||
torrent::Object::list_type& result = resultRaw.as_list();
|
||||
|
||||
for (torrent::ConnectionList::const_iterator itr = download->connection_list()->begin(), last = download->connection_list()->end();
|
||||
itr != last; itr++) {
|
||||
for (const auto& connection : *download->connection_list()) {
|
||||
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
|
||||
|
||||
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
|
||||
const std::string& cmd = cItr->as_string();
|
||||
|
||||
row.push_back(rpc::parse_command(rpc::make_target(*itr), cmd.c_str(), cmd.c_str() + cmd.size()).first);
|
||||
row.push_back(rpc::parse_command(rpc::make_target(connection), cmd.c_str(), cmd.c_str() + cmd.size()).first);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -547,19 +544,20 @@ download_set_variable_string(core::Download* download, const torrent::Object::st
|
||||
//
|
||||
|
||||
torrent::Object
|
||||
d_list_push_back(core::Download* download, const torrent::Object& rawArgs, const char* first_key, const char* second_key) {
|
||||
download_get_variable(download, first_key, second_key).as_list().push_back(rawArgs);
|
||||
d_list_push_back_string(core::Download* download, const torrent::Object& rawArgs, const char* first_key, const char* second_key) {
|
||||
auto& arg = rawArgs.as_string();
|
||||
download_get_variable(download, first_key, second_key).as_list().push_back(arg);
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
d_list_push_back_unique(core::Download* download, const torrent::Object& rawArgs, const char* first_key, const char* second_key) {
|
||||
const torrent::Object& args = (rawArgs.is_list() && !rawArgs.as_list().empty()) ? rawArgs.as_list().front() : rawArgs;
|
||||
d_list_push_back_unique_string(core::Download* download, const torrent::Object& rawArgs, const char* first_key, const char* second_key) {
|
||||
auto& arg = rawArgs.as_string();
|
||||
torrent::Object::list_type& list = download_get_variable(download, first_key, second_key).as_list();
|
||||
|
||||
if (std::find_if(list.begin(), list.end(), [args](const torrent::Object& obj) { return torrent::object_equal(obj, args); }) == list.end())
|
||||
list.push_back(rawArgs);
|
||||
if (std::none_of(list.begin(), list.end(), [arg](const torrent::Object& obj) { return torrent::object_equal(obj, arg); }))
|
||||
list.push_back(arg);
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
@@ -569,7 +567,7 @@ d_list_has(core::Download* download, const torrent::Object& rawArgs, const char*
|
||||
const torrent::Object& args = (rawArgs.is_list() && !rawArgs.as_list().empty()) ? rawArgs.as_list().front() : rawArgs;
|
||||
torrent::Object::list_type& list = download_get_variable(download, first_key, second_key).as_list();
|
||||
|
||||
return (int64_t)(std::find_if(list.begin(), list.end(), [args](const torrent::Object& obj) { return torrent::object_equal(obj, args); }) != list.end());
|
||||
return (int64_t)(std::any_of(list.begin(), list.end(), [args](const auto& obj) { return torrent::object_equal(obj, args); }));
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
@@ -776,8 +774,8 @@ initialize_command_download() {
|
||||
CMD2_DL ("d.views", std::bind(&download_get_variable, std::placeholders::_1, "rtorrent", "views"));
|
||||
CMD2_DL ("d.views.has", std::bind(&d_list_has, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
|
||||
CMD2_DL ("d.views.remove", std::bind(&d_list_remove, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
|
||||
CMD2_DL ("d.views.push_back", std::bind(&d_list_push_back, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
|
||||
CMD2_DL ("d.views.push_back_unique", std::bind(&d_list_push_back_unique, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
|
||||
CMD2_DL ("d.views.push_back", std::bind(&d_list_push_back_string, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
|
||||
CMD2_DL ("d.views.push_back_unique", std::bind(&d_list_push_back_unique_string, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
|
||||
|
||||
// This command really needs to be improved, so we have proper
|
||||
// logging support.
|
||||
|
||||
@@ -25,9 +25,9 @@ static std::vector<std::pair<const char*, int>> object_storage_flags = {
|
||||
|
||||
static int
|
||||
object_storage_parse_flag(const std::string& flag) {
|
||||
for (auto f : object_storage_flags)
|
||||
if (f.first == flag)
|
||||
return f.second;
|
||||
for (auto [n, f] : object_storage_flags)
|
||||
if (n == flag)
|
||||
return f;
|
||||
|
||||
throw torrent::input_error("unknown flag");
|
||||
}
|
||||
@@ -380,13 +380,11 @@ system_method_set_key(const torrent::Object::list_type& args) {
|
||||
|
||||
torrent::Object
|
||||
system_method_list_keys(const torrent::Object::string_type& args) {
|
||||
const torrent::Object::map_type& multi_cmd = control->object_storage()->get_str(args).as_map();
|
||||
|
||||
torrent::Object rawResult = torrent::Object::create_list();
|
||||
torrent::Object::list_type& result = rawResult.as_list();
|
||||
|
||||
for (torrent::Object::map_const_iterator itr = multi_cmd.begin(), last = multi_cmd.end(); itr != last; itr++)
|
||||
result.push_back(itr->first);
|
||||
for (const auto& itr : control->object_storage()->get_str(args).as_map())
|
||||
result.push_back(itr.first);
|
||||
|
||||
return rawResult;
|
||||
}
|
||||
|
||||
+17
-19
@@ -55,23 +55,23 @@ apply_on_ratio(const torrent::Object& rawArgs) {
|
||||
|
||||
auto ratio_command = "group." + group_name + ".ratio.command";
|
||||
|
||||
for (std::vector<core::Download*>::iterator itr = downloads.begin(), last = downloads.end(); itr != last; itr++)
|
||||
rpc::commands.call_catch(ratio_command, rpc::make_target(*itr), torrent::Object(), "Ratio reached, but command failed: ");
|
||||
for (const auto& download : downloads)
|
||||
rpc::commands.call_catch(ratio_command, rpc::make_target(download), torrent::Object(), "Ratio reached, but command failed: ");
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_start_tied() {
|
||||
for (auto itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) {
|
||||
if (rpc::call_command_value("d.state", rpc::make_target(*itr)) == 1)
|
||||
for (const auto& download : *control->core()->download_list()) {
|
||||
if (rpc::call_command_value("d.state", rpc::make_target(download)) == 1)
|
||||
continue;
|
||||
|
||||
rak::file_stat fs;
|
||||
const std::string& tied_to_file = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
|
||||
const std::string& tied_to_file = rpc::call_command_string("d.tied_to_file", rpc::make_target(download));
|
||||
|
||||
if (!tied_to_file.empty() && fs.update(rak::path_expand(tied_to_file)))
|
||||
rpc::parse_command_single(rpc::make_target(*itr), "d.try_start=");
|
||||
rpc::parse_command_single(rpc::make_target(download), "d.try_start=");
|
||||
}
|
||||
|
||||
return torrent::Object();
|
||||
@@ -79,15 +79,15 @@ apply_start_tied() {
|
||||
|
||||
torrent::Object
|
||||
apply_stop_untied() {
|
||||
for (auto itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) {
|
||||
if (rpc::call_command_value("d.state", rpc::make_target(*itr)) == 0)
|
||||
for (const auto& download : *control->core()->download_list()) {
|
||||
if (rpc::call_command_value("d.state", rpc::make_target(download)) == 0)
|
||||
continue;
|
||||
|
||||
rak::file_stat fs;
|
||||
const std::string& tied_to_file = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
|
||||
const std::string& tied_to_file = rpc::call_command_string("d.tied_to_file", rpc::make_target(download));
|
||||
|
||||
if (!tied_to_file.empty() && !fs.update(rak::path_expand(tied_to_file)))
|
||||
rpc::parse_command_single(rpc::make_target(*itr), "d.try_stop=");
|
||||
rpc::parse_command_single(rpc::make_target(download), "d.try_stop=");
|
||||
}
|
||||
|
||||
return torrent::Object();
|
||||
@@ -95,12 +95,12 @@ apply_stop_untied() {
|
||||
|
||||
torrent::Object
|
||||
apply_close_untied() {
|
||||
for (auto itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) {
|
||||
for (const auto& download : *control->core()->download_list()) {
|
||||
rak::file_stat fs;
|
||||
const std::string& tied_to_file = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
|
||||
const std::string& tied_to_file = rpc::call_command_string("d.tied_to_file", rpc::make_target(download));
|
||||
|
||||
if (rpc::call_command_value("d.ignore_commands", rpc::make_target(*itr)) == 0 && !tied_to_file.empty() && !fs.update(rak::path_expand(tied_to_file)))
|
||||
rpc::parse_command_single(rpc::make_target(*itr), "d.try_close=");
|
||||
if (rpc::call_command_value("d.ignore_commands", rpc::make_target(download)) == 0 && !tied_to_file.empty() && !fs.update(rak::path_expand(tied_to_file)))
|
||||
rpc::parse_command_single(rpc::make_target(download), "d.try_close=");
|
||||
}
|
||||
|
||||
return torrent::Object();
|
||||
@@ -234,9 +234,7 @@ d_multicall(const torrent::Object::list_type& args) {
|
||||
|
||||
// Add some pre-parsing of the commands, so we don't spend time
|
||||
// parsing and searching command map for every single call.
|
||||
std::vector<core::Download*> dlist((*view_itr)->size_visible());
|
||||
|
||||
std::copy((*view_itr)->begin_visible(), (*view_itr)->end_visible(), dlist.data());
|
||||
std::vector<core::Download*> dlist((*view_itr)->begin_visible(), (*view_itr)->end_visible());
|
||||
|
||||
torrent::Object resultRaw = torrent::Object::create_list();
|
||||
torrent::Object::list_type& result = resultRaw.as_list();
|
||||
@@ -275,14 +273,14 @@ d_multicall_filtered(const torrent::Object::list_type& args) {
|
||||
torrent::Object::list_type& result = resultRaw.as_list();
|
||||
++arg; // skip to first command
|
||||
|
||||
for (core::View::iterator item = dlist.begin(); item != dlist.end(); ++item) {
|
||||
for (const auto& item : dlist) {
|
||||
// Add empty row to result
|
||||
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
|
||||
|
||||
// Call the provided commands and assemble their results
|
||||
for (torrent::Object::list_const_iterator command = arg; command != args.end(); command++) {
|
||||
auto& cmdstr = command->as_string();
|
||||
row.push_back(rpc::parse_command(rpc::make_target(*item), cmdstr.c_str(), cmdstr.c_str() + cmdstr.size()).first);
|
||||
row.push_back(rpc::parse_command(rpc::make_target(item), cmdstr.c_str(), cmdstr.c_str() + cmdstr.size()).first);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-6
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@@ -76,8 +74,8 @@ apply_f_path_components(torrent::File* file) {
|
||||
torrent::Object resultRaw = torrent::Object::create_list();
|
||||
torrent::Object::list_type& result = resultRaw.as_list();
|
||||
|
||||
for (torrent::Path::const_iterator itr = file->path()->begin(), last = file->path()->end(); itr != last; itr++)
|
||||
result.push_back(*itr);
|
||||
for (const auto& itr : *file->path())
|
||||
result.push_back(itr);
|
||||
|
||||
return resultRaw;
|
||||
}
|
||||
|
||||
@@ -180,8 +180,7 @@ apply_cg_insert(const std::string& arg) {
|
||||
if (rpc::parse_whole_value_nothrow(arg.c_str(), &dummy))
|
||||
throw torrent::input_error("Cannot use a value string as choke group name.");
|
||||
|
||||
if (arg.empty() ||
|
||||
std::find_if(cg_list_hack.begin(), cg_list_hack.end(), [&arg](torrent::choke_group* cg) { return arg == cg->name(); }) != cg_list_hack.end())
|
||||
if (arg.empty() || std::any_of(cg_list_hack.begin(), cg_list_hack.end(), [&arg](auto cg) { return arg == cg->name(); }))
|
||||
throw torrent::input_error("Duplicate name for choke group.");
|
||||
|
||||
cg_list_hack.push_back(new torrent::choke_group());
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
+2
-4
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <torrent/chunk_manager.h>
|
||||
#include <torrent/data/file_manager.h>
|
||||
#include <torrent/data/chunk_utils.h>
|
||||
#include <torrent/utils/chrono.h>
|
||||
#include <torrent/utils/option_strings.h>
|
||||
|
||||
#include "core/download.h"
|
||||
@@ -34,11 +35,10 @@ typedef torrent::FileManager FM_t;
|
||||
torrent::Object
|
||||
apply_pieces_stats_total_size() {
|
||||
uint64_t size = 0;
|
||||
core::DownloadList* d_list = control->core()->download_list();
|
||||
|
||||
for (core::DownloadList::iterator itr = d_list->begin(), last = d_list->end(); itr != last; itr++)
|
||||
if ((*itr)->is_active())
|
||||
size += (*itr)->file_list()->size_bytes();
|
||||
for (const auto& d : *control->core()->download_list())
|
||||
if (d->is_active())
|
||||
size += d->file_list()->size_bytes();
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -108,19 +108,18 @@ apply_log(const torrent::Object::string_type& arg, int logType) {
|
||||
|
||||
torrent::Object
|
||||
log_vmmap_dump(const std::string& str) {
|
||||
core::DownloadList* d_list = control->core()->download_list();
|
||||
std::vector<torrent::vm_mapping> all_mappings;
|
||||
|
||||
for (core::DownloadList::iterator itr = d_list->begin(), last = d_list->end(); itr != last; itr++) {
|
||||
std::vector<torrent::vm_mapping> tmp_mappings = torrent::chunk_list_mapping((*itr)->download());
|
||||
for (const auto& d : *control->core()->download_list()) {
|
||||
std::vector<torrent::vm_mapping> tmp_mappings = torrent::chunk_list_mapping(d->download());
|
||||
|
||||
all_mappings.insert(all_mappings.end(), tmp_mappings.begin(), tmp_mappings.end());
|
||||
all_mappings.insert(all_mappings.end(), tmp_mappings.begin(), tmp_mappings.end());
|
||||
}
|
||||
|
||||
FILE* log_file = fopen(str.c_str(), "w");
|
||||
|
||||
for (std::vector<torrent::vm_mapping>::iterator itr = all_mappings.begin(), last = all_mappings.end(); itr != last; itr++) {
|
||||
fprintf(log_file, "%8p-%8p [%5llxk]\n", itr->ptr, (char*)itr->ptr + itr->length, (long long unsigned int)(itr->length / 1024));
|
||||
for (auto& all_mapping : all_mappings) {
|
||||
fprintf(log_file, "%8p-%8p [%5llxk]\n", all_mapping.ptr, (char*)all_mapping.ptr + all_mapping.length, (long long unsigned int)(all_mapping.length / 1024));
|
||||
}
|
||||
|
||||
fclose(log_file);
|
||||
|
||||
+33
-56
@@ -5,16 +5,16 @@
|
||||
#include <unistd.h>
|
||||
#include <rak/address_info.h>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/connection_manager.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/connection_manager.h>
|
||||
#include <torrent/data/file_manager.h>
|
||||
#include <torrent/download/resource_manager.h>
|
||||
#include <torrent/net/http_stack.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <torrent/utils/option_strings.h>
|
||||
|
||||
#include "core/curl_stack.h"
|
||||
#include "core/download.h"
|
||||
#include "core/manager.h"
|
||||
#include "rpc/scgi.h"
|
||||
@@ -30,8 +30,8 @@ torrent::Object
|
||||
apply_encryption(const torrent::Object::list_type& args) {
|
||||
uint32_t options_mask = torrent::ConnectionManager::encryption_none;
|
||||
|
||||
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
|
||||
uint32_t opt = torrent::option_find_string(torrent::OPTION_ENCRYPTION, itr->as_string().c_str());
|
||||
for (const auto& arg : args) {
|
||||
uint32_t opt = torrent::option_find_string(torrent::OPTION_ENCRYPTION, arg.as_string().c_str());
|
||||
|
||||
if (opt == torrent::ConnectionManager::encryption_none)
|
||||
options_mask = torrent::ConnectionManager::encryption_none;
|
||||
@@ -59,45 +59,20 @@ apply_tos(const torrent::Object::string_type& arg) {
|
||||
torrent::Object apply_encoding_list(const std::string& arg) { torrent::encoding_list()->push_back(arg); return torrent::Object(); }
|
||||
|
||||
void
|
||||
initialize_rpc() {
|
||||
rpc::rpc.initialize();
|
||||
|
||||
rpc::rpc.slot_find_download() = [](const char* hash) {
|
||||
return control->core()->download_list()->find_hex_ptr(hash);
|
||||
};
|
||||
rpc::rpc.slot_find_file() = [](core::Download* d, uint32_t index) -> torrent::File* {
|
||||
if (index >= d->file_list()->size_files())
|
||||
throw torrent::input_error("invalid parameters: index not found");
|
||||
|
||||
return (*d->file_list())[index].get();
|
||||
};
|
||||
rpc::rpc.slot_find_tracker() = [](core::Download* d, uint32_t index) -> torrent::tracker::Tracker {
|
||||
if (index >= d->tracker_controller().size())
|
||||
throw torrent::input_error("invalid parameters: index not found");
|
||||
|
||||
// TODO: This should be rewritten to check if the tracker is valid and use a different
|
||||
// function.
|
||||
return d->tracker_controller().at(index);
|
||||
};
|
||||
rpc::rpc.slot_find_peer() = [](core::Download* d, const torrent::HashString& hash) -> torrent::Peer* {
|
||||
auto itr = d->connection_list()->find(hash.c_str());
|
||||
|
||||
if (itr == d->connection_list()->end())
|
||||
throw torrent::input_error("invalid parameters: hash not found");
|
||||
|
||||
return *itr;
|
||||
};
|
||||
initialize_rpc_handlers() {
|
||||
rpc::rpc.initialize_handlers();
|
||||
|
||||
unsigned int count = 0;
|
||||
|
||||
for (rpc::CommandMap::const_iterator itr = rpc::commands.begin(), last = rpc::commands.end(); itr != last; itr++, count++) {
|
||||
if (!(itr->second.m_flags & rpc::CommandMap::flag_public_rpc))
|
||||
for (const auto& [name, cmd] : rpc::commands) {
|
||||
if (!(cmd.m_flags & rpc::CommandMap::flag_public_rpc))
|
||||
continue;
|
||||
|
||||
rpc::rpc.insert_command(itr->first.c_str(), itr->second.m_parm, itr->second.m_doc);
|
||||
rpc::rpc.insert_command(name.c_str(), cmd.m_parm, cmd.m_doc);
|
||||
++count;
|
||||
}
|
||||
|
||||
lt_log_print(torrent::LOG_RPC_EVENTS, "RPC initialized with %u functions.", count);
|
||||
lt_log_print(torrent::LOG_RPC_EVENTS, "RPC manager initialized with %u functions.", count);
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
@@ -105,7 +80,7 @@ apply_scgi(const std::string& arg, int type) {
|
||||
if (worker_thread->scgi() != NULL)
|
||||
throw torrent::input_error("SCGI already enabled.");
|
||||
|
||||
initialize_rpc();
|
||||
initialize_rpc_handlers();
|
||||
|
||||
rpc::SCgi* scgi = new rpc::SCgi;
|
||||
|
||||
@@ -189,9 +164,9 @@ apply_xmlrpc_dialect(const std::string& arg) {
|
||||
|
||||
void
|
||||
initialize_command_network() {
|
||||
torrent::ConnectionManager* cm = torrent::connection_manager();
|
||||
torrent::FileManager* fileManager = torrent::file_manager();
|
||||
core::CurlStack* httpStack = control->core()->http_stack();
|
||||
auto cm = torrent::connection_manager();
|
||||
auto fileManager = torrent::file_manager();
|
||||
auto http_stack = torrent::net_thread::http_stack();
|
||||
|
||||
CMD2_ANY_STRING ("encoding.add", std::bind(&apply_encoding_list, std::placeholders::_2));
|
||||
|
||||
@@ -215,21 +190,21 @@ initialize_command_network() {
|
||||
CMD2_VAR_STRING ("protocol.choke_heuristics.down.leech", "download_leech");
|
||||
CMD2_VAR_STRING ("protocol.choke_heuristics.down.seed", "download_leech");
|
||||
|
||||
CMD2_ANY ("network.http.cacert", std::bind(&core::CurlStack::http_cacert, httpStack));
|
||||
CMD2_ANY_STRING_V("network.http.cacert.set", std::bind(&core::CurlStack::set_http_cacert, httpStack, std::placeholders::_2));
|
||||
CMD2_ANY ("network.http.capath", std::bind(&core::CurlStack::http_capath, httpStack));
|
||||
CMD2_ANY_STRING_V("network.http.capath.set", std::bind(&core::CurlStack::set_http_capath, httpStack, std::placeholders::_2));
|
||||
CMD2_ANY ("network.http.dns_cache_timeout", std::bind(&core::CurlStack::dns_timeout, httpStack));
|
||||
CMD2_ANY_VALUE_V ("network.http.dns_cache_timeout.set", std::bind(&core::CurlStack::set_dns_timeout, httpStack, std::placeholders::_2));
|
||||
CMD2_ANY ("network.http.current_open", std::bind(&core::CurlStack::active, httpStack));
|
||||
CMD2_ANY ("network.http.max_open", std::bind(&core::CurlStack::max_active, httpStack));
|
||||
CMD2_ANY_VALUE_V ("network.http.max_open.set", std::bind(&core::CurlStack::set_max_active, httpStack, std::placeholders::_2));
|
||||
CMD2_ANY ("network.http.proxy_address", std::bind(&core::CurlStack::http_proxy, httpStack));
|
||||
CMD2_ANY_STRING_V("network.http.proxy_address.set", std::bind(&core::CurlStack::set_http_proxy, httpStack, std::placeholders::_2));
|
||||
CMD2_ANY ("network.http.ssl_verify_host", std::bind(&core::CurlStack::ssl_verify_host, httpStack));
|
||||
CMD2_ANY_VALUE_V ("network.http.ssl_verify_host.set", std::bind(&core::CurlStack::set_ssl_verify_host, httpStack, std::placeholders::_2));
|
||||
CMD2_ANY ("network.http.ssl_verify_peer", std::bind(&core::CurlStack::ssl_verify_peer, httpStack));
|
||||
CMD2_ANY_VALUE_V ("network.http.ssl_verify_peer.set", std::bind(&core::CurlStack::set_ssl_verify_peer, httpStack, std::placeholders::_2));
|
||||
CMD2_ANY ("network.http.cacert", [http_stack](auto, auto) { return http_stack->http_cacert(); });
|
||||
CMD2_ANY_STRING_V("network.http.cacert.set", [http_stack](auto, auto& str) { return http_stack->set_http_cacert(str); });
|
||||
CMD2_ANY ("network.http.capath", [http_stack](auto, auto) { return http_stack->http_capath(); });
|
||||
CMD2_ANY_STRING_V("network.http.capath.set", [http_stack](auto, auto& str) { return http_stack->set_http_capath(str); });
|
||||
CMD2_ANY ("network.http.dns_cache_timeout", [http_stack](auto, auto) { return http_stack->dns_timeout(); });
|
||||
CMD2_ANY_VALUE_V ("network.http.dns_cache_timeout.set", [http_stack](auto, auto& value) { return http_stack->set_dns_timeout(value); });
|
||||
CMD2_ANY ("network.http.current_open", [http_stack](auto, auto) { return http_stack->active(); });
|
||||
CMD2_ANY ("network.http.max_open", [http_stack](auto, auto) { return http_stack->max_active(); });
|
||||
CMD2_ANY_VALUE_V ("network.http.max_open.set", [http_stack](auto, auto& value) { return http_stack->set_max_active(value); });
|
||||
CMD2_ANY ("network.http.proxy_address", [http_stack](auto, auto) { return http_stack->http_proxy(); });
|
||||
CMD2_ANY_STRING_V("network.http.proxy_address.set", [http_stack](auto, auto& str) { return http_stack->set_http_proxy(str); });
|
||||
CMD2_ANY ("network.http.ssl_verify_host", [http_stack](auto, auto) { return http_stack->ssl_verify_host(); });
|
||||
CMD2_ANY_VALUE_V ("network.http.ssl_verify_host.set", [http_stack](auto, auto& value) { return http_stack->set_ssl_verify_host(value); });
|
||||
CMD2_ANY ("network.http.ssl_verify_peer", [http_stack](auto, auto) { return http_stack->ssl_verify_peer(); });
|
||||
CMD2_ANY_VALUE_V ("network.http.ssl_verify_peer.set", [http_stack](auto, auto& value) { return http_stack->set_ssl_verify_peer(value); });
|
||||
|
||||
CMD2_ANY ("network.send_buffer.size", std::bind(&torrent::ConnectionManager::send_buffer_size, cm));
|
||||
CMD2_ANY_VALUE_V ("network.send_buffer.size.set", std::bind(&torrent::ConnectionManager::set_send_buffer_size, cm, std::placeholders::_2));
|
||||
@@ -267,6 +242,8 @@ initialize_command_network() {
|
||||
CMD2_ANY_VALUE_V ("network.block.ipv4.set", std::bind(&torrent::ConnectionManager::set_block_ipv4, cm, std::placeholders::_2));
|
||||
CMD2_ANY ("network.block.ipv6", std::bind(&torrent::ConnectionManager::is_block_ipv6, cm));
|
||||
CMD2_ANY_VALUE_V ("network.block.ipv6.set", std::bind(&torrent::ConnectionManager::set_block_ipv6, cm, std::placeholders::_2));
|
||||
CMD2_ANY ("network.block.ipv4in6", std::bind(&torrent::ConnectionManager::is_block_ipv4in6, cm));
|
||||
CMD2_ANY_VALUE_V ("network.block.ipv4in6.set", std::bind(&torrent::ConnectionManager::set_block_ipv4in6, cm, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY ("network.prefer.ipv6", std::bind(&torrent::ConnectionManager::is_prefer_ipv6, cm));
|
||||
CMD2_ANY_VALUE_V ("network.prefer.ipv6.set", std::bind(&torrent::ConnectionManager::set_prefer_ipv6, cm, std::placeholders::_2));
|
||||
|
||||
+2
-4
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
+21
-15
@@ -31,11 +31,11 @@ apply_dht_add_node(const std::string& arg) {
|
||||
if (!torrent::dht_controller()->is_valid())
|
||||
throw torrent::input_error("DHT not enabled.");
|
||||
|
||||
int port, ret;
|
||||
int port;
|
||||
char dummy;
|
||||
char host[1024];
|
||||
|
||||
ret = std::sscanf(arg.c_str(), "%1023[^:]:%i%c", host, &port, &dummy);
|
||||
int ret = std::sscanf(arg.c_str(), "%1023[^:]:%i%c", host, &port, &dummy);
|
||||
|
||||
if (ret == 1)
|
||||
port = 6881;
|
||||
@@ -47,13 +47,18 @@ apply_dht_add_node(const std::string& arg) {
|
||||
|
||||
assert(std::this_thread::get_id() == torrent::main_thread::thread()->thread_id());
|
||||
|
||||
auto host_str = std::string(host);
|
||||
|
||||
// TODO: Move this lookup to DhtController.
|
||||
|
||||
// Currently discarding SOCK_STREAM.
|
||||
torrent::this_thread::resolver()->resolve_specific(nullptr, host, PF_INET, [port](torrent::c_sa_shared_ptr sa, int err) {
|
||||
torrent::this_thread::resolver()->resolve_specific(nullptr, host_str, PF_INET, [host_str, port](torrent::c_sa_shared_ptr sa, int err) {
|
||||
if (sa == nullptr) {
|
||||
lt_log_print(torrent::LOG_DHT_WARN, "Could not resolve host: %s", gai_strerror(err));
|
||||
lt_log_print(torrent::LOG_DHT_ERROR, "dht.add_node : could not resolve host : %s (%s)", gai_strerror(err), host_str.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
lt_log_print(torrent::LOG_DHT_CONTROLLER, "dht.add_node : %s", host_str.c_str());
|
||||
torrent::dht_controller()->add_node(sa.get(), port);
|
||||
});
|
||||
|
||||
@@ -63,22 +68,22 @@ apply_dht_add_node(const std::string& arg) {
|
||||
torrent::Object
|
||||
apply_enable_trackers(int64_t arg) {
|
||||
if (arg == 0) {
|
||||
for (auto itr : *control->core()->download_list())
|
||||
itr->tracker_controller().for_each([](auto& tracker) { tracker.disable(); });
|
||||
for (auto download : *control->core()->download_list())
|
||||
download->tracker_controller().for_each([](auto& tracker) { tracker.disable(); });
|
||||
|
||||
} else if (rpc::call_command_value("trackers.use_udp") == 0) {
|
||||
for (auto itr : *control->core()->download_list()) {
|
||||
itr->tracker_controller().for_each([](auto& tracker) {
|
||||
if (tracker.type() == torrent::TRACKER_UDP)
|
||||
tracker.disable();
|
||||
else
|
||||
tracker.enable();
|
||||
});
|
||||
for (auto download : *control->core()->download_list()) {
|
||||
download->tracker_controller().for_each([](auto& tracker) {
|
||||
if (tracker.type() == torrent::TRACKER_UDP)
|
||||
tracker.disable();
|
||||
else
|
||||
tracker.enable();
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
for (auto itr : *control->core()->download_list())
|
||||
itr->tracker_controller().for_each([](auto& tracker) { tracker.enable(); });
|
||||
for (auto download : *control->core()->download_list())
|
||||
download->tracker_controller().for_each([](auto& tracker) { tracker.enable(); });
|
||||
}
|
||||
|
||||
return torrent::Object();
|
||||
@@ -138,6 +143,7 @@ initialize_command_tracker() {
|
||||
CMD2_VAR_BOOL ("trackers.use_udp", true);
|
||||
|
||||
CMD2_ANY_STRING_V ("dht.mode.set", std::bind(&core::DhtManager::set_mode, control->dht_manager(), std::placeholders::_2));
|
||||
// TODO: This should query DhtController.
|
||||
CMD2_VAR_VALUE ("dht.port", int64_t(6881));
|
||||
CMD2_ANY_STRING ("dht.add_node", std::bind(&apply_dht_add_node, std::placeholders::_2));
|
||||
CMD2_ANY ("dht.statistics", std::bind(&core::DhtManager::dht_statistics, control->dht_manager()));
|
||||
|
||||
+47
-41
@@ -75,8 +75,8 @@ apply_view_list() {
|
||||
torrent::Object rawResult = torrent::Object::create_list();
|
||||
torrent::Object::list_type& result = rawResult.as_list();
|
||||
|
||||
for (core::ViewManager::const_iterator itr = control->view_manager()->begin(), last = control->view_manager()->end(); itr != last; itr++)
|
||||
result.push_back((*itr)->name());
|
||||
for (auto itr : *control->view_manager())
|
||||
result.push_back(itr->name());
|
||||
|
||||
return rawResult;
|
||||
}
|
||||
@@ -193,18 +193,18 @@ apply_and(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
if (rawArgs.type() != torrent::Object::TYPE_LIST)
|
||||
return as_boolean(rawArgs);
|
||||
|
||||
for (torrent::Object::list_const_iterator itr = rawArgs.as_list().begin(), last = rawArgs.as_list().end(); itr != last; itr++)
|
||||
if (itr->is_dict_key()) {
|
||||
if (!as_boolean(rpc::commands.call_command(itr->as_dict_key().c_str(), itr->as_dict_obj(), target)))
|
||||
for (const auto& itr : rawArgs.as_list())
|
||||
if (itr.is_dict_key()) {
|
||||
if (!as_boolean(rpc::commands.call_command(itr.as_dict_key().c_str(), itr.as_dict_obj(), target)))
|
||||
return (int64_t)false;
|
||||
|
||||
} else if (itr->is_value()) {
|
||||
if (!itr->as_value())
|
||||
} else if (itr.is_value()) {
|
||||
if (!itr.as_value())
|
||||
return (int64_t)false;
|
||||
|
||||
} else {
|
||||
// TODO: Switch to new versions that only accept the new command syntax.
|
||||
if (!as_boolean(rpc::parse_command_single(target, itr->as_string())))
|
||||
if (!as_boolean(rpc::parse_command_single(target, itr.as_string())))
|
||||
return (int64_t)false;
|
||||
}
|
||||
|
||||
@@ -216,17 +216,17 @@ apply_or(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
if (rawArgs.type() != torrent::Object::TYPE_LIST)
|
||||
return as_boolean(rawArgs);
|
||||
|
||||
for (torrent::Object::list_const_iterator itr = rawArgs.as_list().begin(), last = rawArgs.as_list().end(); itr != last; itr++)
|
||||
if (itr->is_dict_key()) {
|
||||
if (as_boolean(rpc::commands.call_command(itr->as_dict_key().c_str(), itr->as_dict_obj(), target)))
|
||||
for (const auto& itr : rawArgs.as_list())
|
||||
if (itr.is_dict_key()) {
|
||||
if (as_boolean(rpc::commands.call_command(itr.as_dict_key().c_str(), itr.as_dict_obj(), target)))
|
||||
return (int64_t)true;
|
||||
|
||||
} else if (itr->is_value()) {
|
||||
if (itr->as_value())
|
||||
} else if (itr.is_value()) {
|
||||
if (itr.as_value())
|
||||
return (int64_t)true;
|
||||
|
||||
} else {
|
||||
if (as_boolean(rpc::parse_command_single(target, itr->as_string())))
|
||||
if (as_boolean(rpc::parse_command_single(target, itr.as_string())))
|
||||
return (int64_t)true;
|
||||
}
|
||||
|
||||
@@ -526,9 +526,9 @@ apply_if(rpc::target_type target, const torrent::Object& rawArgs, int flags) {
|
||||
// nice to have a parse_command function that takes list
|
||||
// iterator...
|
||||
|
||||
for (torrent::Object::list_type::const_iterator cmdItr = itr->as_list().begin(), last = itr->as_list().end(); cmdItr != last; cmdItr++)
|
||||
if (cmdItr->is_string())
|
||||
rpc::parse_command(target, cmdItr->as_string().c_str(), cmdItr->as_string().c_str() + cmdItr->as_string().size());
|
||||
for (const auto& cmdItr : itr->as_list())
|
||||
if (cmdItr.is_string())
|
||||
rpc::parse_command(target, cmdItr.as_string().c_str(), cmdItr.as_string().c_str() + cmdItr.as_string().size());
|
||||
|
||||
return torrent::Object();
|
||||
|
||||
@@ -630,26 +630,26 @@ as_vector(const torrent::Object::list_type& args) {
|
||||
|
||||
std::vector<int64_t> result;
|
||||
|
||||
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
|
||||
for (const auto& arg : args) {
|
||||
|
||||
if (itr->is_value()) {
|
||||
result.push_back(itr->as_value());
|
||||
} else if (itr->is_string()) {
|
||||
result.push_back(rpc::convert_to_value(itr->as_string()));
|
||||
} else if (itr->is_list()) {
|
||||
std::vector<int64_t> subResult = as_vector(itr->as_list());
|
||||
if (arg.is_value()) {
|
||||
result.push_back(arg.as_value());
|
||||
} else if (arg.is_string()) {
|
||||
result.push_back(rpc::convert_to_value(arg.as_string()));
|
||||
} else if (arg.is_list()) {
|
||||
std::vector<int64_t> subResult = as_vector(arg.as_list());
|
||||
result.insert(result.end(), subResult.begin(), subResult.end());
|
||||
} else {
|
||||
throw torrent::input_error("Wrong type supplied to as_vector.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Comp>
|
||||
int64_t
|
||||
apply_math_basic(const char* name, const std::function<int64_t(int64_t,int64_t)> op, const torrent::Object::list_type& args) {
|
||||
apply_math_basic(const char* name, Comp op, const torrent::Object::list_type& args) {
|
||||
int64_t val = 0, rhs = 0;
|
||||
bool divides = !strcmp(name, "math.div") || !strcmp(name, "math.mod");
|
||||
|
||||
@@ -678,8 +678,9 @@ apply_math_basic(const char* name, const std::function<int64_t(int64_t,int64_t)>
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename Comp>
|
||||
int64_t
|
||||
apply_arith_basic(const std::function<int64_t(int64_t,int64_t)> op, const torrent::Object::list_type& args) {
|
||||
apply_arith_basic(Comp op, const torrent::Object::list_type& args) {
|
||||
if (args.size() == 0)
|
||||
throw torrent::input_error("Wrong argument count in apply_arith_basic.");
|
||||
|
||||
@@ -711,20 +712,19 @@ apply_arith_count(const torrent::Object::list_type& args) {
|
||||
|
||||
int64_t val = 0;
|
||||
|
||||
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
|
||||
for (const auto& arg : args) {
|
||||
|
||||
switch (itr->type()) {
|
||||
switch (arg.type()) {
|
||||
case torrent::Object::TYPE_VALUE:
|
||||
case torrent::Object::TYPE_STRING:
|
||||
val++;
|
||||
break;
|
||||
case torrent::Object::TYPE_LIST:
|
||||
val += apply_arith_count(itr->as_list());
|
||||
val += apply_arith_count(arg.as_list());
|
||||
break;
|
||||
default:
|
||||
throw torrent::input_error("Wrong type supplied to apply_arith_count.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return val;
|
||||
@@ -752,9 +752,9 @@ cmd_status_throttle_names(bool up, const torrent::Object::list_type& args) {
|
||||
|
||||
std::vector<std::string> throttle_name_list;
|
||||
|
||||
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
|
||||
if (itr->is_string())
|
||||
throttle_name_list.push_back(itr->as_string());
|
||||
for (const auto& arg : args) {
|
||||
if (arg.is_string())
|
||||
throttle_name_list.push_back(arg.as_string());
|
||||
}
|
||||
|
||||
if (up)
|
||||
@@ -768,6 +768,7 @@ cmd_status_throttle_names(bool up, const torrent::Object::list_type& args) {
|
||||
torrent::Object
|
||||
apply_set_color(int color_id, const torrent::Object::string_type& color_str) {
|
||||
control->object_storage()->set_str_string(display::color_vars[color_id], color_str);
|
||||
|
||||
display::Canvas::build_colors();
|
||||
return torrent::Object();
|
||||
}
|
||||
@@ -824,6 +825,9 @@ initialize_command_ui() {
|
||||
CMD2_ANY_LIST ("ui.status.throttle.up.set", std::bind(&cmd_status_throttle_names, true, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("ui.status.throttle.down.set", std::bind(&cmd_status_throttle_names, false, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY ("ui.keymap.style", std::bind(&ui::Root::keymap_style, control->ui()));
|
||||
CMD2_ANY_STRING_V("ui.keymap.style.set", std::bind(&ui::Root::set_keymap_style, control->ui(), std::placeholders::_2));
|
||||
|
||||
// TODO: Add 'option_string' for rtorrent-specific options.
|
||||
CMD2_VAR_STRING("ui.torrent_list.layout", "full");
|
||||
|
||||
@@ -858,13 +862,13 @@ initialize_command_ui() {
|
||||
CMD2_ANY_VALUE("convert.xb", std::bind(&apply_to_xb, std::placeholders::_2));
|
||||
CMD2_ANY_VALUE("convert.throttle", std::bind(&apply_to_throttle, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY_LIST("math.add", std::bind(&apply_math_basic, "math.add", std::plus<int64_t>(), std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.sub", std::bind(&apply_math_basic, "math.sub", std::minus<int64_t>(), std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.mul", std::bind(&apply_math_basic, "math.mul", std::multiplies<int64_t>(), std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.div", std::bind(&apply_math_basic, "math.div", std::divides<int64_t>(), std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.mod", std::bind(&apply_math_basic, "math.mod", std::modulus<int64_t>(), std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.min", std::bind(&apply_arith_basic, std::less<int64_t>(), std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.max", std::bind(&apply_arith_basic, std::greater<int64_t>(), std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.add", [](auto, const auto& args) { return apply_math_basic("math.add", std::plus(), args); });
|
||||
CMD2_ANY_LIST("math.sub", [](auto, const auto& args) { return apply_math_basic("math.sub", std::minus(), args); });
|
||||
CMD2_ANY_LIST("math.mul", [](auto, const auto& args) { return apply_math_basic("math.mul", std::multiplies(), args); });
|
||||
CMD2_ANY_LIST("math.div", [](auto, const auto& args) { return apply_math_basic("math.div", std::divides(), args); });
|
||||
CMD2_ANY_LIST("math.mod", [](auto, const auto& args) { return apply_math_basic("math.mod", std::modulus(), args); });
|
||||
CMD2_ANY_LIST("math.min", [](auto, const auto& args) { return apply_arith_basic(std::less(), args); });
|
||||
CMD2_ANY_LIST("math.max", [](auto, const auto& args) { return apply_arith_basic(std::greater(), args); });
|
||||
CMD2_ANY_LIST("math.cnt", std::bind(&apply_arith_count, std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.avg", std::bind(&apply_arith_other, "average", std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.med", std::bind(&apply_arith_other, "median", std::placeholders::_2));
|
||||
@@ -875,9 +879,11 @@ initialize_command_ui() {
|
||||
// Build set/get methods for all color definitions
|
||||
for (int color_id = 1; color_id < display::RCOLOR_MAX; color_id++) {
|
||||
control->object_storage()->insert_str(display::color_vars[color_id], "", rpc::object_storage::flag_string_type);
|
||||
|
||||
CMD2_ANY_STRING(std::string(display::color_vars[color_id]) + ".set", [color_id](const auto&, const auto& arg) {
|
||||
return apply_set_color(color_id, arg);
|
||||
});
|
||||
|
||||
CMD2_ANY(display::color_vars[color_id], [color_id](const auto&, const auto&) {
|
||||
return control->object_storage()->get_str(display::color_vars[color_id]);
|
||||
});
|
||||
|
||||
+20
-28
@@ -1,11 +1,13 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "control.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <torrent/connection_manager.h>
|
||||
#include <torrent/net/http_stack.h>
|
||||
#include <torrent/utils/directory_events.h>
|
||||
|
||||
#include "core/curl_stack.h"
|
||||
#include "core/dht_manager.h"
|
||||
#include "core/download_store.h"
|
||||
#include "core/http_queue.h"
|
||||
@@ -26,10 +28,8 @@
|
||||
#include "rpc/object_storage.h"
|
||||
#include "ui/root.h"
|
||||
|
||||
#include "control.h"
|
||||
|
||||
Control::Control() :
|
||||
m_ui(new ui::Root()),
|
||||
Control::Control()
|
||||
: m_ui(new ui::Root()),
|
||||
m_display(new display::Manager()),
|
||||
m_input(new input::Manager()),
|
||||
m_inputStdin(new input::InputEvent(STDIN_FILENO)),
|
||||
@@ -38,11 +38,11 @@ Control::Control() :
|
||||
m_lua_engine(new rpc::LuaEngine()),
|
||||
m_directory_events(new torrent::directory_events()) {
|
||||
|
||||
m_core = new core::Manager();
|
||||
m_viewManager = new core::ViewManager();
|
||||
m_dhtManager = new core::DhtManager();
|
||||
m_core = std::make_unique<core::Manager>();
|
||||
m_viewManager = std::make_unique<core::ViewManager>();
|
||||
m_dhtManager = std::make_unique<core::DhtManager>();
|
||||
|
||||
m_inputStdin->slot_pressed(std::bind(&input::Manager::pressed, m_input, std::placeholders::_1));
|
||||
m_inputStdin->slot_pressed(std::bind(&input::Manager::pressed, m_input.get(), std::placeholders::_1));
|
||||
|
||||
m_task_shutdown.slot() = std::bind(&Control::handle_shutdown, this);
|
||||
|
||||
@@ -50,20 +50,10 @@ Control::Control() :
|
||||
}
|
||||
|
||||
Control::~Control() {
|
||||
delete m_inputStdin;
|
||||
delete m_input;
|
||||
m_viewManager.reset();
|
||||
|
||||
delete m_viewManager;
|
||||
|
||||
delete m_ui;
|
||||
delete m_display;
|
||||
delete m_core;
|
||||
delete m_dhtManager;
|
||||
|
||||
delete m_directory_events;
|
||||
delete m_commandScheduler;
|
||||
delete m_objectStorage;
|
||||
delete m_lua_engine;
|
||||
m_ui.reset();
|
||||
m_display.reset();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -73,19 +63,18 @@ Control::initialize() {
|
||||
display::Window::slot_unschedule([this](display::Window* w) { m_display->unschedule(w); });
|
||||
display::Window::slot_adjust([this]() { m_display->adjust_layout(); });
|
||||
|
||||
m_core->http_stack()->set_user_agent(USER_AGENT);
|
||||
torrent::net_thread::http_stack()->set_user_agent(USER_AGENT);
|
||||
|
||||
m_core->initialize_second();
|
||||
m_core->listen_open();
|
||||
m_core->download_store()->enable(rpc::call_command_value("session.use_lock"));
|
||||
|
||||
m_core->set_hashing_view(*m_viewManager->find_throw("hashing"));
|
||||
|
||||
m_dhtManager->set_port(torrent::connection_manager()->listen_port());
|
||||
|
||||
m_ui->init(this);
|
||||
|
||||
if(!display::Canvas::daemon()) {
|
||||
if(!display::Canvas::daemon())
|
||||
m_inputStdin->insert(torrent::this_thread::poll());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -122,7 +111,10 @@ Control::is_shutdown_completed() {
|
||||
// Tracker requests can be disowned, so wait for these to
|
||||
// finish. The edge case of torrent http downloads may delay
|
||||
// shutdown.
|
||||
if (!core()->http_stack()->empty() || !core()->http_queue()->empty())
|
||||
|
||||
// TODO: We keep http requests in the queue for a while after, so improve this check to ignore
|
||||
// those.
|
||||
if (torrent::net_thread::http_stack()->active() != 0 || !core()->http_queue()->empty())
|
||||
return false;
|
||||
|
||||
return torrent::is_inactive();
|
||||
|
||||
+23
-22
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <cinttypes>
|
||||
#include <memory>
|
||||
#include <sys/types.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/utils/scheduler.h>
|
||||
@@ -55,20 +56,20 @@ public:
|
||||
void receive_normal_shutdown() { m_shutdownReceived = true; }
|
||||
void receive_quick_shutdown() { m_shutdownReceived = true; m_shutdownQuick = true; }
|
||||
|
||||
core::Manager* core() { return m_core; }
|
||||
core::ViewManager* view_manager() { return m_viewManager; }
|
||||
core::DhtManager* dht_manager() { return m_dhtManager; }
|
||||
core::Manager* core() { return m_core.get(); }
|
||||
core::ViewManager* view_manager() { return m_viewManager.get(); }
|
||||
core::DhtManager* dht_manager() { return m_dhtManager.get(); }
|
||||
|
||||
ui::Root* ui() { return m_ui; }
|
||||
display::Manager* display() { return m_display; }
|
||||
input::Manager* input() { return m_input; }
|
||||
input::InputEvent* input_stdin() { return m_inputStdin; }
|
||||
ui::Root* ui() { return m_ui.get(); }
|
||||
display::Manager* display() { return m_display.get(); }
|
||||
input::Manager* input() { return m_input.get(); }
|
||||
input::InputEvent* input_stdin() { return m_inputStdin.get(); }
|
||||
|
||||
rpc::CommandScheduler* command_scheduler() { return m_commandScheduler; }
|
||||
rpc::object_storage* object_storage() { return m_objectStorage; }
|
||||
rpc::LuaEngine* lua_engine() { return m_lua_engine; }
|
||||
rpc::CommandScheduler* command_scheduler() { return m_commandScheduler.get(); }
|
||||
rpc::object_storage* object_storage() { return m_objectStorage.get(); }
|
||||
rpc::LuaEngine* lua_engine() { return m_lua_engine.get(); }
|
||||
|
||||
torrent::directory_events* directory_events() { return m_directory_events; }
|
||||
torrent::directory_events* directory_events() { return m_directory_events.get(); }
|
||||
|
||||
uint64_t tick() const { return m_tick; }
|
||||
void inc_tick() { m_tick++; }
|
||||
@@ -80,19 +81,19 @@ private:
|
||||
Control(const Control&);
|
||||
void operator = (const Control&);
|
||||
|
||||
core::Manager* m_core;
|
||||
core::ViewManager* m_viewManager;
|
||||
core::DhtManager* m_dhtManager;
|
||||
std::unique_ptr<core::Manager> m_core;
|
||||
std::unique_ptr<core::ViewManager> m_viewManager;
|
||||
std::unique_ptr<core::DhtManager> m_dhtManager;
|
||||
|
||||
ui::Root* m_ui;
|
||||
display::Manager* m_display;
|
||||
input::Manager* m_input;
|
||||
input::InputEvent* m_inputStdin;
|
||||
std::unique_ptr<ui::Root> m_ui;
|
||||
std::unique_ptr<display::Manager> m_display;
|
||||
std::unique_ptr<input::Manager> m_input;
|
||||
std::unique_ptr<input::InputEvent> m_inputStdin;
|
||||
|
||||
rpc::CommandScheduler* m_commandScheduler;
|
||||
rpc::object_storage* m_objectStorage;
|
||||
rpc::LuaEngine* m_lua_engine;
|
||||
torrent::directory_events* m_directory_events;
|
||||
std::unique_ptr<rpc::CommandScheduler> m_commandScheduler;
|
||||
std::unique_ptr<rpc::object_storage> m_objectStorage;
|
||||
std::unique_ptr<rpc::LuaEngine> m_lua_engine;
|
||||
std::unique_ptr<torrent::directory_events> m_directory_events;
|
||||
|
||||
uint64_t m_tick{};
|
||||
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "core/curl_get.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <curl/curl.h>
|
||||
#include <curl/easy.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "core/curl_stack.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
size_t
|
||||
curl_get_receive_write(void* data, size_t size, size_t nmemb, void* handle) {
|
||||
if (!((CurlGet*)handle)->stream()->write((const char*)data, size * nmemb).fail())
|
||||
return size * nmemb;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
CurlGet::CurlGet(CurlStack* s) :
|
||||
m_stack(s) {
|
||||
|
||||
m_task_timeout.slot() = [this]() { receive_timeout(); };
|
||||
}
|
||||
|
||||
CurlGet::~CurlGet() {
|
||||
close();
|
||||
}
|
||||
|
||||
void
|
||||
CurlGet::start() {
|
||||
if (is_busy())
|
||||
throw torrent::internal_error("Tried to call CurlGet::start on a busy object.");
|
||||
|
||||
if (m_stream == NULL)
|
||||
throw torrent::internal_error("Tried to call CurlGet::start without a valid output stream.");
|
||||
|
||||
if (!m_stack->is_running())
|
||||
return;
|
||||
|
||||
m_handle = curl_easy_init();
|
||||
|
||||
if (m_handle == NULL)
|
||||
throw torrent::internal_error("Call to curl_easy_init() failed.");
|
||||
|
||||
curl_easy_setopt(m_handle, CURLOPT_URL, m_url.c_str());
|
||||
curl_easy_setopt(m_handle, CURLOPT_WRITEFUNCTION, &curl_get_receive_write);
|
||||
curl_easy_setopt(m_handle, CURLOPT_WRITEDATA, this);
|
||||
|
||||
if (m_timeout != 0) {
|
||||
curl_easy_setopt(m_handle, CURLOPT_CONNECTTIMEOUT, (long)60);
|
||||
curl_easy_setopt(m_handle, CURLOPT_TIMEOUT, (long)m_timeout);
|
||||
|
||||
// Normally libcurl should handle the timeout. But sometimes that doesn't
|
||||
// work right so we do a fallback timeout that just aborts the transfer.
|
||||
torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&m_task_timeout, 5s + 1s*m_timeout);
|
||||
}
|
||||
|
||||
curl_easy_setopt(m_handle, CURLOPT_FORBID_REUSE, (long)1);
|
||||
curl_easy_setopt(m_handle, CURLOPT_NOSIGNAL, (long)1);
|
||||
curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, (long)1);
|
||||
curl_easy_setopt(m_handle, CURLOPT_MAXREDIRS, (long)5);
|
||||
|
||||
curl_easy_setopt(m_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER);
|
||||
|
||||
curl_easy_setopt(m_handle, CURLOPT_ENCODING, "");
|
||||
|
||||
m_ipv6 = false;
|
||||
|
||||
m_stack->add_get(this);
|
||||
}
|
||||
|
||||
void
|
||||
CurlGet::close() {
|
||||
torrent::this_thread::scheduler()->erase(&m_task_timeout);
|
||||
|
||||
if (!is_busy())
|
||||
return;
|
||||
|
||||
m_stack->remove_get(this);
|
||||
|
||||
curl_easy_cleanup(m_handle);
|
||||
|
||||
m_handle = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
CurlGet::retry_ipv6() {
|
||||
CURL* nhandle = curl_easy_duphandle(m_handle);
|
||||
|
||||
curl_easy_setopt(nhandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
|
||||
curl_easy_cleanup(m_handle);
|
||||
|
||||
m_handle = nhandle;
|
||||
m_ipv6 = true;
|
||||
}
|
||||
|
||||
void
|
||||
CurlGet::receive_timeout() {
|
||||
return m_stack->transfer_done(m_handle, "Timed out");
|
||||
}
|
||||
|
||||
curl_off_t
|
||||
CurlGet::size_done() {
|
||||
curl_off_t d = 0;
|
||||
curl_easy_getinfo(m_handle, CURLINFO_SIZE_DOWNLOAD_T, &d);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
curl_off_t
|
||||
CurlGet::size_total() {
|
||||
curl_off_t d = 0;
|
||||
curl_easy_getinfo(m_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &d);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
#ifndef RTORRENT_CORE_CURL_GET_H
|
||||
#define RTORRENT_CORE_CURL_GET_H
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <curl/curl.h>
|
||||
#include <torrent/http.h>
|
||||
#include <torrent/utils/scheduler.h>
|
||||
|
||||
namespace core {
|
||||
|
||||
class CurlStack;
|
||||
|
||||
class CurlGet : public torrent::Http {
|
||||
public:
|
||||
CurlGet(CurlStack* s);
|
||||
virtual ~CurlGet();
|
||||
|
||||
void start();
|
||||
void close();
|
||||
|
||||
bool is_using_ipv6() { return m_ipv6; }
|
||||
void retry_ipv6();
|
||||
|
||||
bool is_busy() const { return m_handle; }
|
||||
bool is_active() const { return m_active; }
|
||||
|
||||
void set_active(bool a) { m_active = a; }
|
||||
|
||||
curl_off_t size_done();
|
||||
curl_off_t size_total();
|
||||
|
||||
CURL* handle() { return m_handle; }
|
||||
|
||||
private:
|
||||
friend class CurlStack;
|
||||
|
||||
CurlGet(const CurlGet&) = delete;
|
||||
void operator = (const CurlGet&) = delete;
|
||||
|
||||
void receive_timeout();
|
||||
|
||||
bool m_active{};
|
||||
bool m_ipv6;
|
||||
|
||||
torrent::utils::SchedulerEntry m_task_timeout;
|
||||
|
||||
CURL* m_handle{};
|
||||
CurlStack* m_stack;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,99 +0,0 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "curl_socket.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <curl/multi.h>
|
||||
#include <torrent/poll.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/utils/thread.h>
|
||||
|
||||
#include "control.h"
|
||||
#include "core/curl_stack.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
int
|
||||
CurlSocket::receive_socket([[maybe_unused]] void* easy_handle, curl_socket_t fd, int what, void* userp, void* socketp) {
|
||||
CurlStack* stack = (CurlStack*)userp;
|
||||
CurlSocket* socket = (CurlSocket*)socketp;
|
||||
|
||||
if (!stack->is_running())
|
||||
return 0;
|
||||
|
||||
if (what == CURL_POLL_REMOVE) {
|
||||
// We also probably need the special code here as we're not
|
||||
// guaranteed that the fd will be closed, afaik.
|
||||
if (socket != NULL)
|
||||
socket->close();
|
||||
|
||||
// TODO: Consider the possibility that we'll need to set the
|
||||
// fd-associated pointer curl holds to NULL.
|
||||
|
||||
delete socket;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (socket == NULL) {
|
||||
socket = stack->new_socket(fd);
|
||||
torrent::this_thread::poll()->open(socket);
|
||||
|
||||
// No interface for libcurl to signal when it's interested in error events.
|
||||
// Assume that hence it must always be interested in them.
|
||||
torrent::this_thread::poll()->insert_error(socket);
|
||||
}
|
||||
|
||||
if (what == CURL_POLL_NONE || what == CURL_POLL_OUT)
|
||||
torrent::this_thread::poll()->remove_read(socket);
|
||||
else
|
||||
torrent::this_thread::poll()->insert_read(socket);
|
||||
|
||||
if (what == CURL_POLL_NONE || what == CURL_POLL_IN)
|
||||
torrent::this_thread::poll()->remove_write(socket);
|
||||
else
|
||||
torrent::this_thread::poll()->insert_write(socket);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CurlSocket::~CurlSocket() {
|
||||
assert(m_fileDesc == -1 && "CurlSocket::~CurlSocket() m_fileDesc != -1.");
|
||||
}
|
||||
|
||||
void
|
||||
CurlSocket::close() {
|
||||
if (m_fileDesc == -1)
|
||||
throw torrent::internal_error("CurlSocket::close() m_fileDesc == -1.");
|
||||
|
||||
torrent::this_thread::poll()->closed(this);
|
||||
m_fileDesc = -1;
|
||||
}
|
||||
|
||||
void
|
||||
CurlSocket::event_read() {
|
||||
#if (LIBCURL_VERSION_NUM >= 0x071003)
|
||||
return m_stack->receive_action(this, CURL_CSELECT_IN);
|
||||
#else
|
||||
return m_stack->receive_action(this, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
CurlSocket::event_write() {
|
||||
#if (LIBCURL_VERSION_NUM >= 0x071003)
|
||||
return m_stack->receive_action(this, CURL_CSELECT_OUT);
|
||||
#else
|
||||
return m_stack->receive_action(this, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
CurlSocket::event_error() {
|
||||
#if (LIBCURL_VERSION_NUM >= 0x071003)
|
||||
return m_stack->receive_action(this, CURL_CSELECT_ERR);
|
||||
#else
|
||||
return m_stack->receive_action(this, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
#ifndef RTORRENT_CORE_CURL_SOCKET_H
|
||||
#define RTORRENT_CORE_CURL_SOCKET_H
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <torrent/event.h>
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
class CurlStack;
|
||||
|
||||
class CurlSocket : public torrent::Event {
|
||||
public:
|
||||
CurlSocket(int fd, CurlStack* stack) : m_stack(stack) { m_fileDesc = fd; }
|
||||
~CurlSocket();
|
||||
|
||||
const char* type_name() const { return "curl"; }
|
||||
|
||||
void close();
|
||||
|
||||
static int receive_socket(void* easy_handle, curl_socket_t fd, int what, void* userp, void* socketp);
|
||||
|
||||
private:
|
||||
CurlSocket(const CurlSocket&);
|
||||
void operator = (const CurlSocket&);
|
||||
|
||||
virtual void event_read();
|
||||
virtual void event_write();
|
||||
virtual void event_error();
|
||||
|
||||
CurlStack* m_stack;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,243 +0,0 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <curl/multi.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "curl_get.h"
|
||||
#include "curl_socket.h"
|
||||
#include "curl_stack.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
CurlStack::CurlStack() {
|
||||
m_handle = (void*)curl_multi_init();
|
||||
m_task_timeout.slot() = std::bind(&CurlStack::receive_timeout, this);
|
||||
|
||||
#if (LIBCURL_VERSION_NUM >= 0x071000)
|
||||
curl_multi_setopt((CURLM*)m_handle, CURLMOPT_TIMERDATA, this);
|
||||
curl_multi_setopt((CURLM*)m_handle, CURLMOPT_TIMERFUNCTION, &CurlStack::set_timeout);
|
||||
#endif
|
||||
curl_multi_setopt((CURLM*)m_handle, CURLMOPT_SOCKETDATA, this);
|
||||
curl_multi_setopt((CURLM*)m_handle, CURLMOPT_SOCKETFUNCTION, &CurlSocket::receive_socket);
|
||||
}
|
||||
|
||||
CurlStack::~CurlStack() {
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
CurlStack::shutdown() {
|
||||
if (!m_running)
|
||||
return;
|
||||
|
||||
m_running = false;
|
||||
|
||||
while (!empty())
|
||||
front()->close();
|
||||
|
||||
curl_multi_cleanup((CURLM*)m_handle);
|
||||
|
||||
torrent::this_thread::scheduler()->erase(&m_task_timeout);
|
||||
}
|
||||
|
||||
CurlGet*
|
||||
CurlStack::new_object() {
|
||||
return new CurlGet(this);
|
||||
}
|
||||
|
||||
CurlSocket*
|
||||
CurlStack::new_socket(int fd) {
|
||||
if (!m_running)
|
||||
throw torrent::internal_error("CurlStack::new_socket() called when not running.");
|
||||
|
||||
CurlSocket* socket = new CurlSocket(fd, this);
|
||||
curl_multi_assign((CURLM*)m_handle, fd, socket);
|
||||
return socket;
|
||||
}
|
||||
|
||||
void
|
||||
CurlStack::receive_action(CurlSocket* socket, int events) {
|
||||
CURLMcode code;
|
||||
|
||||
do {
|
||||
int count;
|
||||
#if (LIBCURL_VERSION_NUM >= 0x071003)
|
||||
code = curl_multi_socket_action((CURLM*)m_handle,
|
||||
socket != NULL ? socket->file_descriptor() : CURL_SOCKET_TIMEOUT,
|
||||
events,
|
||||
&count);
|
||||
#else
|
||||
code = curl_multi_socket((CURLM*)m_handle,
|
||||
socket != NULL ? socket->file_descriptor() : CURL_SOCKET_TIMEOUT,
|
||||
&count);
|
||||
#endif
|
||||
|
||||
if (code > 0)
|
||||
throw torrent::internal_error("Error calling curl_multi_socket_action.");
|
||||
|
||||
// Socket might be removed when cleaning handles below, future
|
||||
// calls should not use it.
|
||||
socket = NULL;
|
||||
events = 0;
|
||||
|
||||
if ((unsigned int)count != size()) {
|
||||
while (process_done_handle())
|
||||
; // Do nothing.
|
||||
|
||||
if (empty())
|
||||
torrent::this_thread::scheduler()->erase(&m_task_timeout);
|
||||
}
|
||||
|
||||
} while (code == CURLM_CALL_MULTI_PERFORM);
|
||||
}
|
||||
|
||||
bool
|
||||
CurlStack::process_done_handle() {
|
||||
int remaining_msgs = 0;
|
||||
CURLMsg* msg = curl_multi_info_read((CURLM*)m_handle, &remaining_msgs);
|
||||
|
||||
if (msg == NULL)
|
||||
return false;
|
||||
|
||||
if (msg->msg != CURLMSG_DONE)
|
||||
throw torrent::internal_error("CurlStack::receive_action() msg->msg != CURLMSG_DONE.");
|
||||
|
||||
if (msg->data.result == CURLE_COULDNT_RESOLVE_HOST) {
|
||||
iterator itr = std::find_if(begin(), end(), [&msg](CurlGet* get) { return get->handle() == msg->easy_handle; });
|
||||
|
||||
if (itr == end())
|
||||
throw torrent::internal_error("Could not find CurlGet when calling CurlStack::receive_action.");
|
||||
|
||||
if (!(*itr)->is_using_ipv6()) {
|
||||
(*itr)->retry_ipv6();
|
||||
|
||||
if (curl_multi_add_handle((CURLM*)m_handle, (*itr)->handle()) > 0)
|
||||
throw torrent::internal_error("Error calling curl_multi_add_handle.");
|
||||
}
|
||||
|
||||
} else {
|
||||
transfer_done(msg->easy_handle,
|
||||
msg->data.result == CURLE_OK ? NULL : curl_easy_strerror(msg->data.result));
|
||||
}
|
||||
|
||||
return remaining_msgs != 0;
|
||||
}
|
||||
|
||||
void
|
||||
CurlStack::transfer_done(void* handle, const char* msg) {
|
||||
iterator itr = std::find_if(begin(), end(), [&handle](CurlGet* get) { return get->handle() == handle; });
|
||||
|
||||
if (itr == end())
|
||||
throw torrent::internal_error("Could not find CurlGet with the right easy_handle.");
|
||||
|
||||
if (msg == NULL)
|
||||
(*itr)->trigger_done();
|
||||
else
|
||||
(*itr)->trigger_failed(msg);
|
||||
}
|
||||
|
||||
void
|
||||
CurlStack::receive_timeout() {
|
||||
receive_action(NULL, 0);
|
||||
|
||||
if (!empty() && !m_task_timeout.is_scheduled()) {
|
||||
// Sometimes libcurl forgets to reset the timeout. Try to poll the value in that case, or use 10
|
||||
// seconds max.
|
||||
long timeout_ms;
|
||||
curl_multi_timeout((CURLM*)m_handle, &timeout_ms);
|
||||
|
||||
auto timeout = std::max<std::chrono::microseconds>(std::chrono::milliseconds(timeout_ms), 10s);
|
||||
|
||||
torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_task_timeout, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CurlStack::add_get(CurlGet* get) {
|
||||
if (!m_user_agent.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_USERAGENT, m_user_agent.c_str());
|
||||
|
||||
if (!m_http_proxy.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_PROXY, m_http_proxy.c_str());
|
||||
|
||||
if (!m_bind_address.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_INTERFACE, m_bind_address.c_str());
|
||||
|
||||
if (!m_http_ca_path.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_CAPATH, m_http_ca_path.c_str());
|
||||
|
||||
if (!m_http_ca_cert.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_CAINFO, m_http_ca_cert.c_str());
|
||||
|
||||
curl_easy_setopt(get->handle(), CURLOPT_SSL_VERIFYHOST, (long)(m_ssl_verify_host ? 2 : 0));
|
||||
curl_easy_setopt(get->handle(), CURLOPT_SSL_VERIFYPEER, (long)(m_ssl_verify_peer ? 1 : 0));
|
||||
curl_easy_setopt(get->handle(), CURLOPT_DNS_CACHE_TIMEOUT, m_dns_timeout);
|
||||
|
||||
base_type::push_back(get);
|
||||
|
||||
if (m_active >= m_max_active)
|
||||
return;
|
||||
|
||||
m_active++;
|
||||
get->set_active(true);
|
||||
|
||||
if (curl_multi_add_handle((CURLM*)m_handle, get->handle()) > 0)
|
||||
throw torrent::internal_error("Error calling curl_multi_add_handle.");
|
||||
|
||||
#if (LIBCURL_VERSION_NUM < 0x071000)
|
||||
receive_timeout();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
CurlStack::remove_get(CurlGet* get) {
|
||||
iterator itr = std::find(begin(), end(), get);
|
||||
|
||||
if (itr == end())
|
||||
throw torrent::internal_error("Could not find CurlGet when calling CurlStack::remove.");
|
||||
|
||||
base_type::erase(itr);
|
||||
|
||||
// The CurlGet object was never activated, so we just skip this one.
|
||||
if (!get->is_active())
|
||||
return;
|
||||
|
||||
get->set_active(false);
|
||||
|
||||
if (curl_multi_remove_handle((CURLM*)m_handle, get->handle()) > 0)
|
||||
throw torrent::internal_error("Error calling curl_multi_remove_handle.");
|
||||
|
||||
if (m_active == m_max_active &&
|
||||
(itr = std::find_if(begin(), end(), [](CurlGet* get) { return !get->is_active(); })) != end()) {
|
||||
(*itr)->set_active(true);
|
||||
|
||||
if (curl_multi_add_handle((CURLM*)m_handle, (*itr)->handle()) > 0)
|
||||
throw torrent::internal_error("Error calling curl_multi_add_handle.");
|
||||
|
||||
} else {
|
||||
m_active--;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CurlStack::global_init() {
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
}
|
||||
|
||||
void
|
||||
CurlStack::global_cleanup() {
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
||||
// TODO: Is this function supposed to set a per-handle timeout, or is
|
||||
// it the shortest timeout amongst all handles?
|
||||
int
|
||||
CurlStack::set_timeout([[maybe_unused]] void* handle, std::chrono::microseconds timeout, void* userp) {
|
||||
CurlStack* stack = (CurlStack*)userp;
|
||||
|
||||
torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&stack->m_task_timeout, timeout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
#ifndef RTORRENT_CORE_CURL_STACK_H
|
||||
#define RTORRENT_CORE_CURL_STACK_H
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <torrent/utils/scheduler.h>
|
||||
|
||||
namespace core {
|
||||
|
||||
class CurlGet;
|
||||
class CurlSocket;
|
||||
|
||||
// By using a deque instead of vector we allow for cheaper removal of
|
||||
// the oldest elements, those that will be first in the in the
|
||||
// deque.
|
||||
//
|
||||
// This should fit well with the use-case of a http stack, thus
|
||||
// we get most of the cache locality benefits of a vector with fast
|
||||
// removal of elements.
|
||||
|
||||
class CurlStack : std::deque<CurlGet*> {
|
||||
public:
|
||||
friend class CurlGet;
|
||||
|
||||
typedef std::deque<CurlGet*> base_type;
|
||||
|
||||
using base_type::value_type;
|
||||
using base_type::iterator;
|
||||
using base_type::const_iterator;
|
||||
using base_type::reverse_iterator;
|
||||
using base_type::const_reverse_iterator;
|
||||
|
||||
using base_type::begin;
|
||||
using base_type::end;
|
||||
using base_type::rbegin;
|
||||
using base_type::rend;
|
||||
|
||||
using base_type::back;
|
||||
using base_type::front;
|
||||
|
||||
using base_type::size;
|
||||
using base_type::empty;
|
||||
|
||||
CurlStack();
|
||||
~CurlStack();
|
||||
|
||||
void shutdown();
|
||||
bool is_running() const { return m_running; }
|
||||
|
||||
CurlGet* new_object();
|
||||
CurlSocket* new_socket(int fd);
|
||||
|
||||
unsigned int active() const { return m_active; }
|
||||
unsigned int max_active() const { return m_max_active; }
|
||||
void set_max_active(unsigned int a) { m_max_active = a; }
|
||||
|
||||
const std::string& user_agent() const { return m_user_agent; }
|
||||
const std::string& http_proxy() const { return m_http_proxy; }
|
||||
const std::string& bind_address() const { return m_bind_address; }
|
||||
const std::string& http_capath() const { return m_http_ca_path; }
|
||||
const std::string& http_cacert() const { return m_http_ca_cert; }
|
||||
|
||||
void set_user_agent(const std::string& s) { m_user_agent = s; }
|
||||
void set_http_proxy(const std::string& s) { m_http_proxy = s; }
|
||||
void set_bind_address(const std::string& s) { m_bind_address = s; }
|
||||
void set_http_capath(const std::string& s) { m_http_ca_path = s; }
|
||||
void set_http_cacert(const std::string& s) { m_http_ca_cert = s; }
|
||||
|
||||
bool ssl_verify_host() const { return m_ssl_verify_host; }
|
||||
bool ssl_verify_peer() const { return m_ssl_verify_peer; }
|
||||
void set_ssl_verify_host(bool s) { m_ssl_verify_host = s; }
|
||||
void set_ssl_verify_peer(bool s) { m_ssl_verify_peer = s; }
|
||||
|
||||
long dns_timeout() const { return m_dns_timeout; }
|
||||
void set_dns_timeout(long timeout) { m_dns_timeout = timeout; }
|
||||
|
||||
static void global_init();
|
||||
static void global_cleanup();
|
||||
|
||||
void receive_action(CurlSocket* socket, int type);
|
||||
|
||||
static int set_timeout(void* handle, std::chrono::microseconds timeout, void* userp);
|
||||
|
||||
void transfer_done(void* handle, const char* msg);
|
||||
|
||||
protected:
|
||||
void add_get(CurlGet* get);
|
||||
void remove_get(CurlGet* get);
|
||||
|
||||
private:
|
||||
CurlStack(const CurlStack&) = delete;
|
||||
void operator = (const CurlStack&) = delete;
|
||||
|
||||
void receive_timeout();
|
||||
|
||||
bool process_done_handle();
|
||||
|
||||
void* m_handle;
|
||||
|
||||
bool m_running{true};
|
||||
|
||||
unsigned int m_active{0};
|
||||
unsigned int m_max_active{32};
|
||||
|
||||
torrent::utils::SchedulerEntry m_task_timeout;
|
||||
|
||||
std::string m_user_agent;
|
||||
std::string m_http_proxy;
|
||||
std::string m_bind_address;
|
||||
std::string m_http_ca_path;
|
||||
std::string m_http_ca_cert;
|
||||
|
||||
bool m_ssl_verify_host{true};
|
||||
bool m_ssl_verify_peer{true};
|
||||
long m_dns_timeout{60};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+30
-15
@@ -18,8 +18,11 @@
|
||||
#include "download_store.h"
|
||||
#include "manager.h"
|
||||
|
||||
#define LT_LOG_THIS(log_fmt, ...) \
|
||||
lt_log_print_subsystem(torrent::LOG_DHT_MANAGER, "dht_manager", log_fmt, __VA_ARGS__);
|
||||
#define LT_LOG(log_fmt, ...) \
|
||||
lt_log_print_subsystem(torrent::LOG_DHT_CONTROLLER, "dht_manager", log_fmt, __VA_ARGS__);
|
||||
|
||||
#define LT_LOG_ERROR(log_fmt, ...) \
|
||||
lt_log_print_subsystem(torrent::LOG_DHT_ERROR, "dht_manager", log_fmt, __VA_ARGS__);
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -30,10 +33,20 @@ DhtManager::~DhtManager() {
|
||||
torrent::this_thread::scheduler()->erase(&m_stop_timeout);
|
||||
}
|
||||
|
||||
void
|
||||
DhtManager::set_port(uint16_t port) {
|
||||
if (torrent::dht_controller()->is_active()) {
|
||||
LT_LOG_ERROR("cannot change port while DHT is active", 0);
|
||||
throw torrent::input_error("cannot change port while DHT is active");
|
||||
}
|
||||
|
||||
m_port = port;
|
||||
}
|
||||
|
||||
void
|
||||
DhtManager::load_dht_cache() {
|
||||
if (m_start == dht_disable || !control->core()->download_store()->is_enabled()) {
|
||||
LT_LOG_THIS("ignoring cache file", 0);
|
||||
LT_LOG("ignoring cache file", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -48,14 +61,14 @@ DhtManager::load_dht_cache() {
|
||||
// If the cache file is corrupted we will just discard it with an
|
||||
// error message.
|
||||
if (cache_stream.fail()) {
|
||||
LT_LOG_THIS("cache file corrupted, discarding (path:%s)", cache_filename.c_str());
|
||||
LT_LOG_ERROR("cache file corrupted, discarding (path:%s)", cache_filename.c_str());
|
||||
cache = torrent::Object::create_map();
|
||||
} else {
|
||||
LT_LOG_THIS("cache file read (path:%s)", cache_filename.c_str());
|
||||
LT_LOG("cache file read (path:%s)", cache_filename.c_str());
|
||||
}
|
||||
|
||||
} else {
|
||||
LT_LOG_THIS("could not open cache file (path:%s)", cache_filename.c_str());
|
||||
LT_LOG("could not open cache file (path:%s)", cache_filename.c_str());
|
||||
}
|
||||
|
||||
torrent::dht_controller()->initialize(cache);
|
||||
@@ -69,12 +82,12 @@ DhtManager::start_dht() {
|
||||
torrent::this_thread::scheduler()->erase(&m_stop_timeout);
|
||||
|
||||
if (!torrent::dht_controller()->is_valid()) {
|
||||
LT_LOG_THIS("server start skipped, manager is uninitialized", 0);
|
||||
LT_LOG("server start skipped, manager is uninitialized", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (torrent::dht_controller()->is_active()) {
|
||||
LT_LOG_THIS("server start skipped, already active", 0);
|
||||
LT_LOG("server start skipped, already active", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -82,12 +95,14 @@ DhtManager::start_dht() {
|
||||
torrent::dht_controller()->set_upload_throttle(throttles.first);
|
||||
torrent::dht_controller()->set_download_throttle(throttles.second);
|
||||
|
||||
int port = rpc::call_command_value("dht.port");
|
||||
|
||||
if (port <= 0)
|
||||
if (m_port <= 0) {
|
||||
LT_LOG("server start skipped, port not set", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!torrent::dht_controller()->start(port)) {
|
||||
LT_LOG("starting server : port=%" PRIu16, m_port);
|
||||
|
||||
if (!torrent::dht_controller()->start(m_port)) {
|
||||
m_start = dht_off;
|
||||
return;
|
||||
}
|
||||
@@ -112,7 +127,7 @@ DhtManager::stop_dht() {
|
||||
torrent::this_thread::scheduler()->erase(&m_stop_timeout);
|
||||
|
||||
if (torrent::dht_controller()->is_active()) {
|
||||
LT_LOG_THIS("stopping server", 0);
|
||||
LT_LOG("stopping server", 0);
|
||||
|
||||
log_statistics(true);
|
||||
torrent::dht_controller()->stop();
|
||||
@@ -196,7 +211,7 @@ DhtManager::log_statistics(bool force) {
|
||||
// We should have had clients ping us at least but have received
|
||||
// nothing, that means the UDP port is probably unreachable.
|
||||
if (torrent::dht_controller()->is_receiving_requests())
|
||||
LT_LOG_THIS("listening port appears to be unreachable, no queries received", 0);
|
||||
LT_LOG("listening port appears to be unreachable, no queries received", 0);
|
||||
|
||||
torrent::dht_controller()->set_receive_requests(false);
|
||||
}
|
||||
@@ -204,7 +219,7 @@ DhtManager::log_statistics(bool force) {
|
||||
if (stats.queries_sent - m_dhtPrevQueriesSent > stats.num_nodes * 2 + 20 && stats.replies_received == m_dhtPrevRepliesReceived) {
|
||||
// No replies to over 20 queries plus two per node we have. Probably firewalled.
|
||||
if (!m_warned)
|
||||
LT_LOG_THIS("listening port appears to be firewalled, no replies received", 0);
|
||||
LT_LOG("listening port appears to be firewalled, no replies received", 0);
|
||||
|
||||
m_warned = true;
|
||||
return false;
|
||||
|
||||
@@ -10,6 +10,9 @@ class DhtManager {
|
||||
public:
|
||||
~DhtManager();
|
||||
|
||||
uint16_t port() const { return m_port; }
|
||||
void set_port(uint16_t port);
|
||||
|
||||
void load_dht_cache();
|
||||
void save_dht_cache();
|
||||
torrent::Object dht_statistics();
|
||||
@@ -48,6 +51,8 @@ private:
|
||||
bool m_warned{};
|
||||
|
||||
int m_start{dht_off};
|
||||
uint16_t m_port{0};
|
||||
|
||||
std::string m_throttleName;
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
#include <torrent/data/file.h>
|
||||
#include <torrent/data/file_list.h>
|
||||
|
||||
#include "rpc/parse_commands.h"
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "download_factory.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <rak/path.h>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <torrent/utils/resume.h>
|
||||
@@ -14,18 +15,15 @@
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/data/file_utils.h>
|
||||
#include <torrent/net/http_stack.h>
|
||||
|
||||
#include "rpc/parse_commands.h"
|
||||
|
||||
#include "curl_get.h"
|
||||
#include "control.h"
|
||||
#include "http_queue.h"
|
||||
#include "globals.h"
|
||||
#include "manager.h"
|
||||
|
||||
#include "download.h"
|
||||
#include "download_factory.h"
|
||||
#include "download_store.h"
|
||||
#include "core/download.h"
|
||||
#include "core/download_store.h"
|
||||
#include "core/http_queue.h"
|
||||
#include "core/manager.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -77,9 +75,7 @@ DownloadFactory::~DownloadFactory() {
|
||||
torrent::this_thread::scheduler()->erase(&m_task_load);
|
||||
torrent::this_thread::scheduler()->erase(&m_task_commit);
|
||||
|
||||
delete m_stream;
|
||||
delete m_object;
|
||||
m_stream = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -94,7 +90,7 @@ DownloadFactory::load_raw_data(const std::string& input) {
|
||||
if (m_stream)
|
||||
throw torrent::internal_error("DownloadFactory::load*() called on an object with m_stream != NULL");
|
||||
|
||||
m_stream = new std::stringstream(input);
|
||||
m_stream.reset(new std::stringstream(input));
|
||||
m_loaded = true;
|
||||
}
|
||||
|
||||
@@ -110,17 +106,18 @@ DownloadFactory::receive_load() {
|
||||
|
||||
if (is_network_uri(m_uri)) {
|
||||
// Http handling here.
|
||||
m_stream = new std::stringstream;
|
||||
m_stream.reset(new std::stringstream);
|
||||
|
||||
HttpQueue::iterator itr = m_manager->http_queue()->insert(m_uri, m_stream);
|
||||
|
||||
(*itr)->signal_done().push_front(std::bind(&DownloadFactory::receive_loaded, this));
|
||||
(*itr)->signal_failed().push_front(std::bind(&DownloadFactory::receive_failed, this, std::placeholders::_1));
|
||||
itr->add_done_slot([this]() { receive_loaded(); });
|
||||
itr->add_failed_slot([this](const std::string& error) { receive_failed(error); });
|
||||
|
||||
m_variables["tied_to_file"] = (int64_t)false;
|
||||
|
||||
} else if (is_magnet_uri(m_uri)) {
|
||||
// DEBUG: Use m_object.
|
||||
m_stream = new std::stringstream();
|
||||
m_stream.reset(new std::stringstream());
|
||||
*m_stream << "d10:magnet-uri" << m_uri.length() << ":" << m_uri << "e";
|
||||
|
||||
m_variables["tied_to_file"] = (int64_t)false;
|
||||
@@ -172,8 +169,8 @@ DownloadFactory::receive_success() {
|
||||
else
|
||||
tracker_key = random() % (std::numeric_limits<uint32_t>::max() - 1) + 1;
|
||||
|
||||
Download* download = m_stream != NULL ?
|
||||
m_manager->download_list()->create(m_stream, tracker_key, m_printLog) :
|
||||
Download* download = m_stream != nullptr ?
|
||||
m_manager->download_list()->create(m_stream.get(), tracker_key, m_printLog) :
|
||||
m_manager->download_list()->create(m_object, tracker_key, m_printLog);
|
||||
|
||||
m_object = NULL;
|
||||
@@ -194,8 +191,8 @@ DownloadFactory::receive_success() {
|
||||
|
||||
torrent::Object::list_type& commands = meta.insert_key("commands", torrent::Object::create_list()).as_list();
|
||||
|
||||
for (command_list_type::iterator itr = m_commands.begin(); itr != m_commands.end(); ++itr)
|
||||
commands.push_back(*itr);
|
||||
for (auto& m_command : m_commands)
|
||||
commands.push_back(m_command);
|
||||
}
|
||||
|
||||
if (m_session) {
|
||||
@@ -289,9 +286,8 @@ DownloadFactory::receive_success() {
|
||||
if (torrent::log_groups[torrent::LOG_TORRENT_DEBUG].valid())
|
||||
log_created(download, rtorrent);
|
||||
|
||||
std::for_each(m_commands.begin(), m_commands.end(), [&download](const std::string& cmd) {
|
||||
rpc::parse_command_multiple_std(cmd, rpc::make_target(download));
|
||||
});
|
||||
for (const auto& command : m_commands)
|
||||
rpc::parse_command_multiple_std(command, rpc::make_target(download));
|
||||
|
||||
if (m_manager->download_list()->find(infohash) == m_manager->download_list()->end())
|
||||
throw torrent::input_error("The newly created download was removed.");
|
||||
@@ -336,8 +332,8 @@ DownloadFactory::log_created(Download* download, torrent::Object* rtorrent) {
|
||||
|
||||
dump << "---COMMANDS---" << std::endl;
|
||||
|
||||
for (command_list_type::const_iterator itr = m_commands.begin(); itr != m_commands.end(); itr++) {
|
||||
dump << *itr << std::endl;
|
||||
for (const auto& m_command : m_commands) {
|
||||
dump << m_command << std::endl;
|
||||
}
|
||||
|
||||
std::string dump_str = dump.str();
|
||||
|
||||
@@ -62,9 +62,9 @@ private:
|
||||
|
||||
void initialize_rtorrent(Download* download, torrent::Object* rtorrent);
|
||||
|
||||
Manager* m_manager;
|
||||
std::iostream* m_stream{};
|
||||
torrent::Object* m_object{};
|
||||
Manager* m_manager;
|
||||
std::shared_ptr<std::iostream> m_stream;
|
||||
torrent::Object* m_object{};
|
||||
|
||||
bool m_commited{};
|
||||
bool m_loaded{};
|
||||
|
||||
@@ -167,8 +167,10 @@ DownloadList::insert(Download* download) {
|
||||
|
||||
// This needs to be separated into two different calls to ensure
|
||||
// the download remains in the view.
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), [&download](View* v) { v->insert(download); });
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), [&download](View* v) { v->filter_download(download); });
|
||||
for (auto v : *control->view_manager())
|
||||
v->insert(download);
|
||||
for (auto v : *control->view_manager())
|
||||
v->filter_download(download);
|
||||
|
||||
DL_TRIGGER_EVENT(*itr, "event.download.inserted");
|
||||
|
||||
@@ -201,7 +203,8 @@ DownloadList::erase(iterator itr) {
|
||||
control->core()->download_store()->remove(*itr);
|
||||
|
||||
DL_TRIGGER_EVENT(*itr, "event.download.erased");
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), [itr](View* v) { v->erase(*itr); });
|
||||
for (auto v : *control->view_manager())
|
||||
v->erase(*itr);
|
||||
|
||||
torrent::download_remove(*(*itr)->download());
|
||||
delete *itr;
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_CORE_DOWNLOAD_SLOT_MAP_H
|
||||
#define RTORRENT_CORE_DOWNLOAD_SLOT_MAP_H
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "download.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
class DownloadSlotMap : public std::map<std::string, std::function<void (Download*)> > {
|
||||
public:
|
||||
typedef std::function<void (Download*)> slot_download;
|
||||
typedef std::map<std::string, slot_download> Base;
|
||||
|
||||
void insert(const std::string& key, slot_download s) { Base::operator[](key) = s; }
|
||||
void erase(const std::string& key) { Base::erase(key); }
|
||||
|
||||
void for_each(Download* d);
|
||||
};
|
||||
|
||||
inline void
|
||||
DownloadSlotMap::for_each(Download* d) {
|
||||
for (iterator itr = begin(), last = end(); itr != last; ++itr)
|
||||
itr->second(d);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -100,9 +100,10 @@ DownloadStore::write_bencode(const std::string& filename, const torrent::Object&
|
||||
#else
|
||||
fdatasync(fd);
|
||||
#endif
|
||||
::close(fd);
|
||||
}
|
||||
|
||||
::close(fd);
|
||||
|
||||
return true;
|
||||
|
||||
download_store_save_error:
|
||||
|
||||
+17
-25
@@ -1,43 +1,37 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <torrent/http.h>
|
||||
|
||||
#include "http_queue.h"
|
||||
#include "curl_get.h"
|
||||
|
||||
#include <torrent/common.h>
|
||||
#include <torrent/net/http_get.h>
|
||||
#include <torrent/net/http_stack.h>
|
||||
|
||||
namespace core {
|
||||
|
||||
HttpQueue::iterator
|
||||
HttpQueue::insert(const std::string& url, std::iostream* s) {
|
||||
std::unique_ptr<CurlGet> h(m_slot_factory());
|
||||
HttpQueue::insert(const std::string& url, std::shared_ptr<std::ostream> stream) {
|
||||
auto itr = base_type::insert(end(), torrent::net::HttpGet(url, stream));
|
||||
|
||||
h->set_url(url);
|
||||
h->set_stream(s);
|
||||
h->set_timeout(5 * 60);
|
||||
for (auto& slot : m_signal_insert)
|
||||
slot(*itr);
|
||||
|
||||
iterator signal_itr = base_type::insert(end(), h.get());
|
||||
itr->add_done_slot([this, itr]() { erase(itr); });
|
||||
itr->add_failed_slot([this, itr](auto) { erase(itr); });
|
||||
|
||||
h->signal_done().push_back(std::bind(&HttpQueue::erase, this, signal_itr));
|
||||
h->signal_failed().push_back(std::bind(&HttpQueue::erase, this, signal_itr));
|
||||
// TODO: Downloading http torrents doesn't seem to work.
|
||||
// TODO: Quitting no longer works.
|
||||
|
||||
(*signal_itr)->start();
|
||||
torrent::net_thread::http_stack()->start_get(*itr);
|
||||
|
||||
h.release();
|
||||
|
||||
for (signal_curl_get::iterator itr = m_signal_insert.begin(), last = m_signal_insert.end(); itr != last; itr++)
|
||||
(*itr)(*signal_itr);
|
||||
|
||||
return signal_itr;
|
||||
return itr;
|
||||
}
|
||||
|
||||
void
|
||||
HttpQueue::erase(iterator signal_itr) {
|
||||
for (signal_curl_get::iterator itr = m_signal_erase.begin(), last = m_signal_erase.end(); itr != last; itr++)
|
||||
(*itr)(*signal_itr);
|
||||
for (const auto& slot : m_signal_erase)
|
||||
slot(*signal_itr);
|
||||
|
||||
delete *signal_itr;
|
||||
signal_itr->close_and_keep_callbacks();
|
||||
base_type::erase(signal_itr);
|
||||
}
|
||||
|
||||
@@ -45,8 +39,6 @@ void
|
||||
HttpQueue::clear() {
|
||||
while (!empty())
|
||||
erase(begin());
|
||||
|
||||
base_type::clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-10
@@ -3,18 +3,20 @@
|
||||
|
||||
#include <functional>
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <torrent/net/http_get.h>
|
||||
|
||||
namespace core {
|
||||
|
||||
class CurlGet;
|
||||
// TODO: Remove this.
|
||||
|
||||
class HttpQueue : private std::list<CurlGet*> {
|
||||
class HttpQueue : private std::list<torrent::net::HttpGet> {
|
||||
public:
|
||||
typedef std::list<CurlGet*> base_type;
|
||||
typedef std::function<CurlGet* ()> slot_factory;
|
||||
typedef std::function<void (CurlGet*)> slot_curl_get;
|
||||
typedef std::list<slot_curl_get> signal_curl_get;
|
||||
using base_type = std::list<torrent::net::HttpGet>;
|
||||
using slot_curl_get = std::function<void (torrent::net::HttpGet)>;
|
||||
using signal_curl_get = std::list<slot_curl_get>;
|
||||
|
||||
using base_type::iterator;
|
||||
using base_type::const_iterator;
|
||||
@@ -37,18 +39,15 @@ public:
|
||||
//
|
||||
// Consider adding a flag to indicate whetever HttpQueue should
|
||||
// delete the stream.
|
||||
iterator insert(const std::string& url, std::iostream* s);
|
||||
iterator insert(const std::string& url, std::shared_ptr<std::ostream> stream);
|
||||
void erase(iterator itr);
|
||||
|
||||
void clear();
|
||||
|
||||
void set_slot_factory(slot_factory s) { m_slot_factory = s; }
|
||||
|
||||
signal_curl_get& signal_insert() { return m_signal_insert; }
|
||||
signal_curl_get& signal_erase() { return m_signal_erase; }
|
||||
|
||||
private:
|
||||
slot_factory m_slot_factory;
|
||||
signal_curl_get m_signal_insert;
|
||||
signal_curl_get m_signal_erase;
|
||||
};
|
||||
|
||||
+31
-49
@@ -18,6 +18,7 @@
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/object_stream.h>
|
||||
#include <torrent/throttle.h>
|
||||
#include <torrent/net/http_stack.h>
|
||||
#include <torrent/utils/log.h>
|
||||
|
||||
#include "rpc/parse_commands.h"
|
||||
@@ -26,15 +27,13 @@
|
||||
#include "utils/file_status_cache.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "curl_get.h"
|
||||
#include "curl_stack.h"
|
||||
#include "control.h"
|
||||
#include "download.h"
|
||||
#include "download_factory.h"
|
||||
#include "download_store.h"
|
||||
#include "http_queue.h"
|
||||
#include "manager.h"
|
||||
#include "view.h"
|
||||
#include "core/download.h"
|
||||
#include "core/download_factory.h"
|
||||
#include "core/download_store.h"
|
||||
#include "core/http_queue.h"
|
||||
#include "core/manager.h"
|
||||
#include "core/view.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -57,7 +56,6 @@ Manager::Manager() :
|
||||
m_download_list = std::make_unique<DownloadList>();
|
||||
m_file_status_cache = std::make_unique<FileStatusCache>();
|
||||
m_http_queue = std::make_unique<HttpQueue>();
|
||||
m_http_stack = std::make_unique<CurlStack>();
|
||||
|
||||
torrent::Throttle* unthrottled = torrent::Throttle::create_throttle();
|
||||
unthrottled->set_max_rate(0);
|
||||
@@ -131,39 +129,24 @@ Manager::retrieve_throttle_value(const torrent::Object::string_type& name, bool
|
||||
}
|
||||
}
|
||||
|
||||
// Most of this should be possible to move out.
|
||||
void
|
||||
Manager::initialize_second() {
|
||||
torrent::Http::slot_factory() = std::bind(&CurlStack::new_object, m_http_stack.get());
|
||||
m_http_queue->set_slot_factory(std::bind(&CurlStack::new_object, m_http_stack.get()));
|
||||
|
||||
CurlStack::global_init();
|
||||
}
|
||||
|
||||
void
|
||||
Manager::cleanup() {
|
||||
m_http_stack->shutdown();
|
||||
|
||||
// Need to disconnect log signals? Not really since we won't receive
|
||||
// any more.
|
||||
|
||||
m_download_list->clear();
|
||||
|
||||
// When we implement asynchronous DNS lookups, we need to cancel them
|
||||
// here before the torrent::* objects are deleted.
|
||||
|
||||
torrent::cleanup();
|
||||
|
||||
m_http_stack.reset();
|
||||
CurlStack::global_cleanup();
|
||||
}
|
||||
|
||||
void
|
||||
Manager::shutdown(bool force) {
|
||||
if (!force)
|
||||
std::for_each(m_download_list->begin(), m_download_list->end(), [this](Download* d) { m_download_list->pause_default(d); });
|
||||
for (auto d : *m_download_list)
|
||||
m_download_list->pause_default(d);
|
||||
else
|
||||
std::for_each(m_download_list->begin(), m_download_list->end(), [this](Download* d) { m_download_list->close_quick(d); });
|
||||
for (auto d : *m_download_list)
|
||||
m_download_list->close_quick(d);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -176,15 +159,11 @@ Manager::listen_open() {
|
||||
int portFirst, portLast;
|
||||
torrent::Object portRange = rpc::call_command("network.port_range");
|
||||
|
||||
if (portRange.is_string()) {
|
||||
if (std::sscanf(portRange.as_string().c_str(), "%i-%i", &portFirst, &portLast) != 2)
|
||||
throw torrent::input_error("Invalid port_range argument.");
|
||||
if (!portRange.is_string())
|
||||
throw torrent::input_error("Invalid port_range argument type.");
|
||||
|
||||
// } else if (portRange.is_list()) {
|
||||
|
||||
} else {
|
||||
if (std::sscanf(portRange.as_string().c_str(), "%i-%i", &portFirst, &portLast) != 2)
|
||||
throw torrent::input_error("Invalid port_range argument.");
|
||||
}
|
||||
|
||||
if (portFirst > portLast || portLast >= (1 << 16))
|
||||
throw torrent::input_error("Invalid port range.");
|
||||
@@ -229,7 +208,10 @@ Manager::set_bind_address(const std::string& addr) {
|
||||
torrent::connection_manager()->set_bind_address(ai->address()->c_sockaddr());
|
||||
}
|
||||
|
||||
m_http_stack->set_bind_address(!ai->address()->is_address_any() ? ai->address()->address_str() : std::string());
|
||||
if (ai->address()->is_address_any())
|
||||
torrent::net_thread::http_stack()->set_bind_address(std::string());
|
||||
else
|
||||
torrent::net_thread::http_stack()->set_bind_address(ai->address()->address_str());
|
||||
|
||||
rak::address_info::free_address_info(ai);
|
||||
|
||||
@@ -364,8 +346,8 @@ Manager::try_create_download_from_meta_download(torrent::Object* bencode, const
|
||||
|
||||
torrent::Object& meta = bencode->get_key("rtorrent_meta_download");
|
||||
torrent::Object::list_type& commands = meta.get_key_list("commands");
|
||||
for (torrent::Object::list_type::const_iterator itr = commands.begin(); itr != commands.end(); ++itr)
|
||||
f->commands().insert(f->commands().end(), itr->as_string());
|
||||
for (const auto& command : commands)
|
||||
f->commands().insert(f->commands().end(), command.as_string());
|
||||
|
||||
f->set_start(meta.get_key_value("start"));
|
||||
f->set_print_log(meta.get_key_value("print_log"));
|
||||
@@ -418,22 +400,22 @@ path_expand(std::vector<std::string>* paths, const std::string& pattern) {
|
||||
|
||||
// Special case for ".."?
|
||||
|
||||
for (std::vector<utils::Directory>::iterator itr = currentCache.begin(); itr != currentCache.end(); ++itr) {
|
||||
for (auto& itr : currentCache) {
|
||||
// Only include filenames starting with '.' if the pattern
|
||||
// starts with the same.
|
||||
itr->update((r.pattern()[0] != '.') ? utils::Directory::update_hide_dot : 0);
|
||||
itr->erase(std::remove_if(itr->begin(), itr->end(), [r](const utils::directory_entry& entry) { return !r(entry.s_name); }), itr->end());
|
||||
itr.update((r.pattern()[0] != '.') ? utils::Directory::update_hide_dot : 0);
|
||||
itr.erase(std::remove_if(itr.begin(), itr.end(), [r](const utils::directory_entry& entry) { return !r(entry.s_name); }), itr.end());
|
||||
|
||||
std::transform(itr->begin(), itr->end(), std::back_inserter(nextCache), [itr](const utils::directory_entry& entry) {
|
||||
return path_expand_transform(itr->path() + (itr->path() == "/" ? "" : "/"), entry);
|
||||
});
|
||||
for (const auto& cache : itr)
|
||||
nextCache.push_back(path_expand_transform(itr.path() + (itr.path() == "/" ? "" : "/"), cache));
|
||||
}
|
||||
|
||||
currentCache.clear();
|
||||
currentCache.swap(nextCache);
|
||||
}
|
||||
|
||||
std::transform(currentCache.begin(), currentCache.end(), std::back_inserter(*paths), std::mem_fn(&utils::Directory::path));
|
||||
for (const auto& cache : currentCache)
|
||||
paths->push_back(cache.path());
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -454,8 +436,8 @@ Manager::try_create_download_expand(const std::string& uri, int flags, command_l
|
||||
path_expand(&paths, uri);
|
||||
|
||||
if (!paths.empty())
|
||||
for (std::vector<std::string>::iterator itr = paths.begin(); itr != paths.end(); ++itr)
|
||||
try_create_download(*itr, flags, commands);
|
||||
for (auto& path : paths)
|
||||
try_create_download(path, flags, commands);
|
||||
|
||||
else
|
||||
try_create_download(uri, flags, commands);
|
||||
@@ -466,8 +448,8 @@ Manager::try_create_download_expand(const std::string& uri, int flags, command_l
|
||||
// hashing view and starts hashing if nessesary.
|
||||
void
|
||||
Manager::receive_hashing_changed() {
|
||||
bool foundHashing = std::find_if(m_hashingView->begin_visible(), m_hashingView->end_visible(),
|
||||
std::mem_fn(&Download::is_hash_checking)) != m_hashingView->end_visible();
|
||||
bool foundHashing = std::any_of(m_hashingView->begin_visible(), m_hashingView->end_visible(),
|
||||
std::mem_fn(&Download::is_hash_checking));
|
||||
|
||||
// Try quick hashing all those with hashing == initial, set them to
|
||||
// something else when failed.
|
||||
|
||||
@@ -21,7 +21,6 @@ class FileStatusCache;
|
||||
|
||||
namespace core {
|
||||
|
||||
class CurlStack;
|
||||
class DownloadStore;
|
||||
class HttpQueue;
|
||||
|
||||
@@ -42,7 +41,6 @@ public:
|
||||
FileStatusCache* file_status_cache() { return m_file_status_cache.get(); }
|
||||
|
||||
HttpQueue* http_queue() { return m_http_queue.get(); }
|
||||
CurlStack* http_stack() { return m_http_stack.get(); }
|
||||
|
||||
View* hashing_view() { return m_hashingView; }
|
||||
void set_hashing_view(View* v);
|
||||
@@ -59,8 +57,6 @@ public:
|
||||
void set_address_throttle(uint32_t begin, uint32_t end, torrent::ThrottlePair throttles);
|
||||
torrent::ThrottlePair get_address_throttle(const sockaddr* addr);
|
||||
|
||||
// Really should find a more descriptive name.
|
||||
void initialize_second();
|
||||
void cleanup();
|
||||
|
||||
void listen_open();
|
||||
@@ -109,7 +105,6 @@ private:
|
||||
std::unique_ptr<DownloadStore> m_download_store;
|
||||
std::unique_ptr<FileStatusCache> m_file_status_cache;
|
||||
std::unique_ptr<HttpQueue> m_http_queue;
|
||||
std::unique_ptr<CurlStack> m_http_stack;
|
||||
|
||||
View* m_hashingView{};
|
||||
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RTORRENT_CORE_RANGE_MAP_H
|
||||
#define RTORRENT_CORE_RANGE_MAP_H
|
||||
|
||||
+7
-8
@@ -16,7 +16,7 @@
|
||||
namespace core {
|
||||
|
||||
// Also add focus thingie here?
|
||||
struct view_downloads_compare : std::function<bool (Download*, Download*)> {
|
||||
struct view_downloads_compare {
|
||||
view_downloads_compare(const torrent::Object& cmd) :
|
||||
m_command(cmd) {}
|
||||
|
||||
@@ -50,7 +50,7 @@ struct view_downloads_compare : std::function<bool (Download*, Download*)> {
|
||||
const torrent::Object& m_command;
|
||||
};
|
||||
|
||||
struct view_downloads_filter : std::function<bool (Download*)> {
|
||||
struct view_downloads_filter {
|
||||
view_downloads_filter(const torrent::Object& cmd, const torrent::Object& cmd2) :
|
||||
m_command(cmd), m_command2(cmd2) {}
|
||||
|
||||
@@ -118,8 +118,8 @@ View::emit_changed() {
|
||||
|
||||
void
|
||||
View::emit_changed_now() {
|
||||
for (signal_void::iterator itr = m_signal_changed.begin(), last = m_signal_changed.end(); itr != last; itr++)
|
||||
(*itr)();
|
||||
for (auto& itr : m_signal_changed)
|
||||
itr();
|
||||
}
|
||||
|
||||
View::~View() {
|
||||
@@ -138,12 +138,11 @@ View::initialize(const std::string& name) {
|
||||
if (name.empty())
|
||||
throw torrent::internal_error("View::initialize(...) called with an empty name.");
|
||||
|
||||
core::DownloadList* dlist = control->core()->download_list();
|
||||
|
||||
m_name = name;
|
||||
|
||||
// Urgh, wrong. No filtering being done.
|
||||
std::for_each(dlist->begin(), dlist->end(), [&](Download* d) { push_back(d); });
|
||||
for (const auto& d : *control->core()->download_list())
|
||||
push_back(d);
|
||||
|
||||
m_size = base_type::size();
|
||||
m_focus = 0;
|
||||
@@ -347,7 +346,7 @@ View::clear_filter_on() {
|
||||
|
||||
inline void
|
||||
View::insert_visible(Download* d) {
|
||||
iterator itr = std::find_if(begin_visible(), end_visible(), [&d, this](Download* d2) { return view_downloads_compare(m_sortNew)(d, d2); });
|
||||
auto itr = std::find_if(begin_visible(), end_visible(), [this, d](auto d2) { return view_downloads_compare(m_sortNew)(d, d2); });
|
||||
|
||||
m_size++;
|
||||
m_focus += (m_focus >= position(itr));
|
||||
|
||||
@@ -18,7 +18,8 @@ namespace core {
|
||||
|
||||
void
|
||||
ViewManager::clear() {
|
||||
std::for_each(begin(), end(), [](View* v) { delete v; });
|
||||
for (auto v : *this)
|
||||
delete v;
|
||||
|
||||
base_type::clear();
|
||||
}
|
||||
@@ -88,8 +89,8 @@ ViewManager::set_filter_on(const std::string& name, const filter_args& args) {
|
||||
|
||||
// TODO: Ensure the filter keys are rlookup.
|
||||
|
||||
for (filter_args::const_iterator itr = args.begin(); itr != args.end(); ++itr)
|
||||
(*viewItr)->set_filter_on_event(*itr);
|
||||
for (const auto& arg : args)
|
||||
(*viewItr)->set_filter_on_event(arg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef RTORRENT_DISPLAY_CANVAS_H
|
||||
#define RTORRENT_DISPLAY_CANVAS_H
|
||||
|
||||
#include <cstdarg>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
+2
-4
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RTORRENT_DISPLAY_FRAME_H
|
||||
#define RTORRENT_DISPLAY_FRAME_H
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RTORRENT_DISPLAY_TEXT_ELEMENT_H
|
||||
#define RTORRENT_DISPLAY_TEXT_ELEMENT_H
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@@ -45,7 +43,8 @@ namespace display {
|
||||
|
||||
void
|
||||
TextElementList::clear() {
|
||||
std::for_each(begin(), end(), [](TextElement* t) { delete t; });
|
||||
for (auto t : *this)
|
||||
delete t;
|
||||
base_type::clear();
|
||||
}
|
||||
|
||||
@@ -55,14 +54,14 @@ TextElementList::print(char* first, char* last, Canvas::attributes_list* attribu
|
||||
|
||||
// Call print for each element even if first == last so that any
|
||||
// attributes gets added to the list.
|
||||
for (iterator itr = begin(); itr != end(); ++itr)
|
||||
for (auto& itr : *this)
|
||||
if (column-- > 0) {
|
||||
char* columnEnd = std::min(last, first + *m_columnWidth);
|
||||
|
||||
if (columnEnd < first || columnEnd > last)
|
||||
throw torrent::internal_error("TextElementList::print(...) columnEnd < first || columnEnd > last.");
|
||||
|
||||
first = (*itr)->print(first, columnEnd, attributes, target);
|
||||
first = itr->print(first, columnEnd, attributes, target);
|
||||
|
||||
if (first > columnEnd)
|
||||
throw torrent::internal_error("TextElementList::print(...) first > columnEnd.");
|
||||
@@ -71,7 +70,7 @@ TextElementList::print(char* first, char* last, Canvas::attributes_list* attribu
|
||||
first = columnEnd;
|
||||
|
||||
} else {
|
||||
first = (*itr)->print(first, last, attributes, target);
|
||||
first = itr->print(first, last, attributes, target);
|
||||
}
|
||||
|
||||
return first;
|
||||
@@ -82,15 +81,15 @@ TextElementList::max_length() {
|
||||
extent_type length = 0;
|
||||
int column = m_columnWidth != NULL ? m_column : 0;
|
||||
|
||||
for (iterator itr = begin(); itr != end(); ++itr) {
|
||||
extent_type l = column-- > 0 ? std::min((*itr)->max_length(), *m_columnWidth) : (*itr)->max_length();
|
||||
for (auto& itr : *this) {
|
||||
extent_type l = column-- > 0 ? std::min(itr->max_length(), *m_columnWidth) : itr->max_length();
|
||||
|
||||
if (l == extent_full)
|
||||
return extent_full;
|
||||
|
||||
length += l;
|
||||
}
|
||||
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RTORRENT_DISPLAY_TEXT_ELEMENT_LIST_H
|
||||
#define RTORRENT_DISPLAY_TEXT_ELEMENT_LIST_H
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RTORRENT_DISPLAY_TEXT_ELEMENT_STRING_H
|
||||
#define RTORRENT_DISPLAY_TEXT_ELEMENT_STRING_H
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include <torrent/utils/chrono.h>
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
+16
-18
@@ -1,5 +1,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "display/utils.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
@@ -14,18 +16,16 @@
|
||||
#include <torrent/data/file_list.h>
|
||||
#include <torrent/data/file_manager.h>
|
||||
#include <torrent/download/resource_manager.h>
|
||||
#include <torrent/net/http_stack.h>
|
||||
#include <torrent/peer/client_info.h>
|
||||
|
||||
#include "core/curl_stack.h"
|
||||
#include "control.h"
|
||||
#include "globals.h"
|
||||
#include "core/download.h"
|
||||
#include "core/manager.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "ui/root.h"
|
||||
|
||||
#include "control.h"
|
||||
#include "globals.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
char*
|
||||
@@ -111,7 +111,7 @@ print_download_info_full(char* first, char* last, core::Download* d) {
|
||||
first = print_buffer(first, last, "%6.1f / %6.1f MB",
|
||||
(double)d->download()->bytes_done() / (double)(1 << 20),
|
||||
(double)d->download()->file_list()->size_bytes() / (double)(1 << 20));
|
||||
|
||||
|
||||
first = print_buffer(first, last, " Rate: %5.1f / %5.1f KB Uploaded: %7.1f MB",
|
||||
(double)d->info()->up_rate()->rate() / (1 << 10),
|
||||
(double)d->info()->down_rate()->rate() / (1 << 10),
|
||||
@@ -295,15 +295,14 @@ print_status_throttle_limit(char* first, char* last, bool up, const ui::Throttle
|
||||
char* firstc = throttle_str;
|
||||
char* lastc = throttle_str + 40 - 1;
|
||||
|
||||
for (ui::ThrottleNameList::const_iterator itr = throttle_names.begin(), laste = throttle_names.end(); itr != laste; itr++) {
|
||||
for (const auto& throttle_name : throttle_names) {
|
||||
|
||||
if (!(*itr).empty()) {
|
||||
int64_t throttle_max = control->core()->retrieve_throttle_value(*itr, false, up);
|
||||
if (!throttle_name.empty()) {
|
||||
int64_t throttle_max = control->core()->retrieve_throttle_value(throttle_name, false, up);
|
||||
|
||||
if (throttle_max > 0)
|
||||
firstc = print_buffer(firstc, lastc, "|%1.0f", (double)throttle_max / 1024.0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Add temp buffer (chop first char first) into main buffer if temp buffer isn't empty
|
||||
@@ -321,10 +320,10 @@ print_status_throttle_rate(char* first, char* last, bool up, const ui::ThrottleN
|
||||
char* firstc = throttle_str;
|
||||
char* lastc = throttle_str + 50 - 1;
|
||||
|
||||
for (ui::ThrottleNameList::const_iterator itr = throttle_names.begin(), laste = throttle_names.end(); itr != laste; itr++) {
|
||||
for (const auto& throttle_name : throttle_names) {
|
||||
|
||||
if (!(*itr).empty() && (up ? torrent::up_throttle_global()->is_throttled() : torrent::down_throttle_global()->is_throttled())) {
|
||||
int64_t throttle_rate_value = control->core()->retrieve_throttle_value(*itr, true, up);
|
||||
if (!throttle_name.empty() && (up ? torrent::up_throttle_global()->is_throttled() : torrent::down_throttle_global()->is_throttled())) {
|
||||
int64_t throttle_rate_value = control->core()->retrieve_throttle_value(throttle_name, true, up);
|
||||
|
||||
if (throttle_rate_value > -1) {
|
||||
double throttle_rate = (double)throttle_rate_value / 1024.0;
|
||||
@@ -333,7 +332,6 @@ print_status_throttle_rate(char* first, char* last, bool up, const ui::ThrottleN
|
||||
firstc = print_buffer(firstc, lastc, "|%3.1f", throttle_rate);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Add temp buffer into main buffer if temp buffer isn't empty
|
||||
@@ -391,7 +389,7 @@ print_status_info(char* first, char* last) {
|
||||
first = print_address(first, last, torrent::connection_manager()->local_address());
|
||||
first = print_buffer(first, last, "]");
|
||||
}
|
||||
|
||||
|
||||
if (first > last)
|
||||
throw torrent::internal_error("print_status_info(...) wrote past end of the buffer.");
|
||||
|
||||
@@ -415,14 +413,14 @@ print_status_extra(char* first, char* last) {
|
||||
torrent::resource_manager()->max_download_unchoked());
|
||||
|
||||
first = print_buffer(first, last, " [H %u/%u]",
|
||||
control->core()->http_stack()->active(),
|
||||
control->core()->http_stack()->max_active());
|
||||
torrent::net_thread::http_stack()->active(),
|
||||
torrent::net_thread::http_stack()->max_active());
|
||||
|
||||
first = print_buffer(first, last, " [S %i/%i/%i]",
|
||||
torrent::total_handshakes(),
|
||||
torrent::connection_manager()->size(),
|
||||
torrent::connection_manager()->max_size());
|
||||
|
||||
|
||||
first = print_buffer(first, last, " [F %i/%i]",
|
||||
torrent::file_manager()->open_files(),
|
||||
torrent::file_manager()->max_open_files());
|
||||
|
||||
+1
-36
@@ -1,45 +1,10 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_DISPLAY_UTILS_H
|
||||
#define RTORRENT_DISPLAY_UTILS_H
|
||||
|
||||
#include <ctime>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace core {
|
||||
class Download;
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <torrent/utils/chrono.h>
|
||||
|
||||
namespace display {
|
||||
|
||||
Window::SlotTimer Window::m_slot_schedule;
|
||||
|
||||
@@ -55,9 +55,8 @@ WindowDownloadChunksSeen::redraw() {
|
||||
|
||||
const torrent::Bitfield* bitfield = m_download->download()->file_list()->bitfield();
|
||||
const torrent::TransferList* transfers = m_download->download()->transfer_list();
|
||||
std::vector<torrent::BlockList*> transferChunks(transfers->size(), 0);
|
||||
std::vector<torrent::BlockList*> transferChunks(transfers->begin(), transfers->end());
|
||||
|
||||
std::copy(transfers->begin(), transfers->end(), transferChunks.begin());
|
||||
std::sort(transferChunks.begin(), transferChunks.end());
|
||||
|
||||
std::vector<torrent::BlockList*>::const_iterator itrTransfer = transferChunks.begin();
|
||||
|
||||
@@ -40,7 +40,7 @@ WindowDownloadTransferList::redraw() {
|
||||
m_canvas->print(0, y, "%5u [P: %u F: %u]", (*itr)->index(), (*itr)->priority(), (*itr)->failed());
|
||||
|
||||
// Handle window size.
|
||||
for (torrent::BlockList::const_iterator bItr = (*itr)->begin(), bLast = (*itr)->end(); bItr != bLast; ++bItr) {
|
||||
for (const auto& bItr : **itr) {
|
||||
if (m_canvas->get_x() >= m_canvas->width() - 1) {
|
||||
if (++y >= m_canvas->height())
|
||||
break;
|
||||
@@ -51,22 +51,22 @@ WindowDownloadTransferList::redraw() {
|
||||
char id;
|
||||
chtype attr = A_NORMAL;
|
||||
|
||||
if (bItr->is_finished()) {
|
||||
if (bItr.is_finished()) {
|
||||
attr = A_REVERSE;
|
||||
id = key_id(bItr->leader()->const_peer_info());
|
||||
id = key_id(bItr.leader()->const_peer_info());
|
||||
|
||||
} else if (bItr->is_transfering()) {
|
||||
} else if (bItr.is_transfering()) {
|
||||
attr = A_BOLD;
|
||||
id = key_id(bItr->leader()->const_peer_info());
|
||||
id = key_id(bItr.leader()->const_peer_info());
|
||||
|
||||
} else if (bItr->queued()->size() >= 1) {
|
||||
id = std::tolower(key_id(bItr->queued()->back()->const_peer_info()));
|
||||
} else if (bItr.queued()->size() >= 1) {
|
||||
id = std::tolower(key_id(bItr.queued()->back()->const_peer_info()));
|
||||
|
||||
} else {
|
||||
id = '.';
|
||||
}
|
||||
|
||||
if (bItr->size_all() > 1)
|
||||
if (bItr.size_all() > 1)
|
||||
attr |= A_UNDERLINE;
|
||||
|
||||
m_canvas->print_char(attr | id);
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#include "display/window_http_queue.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <torrent/net/http_get.h>
|
||||
|
||||
#include "core/curl_get.h"
|
||||
#include "core/http_queue.h"
|
||||
#include "display/canvas.h"
|
||||
|
||||
@@ -17,8 +17,9 @@ WindowHttpQueue::WindowHttpQueue(core::HttpQueue* q) :
|
||||
m_queue(q) {
|
||||
|
||||
set_active(false);
|
||||
m_conn_insert = m_queue->signal_insert().insert(m_queue->signal_insert().end(), [this](auto* h) { receive_insert(h); });
|
||||
m_conn_erase = m_queue->signal_erase().insert(m_queue->signal_insert().end(), [this](auto* h) { receive_erase(h); });
|
||||
|
||||
m_conn_insert = m_queue->signal_insert().insert(m_queue->signal_insert().end(), [this](auto h) { receive_insert(h); });
|
||||
m_conn_erase = m_queue->signal_erase().insert(m_queue->signal_insert().end(), [this](auto h) { receive_erase(h); });
|
||||
|
||||
m_task_deactivate.slot() = [this] {
|
||||
if (!m_container.empty())
|
||||
@@ -55,14 +56,14 @@ WindowHttpQueue::redraw() {
|
||||
Container::iterator itr = m_container.begin();
|
||||
|
||||
while (itr != m_container.end() && pos + 10 < m_canvas->width()) {
|
||||
if (itr->m_http == NULL)
|
||||
if (!itr->m_http.is_valid())
|
||||
m_canvas->print(pos, 0, "[%s done]", itr->m_name.c_str());
|
||||
|
||||
else if (itr->m_http->size_total() == 0)
|
||||
else if (itr->m_http.size_total() == 0)
|
||||
m_canvas->print(pos, 0, "[%s ---%%]", itr->m_name.c_str());
|
||||
|
||||
else
|
||||
m_canvas->print(pos, 0, "[%s %3i%%]", itr->m_name.c_str(), (int)(100.0 * itr->m_http->size_done() / itr->m_http->size_total()));
|
||||
m_canvas->print(pos, 0, "[%s %3i%%]", itr->m_name.c_str(), (int)(100.0 * itr->m_http.size_done() / itr->m_http.size_total()));
|
||||
|
||||
pos += itr->m_name.size() + 6;
|
||||
++itr;
|
||||
@@ -72,7 +73,7 @@ WindowHttpQueue::redraw() {
|
||||
void
|
||||
WindowHttpQueue::cleanup_list() {
|
||||
for (Container::iterator itr = m_container.begin(); itr != m_container.end(); ) {
|
||||
if (itr->m_http == nullptr && itr->m_timer < torrent::this_thread::cached_time()) {
|
||||
if (!itr->m_http.is_valid() && itr->m_timer < torrent::this_thread::cached_time()) {
|
||||
itr = m_container.erase(itr);
|
||||
continue;
|
||||
}
|
||||
@@ -82,10 +83,10 @@ WindowHttpQueue::cleanup_list() {
|
||||
}
|
||||
|
||||
std::string
|
||||
WindowHttpQueue::create_name(core::CurlGet* h) {
|
||||
size_t p = h->url().rfind('/', h->url().size() - std::min<int>(10, h->url().size()));
|
||||
WindowHttpQueue::create_name(torrent::net::HttpGet http_get) {
|
||||
size_t p = http_get.url().rfind('/', http_get.url().size() - std::min<int>(10, http_get.url().size()));
|
||||
|
||||
std::string n = p != std::string::npos ? h->url().substr(p) : h->url();
|
||||
std::string n = p != std::string::npos ? http_get.url().substr(p) : http_get.url();
|
||||
|
||||
if (n.empty())
|
||||
throw std::logic_error("WindowHttpQueue::create_name(...) made a bad string");
|
||||
@@ -105,8 +106,8 @@ WindowHttpQueue::create_name(core::CurlGet* h) {
|
||||
}
|
||||
|
||||
void
|
||||
WindowHttpQueue::receive_insert(core::CurlGet* h) {
|
||||
m_container.push_back(Node(h, create_name(h)));
|
||||
WindowHttpQueue::receive_insert(torrent::net::HttpGet http_get) {
|
||||
m_container.push_back(Node(http_get, create_name(http_get)));
|
||||
|
||||
if (!is_active()) {
|
||||
set_active(true);
|
||||
@@ -117,13 +118,15 @@ WindowHttpQueue::receive_insert(core::CurlGet* h) {
|
||||
}
|
||||
|
||||
void
|
||||
WindowHttpQueue::receive_erase(core::CurlGet* h) {
|
||||
Container::iterator itr = std::find_if(m_container.begin(), m_container.end(), [h](Node& n) { return h == n.m_http; });
|
||||
WindowHttpQueue::receive_erase(torrent::net::HttpGet http_get) {
|
||||
auto itr = std::find_if(m_container.begin(),
|
||||
m_container.end(),
|
||||
[http_get](auto& n) { return http_get == n.m_http; });
|
||||
|
||||
if (itr == m_container.end())
|
||||
throw std::logic_error("WindowHttpQueue::receive_erase(...) tried to remove an object we don't have");
|
||||
|
||||
itr->m_http = nullptr;
|
||||
itr->m_http = torrent::net::HttpGet();
|
||||
itr->m_timer = torrent::this_thread::cached_time() + 4s;
|
||||
|
||||
mark_dirty();
|
||||
|
||||
@@ -3,20 +3,20 @@
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <torrent/net/http_get.h>
|
||||
|
||||
#include "window.h"
|
||||
|
||||
namespace core {
|
||||
class CurlGet;
|
||||
class HttpQueue;
|
||||
class HttpQueue;
|
||||
}
|
||||
|
||||
namespace display {
|
||||
|
||||
class WindowHttpQueue : public Window {
|
||||
public:
|
||||
typedef std::function<void (core::CurlGet*)> slot_curl_get;
|
||||
typedef std::list<slot_curl_get> signal_curl_get;
|
||||
typedef std::function<void (torrent::net::HttpGet)> slot_curl_get;
|
||||
typedef std::list<slot_curl_get> signal_curl_get;
|
||||
|
||||
WindowHttpQueue(core::HttpQueue* q);
|
||||
~WindowHttpQueue() override;
|
||||
@@ -25,9 +25,9 @@ public:
|
||||
|
||||
private:
|
||||
struct Node {
|
||||
Node(core::CurlGet* h, const std::string& n) : m_http(h), m_name(n) {}
|
||||
Node(torrent::net::HttpGet h, const std::string& n) : m_http(h), m_name(n) {}
|
||||
|
||||
core::CurlGet* m_http{};
|
||||
torrent::net::HttpGet m_http{};
|
||||
std::string m_name;
|
||||
std::chrono::microseconds m_timer{};
|
||||
};
|
||||
@@ -36,10 +36,10 @@ private:
|
||||
|
||||
void cleanup_list();
|
||||
|
||||
void receive_insert(core::CurlGet* h);
|
||||
void receive_erase(core::CurlGet* h);
|
||||
void receive_insert(torrent::net::HttpGet h);
|
||||
void receive_erase(torrent::net::HttpGet h);
|
||||
|
||||
static std::string create_name(core::CurlGet* h);
|
||||
static std::string create_name(torrent::net::HttpGet h);
|
||||
|
||||
core::HttpQueue* m_queue;
|
||||
Container m_container;
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RTORRENT_DISPLAY_WINDOW_INPUT_H
|
||||
#define RTORRENT_DISPLAY_WINDOW_INPUT_H
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RTORRENT_DISPLAY_WINDOW_STRING_LIST_H
|
||||
#define RTORRENT_DISPLAY_WINDOW_STRING_LIST_H
|
||||
|
||||
@@ -16,7 +16,8 @@ WindowText::WindowText(rpc::target_type target, extent_type margin) :
|
||||
|
||||
void
|
||||
WindowText::clear() {
|
||||
std::for_each(begin(), end(), [](TextElement* text) { delete text; });
|
||||
for (auto t : *this)
|
||||
delete t;
|
||||
base_type::clear();
|
||||
|
||||
delete m_errorHandler;
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RTORRENT_INPUT_BINDINGS_H
|
||||
#define RTORRENT_INPUT_BINDINGS_H
|
||||
|
||||
+14
-20
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@@ -58,8 +56,8 @@ PathInput::pressed(int key) {
|
||||
return TextInput::pressed(key);
|
||||
|
||||
} else if (m_showNext) {
|
||||
for (signal_void::iterator itr = m_signal_show_next.begin(), last = m_signal_show_next.end(); itr != last; itr++)
|
||||
(*itr)();
|
||||
for (auto& itr : m_signal_show_next)
|
||||
itr();
|
||||
|
||||
} else {
|
||||
receive_do_complete();
|
||||
@@ -68,17 +66,6 @@ PathInput::pressed(int key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
struct _transform_filename {
|
||||
void operator () (utils::directory_entry& entry) {
|
||||
#ifdef __sun__
|
||||
if (entry.s_type & S_IFDIR)
|
||||
#else
|
||||
if (entry.s_type == DT_DIR)
|
||||
#endif
|
||||
entry.s_name += '/';
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
PathInput::receive_do_complete() {
|
||||
lt_log_print(torrent::LOG_UI_EVENTS, "path_input: received completion");
|
||||
@@ -93,7 +80,14 @@ PathInput::receive_do_complete() {
|
||||
return;
|
||||
}
|
||||
|
||||
std::for_each(dir.begin(), dir.end(), _transform_filename());
|
||||
for (auto& entry : dir) {
|
||||
#ifdef __sun__
|
||||
if (entry.s_type & S_IFDIR)
|
||||
#else
|
||||
if (entry.s_type == DT_DIR)
|
||||
#endif
|
||||
entry.s_name += '/';
|
||||
}
|
||||
|
||||
range_type r = find_incomplete(dir, str().substr(dirEnd, get_pos()));
|
||||
|
||||
@@ -118,8 +112,8 @@ PathInput::receive_do_complete() {
|
||||
if (m_showNext) {
|
||||
lt_log_print(torrent::LOG_UI_EVENTS, "path_input: show next page");
|
||||
|
||||
for (signal_itr_itr::iterator itr = m_signal_show_range.begin(), last = m_signal_show_range.end(); itr != last; itr++)
|
||||
(*itr)(r.first, r.second);
|
||||
for (auto& itr : m_signal_show_range)
|
||||
itr(r.first, r.second);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RTORRENT_INPUT_PATH_INPUT_H
|
||||
#define RTORRENT_INPUT_PATH_INPUT_H
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RTORRENT_INPUT_TEXT_INPUT_H
|
||||
#define RTORRENT_INPUT_TEXT_INPUT_H
|
||||
|
||||
+50
-9
@@ -7,11 +7,12 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <inttypes.h>
|
||||
#include <typeinfo>
|
||||
#include <unistd.h>
|
||||
#include <torrent/http.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/data/chunk_utils.h>
|
||||
#include <torrent/utils/chrono.h>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <rak/error_number.h>
|
||||
|
||||
@@ -82,15 +83,44 @@ parse_options(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
initialize_rpc_slots() {
|
||||
rpc::rpc.slot_find_download() = [](const char* hash) {
|
||||
return control->core()->download_list()->find_hex_ptr(hash);
|
||||
};
|
||||
rpc::rpc.slot_find_file() = [](core::Download* d, uint32_t index) -> torrent::File* {
|
||||
if (index >= d->file_list()->size_files())
|
||||
throw torrent::input_error("invalid parameters: index not found");
|
||||
|
||||
return (*d->file_list())[index].get();
|
||||
};
|
||||
rpc::rpc.slot_find_tracker() = [](core::Download* d, uint32_t index) -> torrent::tracker::Tracker {
|
||||
if (index >= d->tracker_controller().size())
|
||||
throw torrent::input_error("invalid parameters: index not found");
|
||||
|
||||
// TODO: This should be rewritten to check if the tracker is valid and use a different
|
||||
// function.
|
||||
return d->tracker_controller().at(index);
|
||||
};
|
||||
rpc::rpc.slot_find_peer() = [](core::Download* d, const torrent::HashString& hash) -> torrent::Peer* {
|
||||
auto itr = d->connection_list()->find(hash.c_str());
|
||||
|
||||
if (itr == d->connection_list()->end())
|
||||
throw torrent::input_error("invalid parameters: hash not found");
|
||||
|
||||
return *itr;
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
load_session_torrents() {
|
||||
utils::Directory entries = control->core()->download_store()->get_formated_entries();
|
||||
|
||||
for (utils::Directory::const_iterator first = entries.begin(), last = entries.end(); first != last; ++first) {
|
||||
for (const auto& entry : entries) {
|
||||
// We don't really support session torrents that are links. These
|
||||
// would be overwritten anyway on exit, and thus not really be
|
||||
// useful.
|
||||
if (!first->is_file())
|
||||
if (!entry.is_file())
|
||||
continue;
|
||||
|
||||
core::DownloadFactory* f = new core::DownloadFactory(control->core());
|
||||
@@ -99,7 +129,7 @@ load_session_torrents() {
|
||||
f->set_session(true);
|
||||
f->set_init_load(true);
|
||||
f->slot_finished([f](){ delete f; });
|
||||
f->load(entries.path() + first->s_name);
|
||||
f->load(entries.path() + entry.s_name);
|
||||
f->commit();
|
||||
}
|
||||
}
|
||||
@@ -174,8 +204,14 @@ main(int argc, char** argv) {
|
||||
if (torrent::utils::Thread::should_handle_sigusr1())
|
||||
SignalHandler::set_handler(SIGUSR1, std::bind(&do_nothing));
|
||||
|
||||
torrent::log_add_group_output(torrent::LOG_NOTICE, "important");
|
||||
torrent::log_add_group_output(torrent::LOG_INFO, "complete");
|
||||
torrent::log_add_group_output(torrent::LOG_NOTICE, "important");
|
||||
torrent::log_add_group_output(torrent::LOG_DHT_ERROR, "important");
|
||||
|
||||
torrent::log_add_group_output(torrent::LOG_INFO, "complete");
|
||||
torrent::log_add_group_output(torrent::LOG_DHT_ERROR, "complete");
|
||||
torrent::log_add_group_output(torrent::LOG_DHT_CONTROLLER, "complete");
|
||||
|
||||
initialize_rpc_slots();
|
||||
|
||||
torrent::initialize();
|
||||
torrent::set_main_thread_slots(std::bind(&client_perform));
|
||||
@@ -309,6 +345,8 @@ main(int argc, char** argv) {
|
||||
"schedule2 = prune_file_status,3600,86400,((system.file_status_cache.prune))\n"
|
||||
|
||||
"protocol.encryption.set=allow_incoming,prefer_plaintext,enable_retry\n"
|
||||
|
||||
"ui.color.focus.set=reverse\n"
|
||||
);
|
||||
|
||||
// Functions that might not get depracted as they are nice for
|
||||
@@ -454,8 +492,10 @@ main(int argc, char** argv) {
|
||||
} catch (torrent::internal_error& e) {
|
||||
control->cleanup_exception();
|
||||
|
||||
std::cout << "Caught internal_error: " << e.what() << std::endl
|
||||
std::cout << "rtorrent: caught torrent::internal_error: "
|
||||
<< e.what() << std::endl
|
||||
<< e.backtrace();
|
||||
|
||||
lt_log_print_dump(torrent::LOG_CRITICAL, e.backtrace().c_str(), e.backtrace().size(),
|
||||
"Caught internal_error: '%s'.", e.what());
|
||||
return -1;
|
||||
@@ -463,7 +503,8 @@ main(int argc, char** argv) {
|
||||
} catch (std::exception& e) {
|
||||
control->cleanup_exception();
|
||||
|
||||
std::cout << "rtorrent: " << e.what() << std::endl;
|
||||
std::cout << "rtorrent: caught" << typeid(e).name() << " : " << e.what() << std::endl;
|
||||
|
||||
lt_log_print(torrent::LOG_CRITICAL, "Caught exception: '%s'.", e.what());
|
||||
return -1;
|
||||
}
|
||||
@@ -588,7 +629,7 @@ do_panic(int signum) {
|
||||
|
||||
void
|
||||
print_help() {
|
||||
std::cout << "Rakshasa's BitTorrent client version " VERSION "." << std::endl;
|
||||
std::cout << "Rakshasa's BitTorrent client version " PACKAGE_VERSION "." << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "All value pairs (f.ex rate and queue size) will be in the UP/DOWN" << std::endl;
|
||||
std::cout << "order. Use the up/down/left/right arrow keys to move between screens." << std::endl;
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@@ -88,17 +86,17 @@ bool
|
||||
OptionParser::has_flag(char flag, int argc, char** argv) {
|
||||
char options[3] = { '-', flag, '\0' };
|
||||
|
||||
return std::find_if(argv, argv + argc, [&options](char* c) { return std::strcmp(c, options) == 0; }) != argv + argc;
|
||||
return std::any_of(argv, argv + argc, [&options](char* c) { return std::strcmp(c, options) == 0; });
|
||||
}
|
||||
|
||||
std::string
|
||||
OptionParser::create_optstring() {
|
||||
std::string s;
|
||||
|
||||
for (Container::iterator itr = m_container.begin(); itr != m_container.end(); ++itr) {
|
||||
s += itr->first;
|
||||
for (auto& itr : m_container) {
|
||||
s += itr.first;
|
||||
|
||||
if (itr->second.m_useOption)
|
||||
if (itr.second.m_useOption)
|
||||
s += ':';
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RTORRENT_OPTION_PARSER_H
|
||||
#define RTORRENT_OPTION_PARSER_H
|
||||
|
||||
@@ -27,7 +27,7 @@ CommandMap::insert(const key_type& key, int flags, const char* parm, const char*
|
||||
throw torrent::internal_error("CommandMap::insert(...) tried to insert an already existing key.");
|
||||
|
||||
// TODO: This is not honoring the public_xmlrpc flags!!!
|
||||
if (rpc::rpc.is_initialized() && (flags & flag_public_rpc))
|
||||
if (rpc::rpc.is_handlers_initialized() && (flags & flag_public_rpc))
|
||||
rpc::rpc.insert_command(key.c_str(), parm, doc);
|
||||
|
||||
return base_type::insert(itr, value_type(key, command_map_data_type(flags, parm, doc)));
|
||||
@@ -55,10 +55,10 @@ CommandMap::create_redirect(const key_type& key_new, const key_type& key_dest, i
|
||||
|
||||
if (dest_itr == base_type::end())
|
||||
throw torrent::input_error("Tried to redirect to a key that doesn't exist: '" + std::string(key_dest) + "'.");
|
||||
|
||||
|
||||
if (new_itr != base_type::end())
|
||||
throw torrent::input_error("Tried to create a redirect key that already exists: '" + std::string(key_new) + "'.");
|
||||
|
||||
|
||||
if (dest_itr->second.m_flags & flag_is_redirect)
|
||||
throw torrent::input_error("Tried to redirect to a key that is not marked 'flag_is_redirect': '" +
|
||||
std::string(key_dest) + "'.");
|
||||
@@ -68,7 +68,7 @@ CommandMap::create_redirect(const key_type& key_new, const key_type& key_dest, i
|
||||
flags |= dest_itr->second.m_flags & ~(flag_has_redirects | flag_public_rpc);
|
||||
|
||||
// TODO: This is not honoring the public_xmlrpc flags!!!
|
||||
if (rpc::rpc.is_initialized() && (flags & flag_public_rpc))
|
||||
if (rpc::rpc.is_handlers_initialized() && (flags & flag_public_rpc))
|
||||
rpc::rpc.insert_command(key_new.c_str(), dest_itr->second.m_parm, dest_itr->second.m_doc);
|
||||
|
||||
iterator itr = base_type::insert(base_type::end(),
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <time.h>
|
||||
#include <rak/string_manip.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/utils/chrono.h>
|
||||
|
||||
#include "rpc/command_scheduler_item.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
@@ -14,7 +15,8 @@
|
||||
namespace rpc {
|
||||
|
||||
CommandScheduler::~CommandScheduler() {
|
||||
std::for_each(begin(), end(), [](CommandSchedulerItem* item) { delete item; });
|
||||
for (auto item : *this)
|
||||
delete item;
|
||||
}
|
||||
|
||||
CommandScheduler::iterator
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "rpc/command_scheduler_item.h"
|
||||
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/utils/chrono.h>
|
||||
|
||||
namespace rpc {
|
||||
|
||||
|
||||
+2
-4
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RTORRENT_RPC_FIXED_KEY_H
|
||||
#define RTORRENT_RPC_FIXED_KEY_H
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RTORRENT_RPC_IP_TABLE_LISTS_H
|
||||
#define RTORRENT_RPC_IP_TABLE_LISTS_H
|
||||
|
||||
+4
-6
@@ -70,9 +70,8 @@ object_to_json(const torrent::Object& object) noexcept {
|
||||
return object.as_string();
|
||||
case torrent::Object::TYPE_LIST: {
|
||||
json result = json::array();
|
||||
std::transform(object.as_list().cbegin(), object.as_list().cend(), std::back_inserter(result), [](const torrent::Object& element) {
|
||||
return object_to_json(element);
|
||||
});
|
||||
for (const auto& obj : object.as_list())
|
||||
result.push_back(object_to_json(obj));
|
||||
return result;
|
||||
}
|
||||
case torrent::Object::TYPE_MAP: {
|
||||
@@ -88,9 +87,8 @@ object_to_json(const torrent::Object& object) noexcept {
|
||||
|
||||
const auto& dict_obj = object.as_dict_obj();
|
||||
if (dict_obj.is_list()) {
|
||||
std::transform(dict_obj.as_list().cbegin(), dict_obj.as_list().cend(), std::back_inserter(result), [](const torrent::Object& element) {
|
||||
return object_to_json(element);
|
||||
});
|
||||
for (const auto& element : dict_obj.as_list())
|
||||
result.push_back(object_to_json(element));
|
||||
} else {
|
||||
result.push_back(object_to_json(dict_obj));
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user