Compare commits

...

123 Commits

Author SHA1 Message Date
rakshasa b38f80e597 Release 0.16.1. 2025-10-16 10:54:05 +02:00
Auska 2d2a756a3c fix: replace VLA
Avoids -Wvla-cxx-extension warning by using standard C++ container.
VLA is not part of standard C++ and causes portability issues.
2025-10-14 11:16:35 +02:00
Jari Sundell 891a6ba69d Added local address commands for inet/inet6. 2025-10-13 19:09:20 +09:00
Jari Sundell 2be730e4b3 Reuse HTTP connections and added totale/cached connection limits. 2025-10-09 21:15:24 +09:00
Jari Sundell bf53700f97 Added 'network.bind_address.ipv{4,6}.set' commands. 2025-10-04 20:24:08 +09:00
Jari Sundell 946dc54f9b Fix libtorrent links in README.md
Updated links to point to the GitHub repository for libtorrent.
2025-10-02 16:31:53 +09:00
Jari Sundell ea2347734b Added network.block.outgoing. 2025-09-23 17:56:51 +09:00
Jari Sundell 5206e6cb88 Moved various socket options to NetworkConfig. 2025-09-22 06:01:18 +09:00
Jari Sundell 48f82c17c2 Remove deprecated no-target flags for commands. 2025-09-20 17:27:26 +09:00
rakshasa 675625255d Check if target is null in xmlrpc_to_object(). 2025-09-20 09:22:56 +02:00
Jari Sundell 658e9f7578 Use simplified fd_accept(). 2025-09-18 17:40:56 +09:00
Jari Sundell e7a80c7b18 Remove deprecated rak::socket_address. 2025-09-17 21:44:54 +09:00
Jari Sundell 677f8f45c8 Improved listen/dht port handling and added 'dht.override_port.set' command. 2025-09-13 17:51:04 +09:00
Jari Sundell ba1ba3096a Added NetworkConfig. 2025-09-12 06:09:24 +09:00
Jari Sundell 65906a033a Preparing 0.16.0 release. 2025-09-05 18:32:24 +09:00
rakshasa dd5e0df05c Fixed HttpGet close call. 2025-09-04 13:11:56 +02:00
Bryant Eadon 00ef7d4be2 cleanup of personal information
Given the change to the README I thought it might be a good idea to also update the copyright notices which had an address too.
2025-09-02 20:10:38 +02:00
Jari Sundell e64f9fe324 Include torrent/common.h header. 2025-09-01 20:46:18 +09:00
Jari Sundell 9d3f6645be Fix formatting and capitalization in README.md 2025-09-01 16:45:24 +09:00
Jari Sundell 285827e611 Revise README structure and donation information
Updated sections in README for clarity and formatting.
2025-09-01 09:42:18 +02:00
Bryant Eadon 7fa1166baa README combined
Combined README files to reduce clutter.  However, the build instructions are incomplete ... I've started by modifying these so a build will complete using the instructions once I get a closer look at libtorrent ... additions welcome.
2025-09-01 09:42:18 +02:00
Bryant Eadon 43ba43252e Delete uused file
minor cleanup.
2025-09-01 09:42:18 +02:00
Bryant Eadon 207375c0cc Update README.md
proposing a new message for the release download.  to draw attention to the github repo, instead of the archive.
2025-08-31 12:47:12 +02:00
PRESFIL 4a5bc86643 doc(lua): More examples for insert_lua_method 2025-08-26 20:11:17 +02:00
PRESFIL 1039497a1a feat(lua): Extend insert_lua_method's func_name's arguments
Allows short form with number of arguments and long flexible form with table:

```lua
rtorrent.insert_lua_method('d.watch_handler', 'watch_handler', { '$argument.0=' })
rtorrent.insert_lua_method('d.watch_handler', 'watch_handler', { 0 })
rtorrent.insert_lua_method('d.watch_handler', 'watch_handler', { [1] = 0 })
rtorrent.insert_lua_method('d.watch_handler', 'watch_handler', 1)
rtorrent.insert_lua_method('d.watch_handler', 'watch_handler', 0)
```

Also, there are way to pass no arguments at all:

```lua
rtorrent.insert_lua_method('d.watch_handler', 'watch_handler')
```

Type checking added.
2025-08-26 20:11:17 +02:00
PRESFIL 36a39e91c8 doc(lua): insert_lua_method: Document, that target always passed 2025-08-26 20:11:17 +02:00
Jari Sundell d35a8d68e6 Fixed uninitialized rpc slots when SCGI is not used. 2025-08-25 15:56:15 +09:00
Jari Sundell bb1cdfc0e7 Fixed DHT bind address and converted to using sockaddr. 2025-08-23 02:54:54 +09:00
PRESFIL b0c68aa398 doc(lua): Example: Remove <const> for Lua 5.3 compatibility 2025-08-07 11:03:58 +02:00
PRESFIL 1492d39a3a feat(lua): Make LUA_DATADIR option 2025-08-07 11:03:58 +02:00
PRESFIL 8dcf2bc609 chore(lua): Use PACKAGE_DATADIR and AM_CPPFLAGS 2025-08-07 11:03:58 +02:00
PRESFIL 7022722c64 chore(lua): Make LUA_DATADIR instead of PACKAGE_DATADIR 2025-08-07 11:03:58 +02:00
PRESFIL 2829a73d8b chore(lua): Make AC_DEFINE_UNQUOTED for PACKAGE_DATADIR 2025-08-07 11:03:58 +02:00
PRESFIL 43c36db5fc chore(lua): Add empty newlines for code readability 2025-08-07 11:03:58 +02:00
PRESFIL 9ed8fe8fd8 doc(lua): Add example Lua configuration
Additional step to test in development (non-packaged) mode:

- In packaged mode, rtorrent knows where to search rtorrent.lua, but in
  project mode, rtorrent.lua located in a non-standard location.
  Therefore run rtorrent with following environment variabler set:

  LUA_PATH=<full path to rtorrent project dir>/lua/?.lua
2025-08-07 11:03:58 +02:00
PRESFIL 95cc070ecc feat(lua): Add insert_lua_method for lua-callbacks
Updated @kannibalox's method to pass lua-functions as rtorrent's methods.
2025-08-07 11:03:58 +02:00
PRESFIL d43d08404a feat(lua): Some aliases for Target-commands 2025-08-07 11:03:58 +02:00
PRESFIL c92becbb7c feat(lua): Replace Autocall with Target-object, Autocall_config -> Autocall
Deep-copy `__namestack` decouples all instances of Autocall, previously it
worked as singleton. This allows to store call-chains as variables, aliases.

Target-object allows to avoid duplication of the target-parameter as required
with Autocall by storing them as variables.

Autocall_config renamed to Autocall for brevity.
2025-08-07 11:03:58 +02:00
PRESFIL 20887b1ccb fix(lua): print= shadowed by native Lua print()
Trying `rc.print()` causes redirection to native global Lua `print()`, which
prints to stdout. I don't see any proc of shor-circuiting `autocall_config`
with global environment `_G`.
2025-08-07 11:03:58 +02:00
PRESFIL 3bd111e498 feat(lua): Add autocall_config assignment semantic 2025-08-07 11:03:58 +02:00
PRESFIL f8ec1ca95e fix(lua): Make rtorrent.lua accessible at start 2025-08-07 11:03:58 +02:00
PRESFIL d9976af767 chore(rpc/parse.cc): Fix typo 2025-08-07 11:03:58 +02:00
PRESFIL c649e49a42 fix(lua): Treat VALUE always as integer
rtorrent doesn't have floating point data type
2025-08-07 11:03:58 +02:00
PRESFIL 9b0d74bd68 fix(lua): Execution of commands with empty target 2025-08-07 11:03:58 +02:00
PRESFIL 09dd1ce9c8 fix(lua): Handling of LUA_TNIL 2025-08-07 11:03:58 +02:00
PRESFIL eb45508ab9 chore(lua): Remove unused lua_rtorrent_call() local function 2025-08-07 11:03:58 +02:00
PRESFIL a1ff6f5710 fix(lua): require(rtorrent) cause infinite loop
- missing `pos = end + 1` pos caused infinite loop

- there was no processing of the last element after the last ';', i.e. it was
  assumed that `lua_path` always has ';' in the last character
2025-08-07 11:03:58 +02:00
rakshasa 756e3bd5ae Invert color of focus ui element. 2025-08-05 08:56:22 +02:00
rakshasa ce97bf583d Fixed formating. 2025-08-04 09:52:27 +02:00
rakshasa dd8281204f Update common.m4. 2025-08-04 09:52:27 +02:00
rakshasa 420f03b40b Fixed input key bindings. 2025-08-04 09:52:27 +02:00
mmmsalmon 9ac43c2b40 remove comment 2025-08-04 09:52:27 +02:00
mmmsalmon 25448320aa add vi/emacs keybind for stopping/removing torrent from download list 2025-08-04 09:52:27 +02:00
rakshasa 788442de6a Added test for xmlrpc string reflection. 2025-08-02 15:02:25 +02:00
rakshasa 4492715737 Strict checking of d.views push_back arguments. 2025-08-02 15:02:25 +02:00
Jari Sundell f1a4c13c41 Added network.block.ipv4in6.set command. 2025-07-05 22:31:52 +09:00
Rosen Penev e11ac9abe3 remove downloa_slot_map.h
Unused.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-30 10:14:07 +02:00
Rosen Penev 34aba86d67 remove std::function inheritance
This does nothing but bloat code size.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-30 10:00:23 +02:00
Rosen Penev 5175414333 add chrono header
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-22 17:26:22 +02:00
Rosen Penev 2b15c4a1fa command_ui: use templates instead of function
Less overhead.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-21 11:48:21 +02:00
Rosen Penev 84c0d516ef replace for_each with range loops
No advantage over the latter, which is simpler.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-21 11:23:11 +02:00
Rosen Penev 8b663dd169 add a void cast to get rid of warning
Just copied the file from libtorrent.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-20 13:07:51 +02:00
Rosen Penev c48b7f5b93 replace VERSION with PACKAGE_VERSION
They're both the same. The latter is more descriptive.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-20 13:07:51 +02:00
rakshasa 4c06e7a923 Changed the order in which slots are added in HttpQueue. 2025-06-19 22:50:42 +02:00
Rosen Penev e3918f5d84 remove some get() calls
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-19 10:07:52 +02:00
Rosen Penev 0948b5f86a clang-tidy: convert loops to range based
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-19 09:57:21 +02:00
Phil Rosenthal bb8d677f6e Fix file descriptor leak in session file saving
When system.files.session.fdatasync is set to "no", file descriptors
  were not being closed after writing session files, causing a severe
  resource leak. Each save operation would leak one file descriptor.

  With hundreds of torrents, this leads to tens of thousands of leaked
  file descriptors within hours, mostly pointing to deleted session files.
  This can exhaust the system's file descriptor limit and cause rtorrent
  to fail when opening new files.

  The fix moves the close() call outside the fdatasync conditional block,
  ensuring file descriptors are always properly closed regardless of the
  fdatasync setting.
2025-06-18 19:00:56 +02:00
Rosen Penev dc6208ccc9 add missing header for va_list
Fixes compilation on NetBSD.
2025-06-18 18:20:22 +02:00
Rosen Penev 18d19e3dee initialize in vector directly
No need for std::copy.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-18 16:15:47 +02:00
Rosen Penev f0517e2748 replace various find_if calls
C++11 has shorter equivalents.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-18 14:39:42 +02:00
Rosen Penev 47089bce70 remove some transform calls
for range loop is more readable.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-17 17:13:05 +02:00
Jari Sundell 64cb3d11a0 Use shared_ptr for CurlGet stream and improved thread-safety. 2025-06-17 23:15:40 +09:00
Rosen Penev 12347843a9 add file.h header
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-11 20:32:35 +02:00
Jari Sundell 41589f06c2 Converted curl/http to be thread-safe. 2025-06-12 00:04:40 +09:00
Fredrik Lindell a51f367671 Add emacs and vi keymap config logic
* Add emacs and vi keymap config logic
2025-06-05 16:29:12 +02:00
Rosen Penev ac4afeb4bc remove variable fdset check
Doesn't seem to be used.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-05 14:33:28 +02:00
Rosen Penev 8d562d53fc remove disabling ipv6
Doesn't look like it does anything.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-05 14:33:28 +02:00
Rosen Penev 1a79eec876 remove LT_SMP_CACHE_BYTES
This is used by the library, not here.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-05 14:33:28 +02:00
Rosen Penev c803970628 remove posix_memalign check
This was used by the library, not here.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-05 14:33:28 +02:00
Rosen Penev 5f2f046165 remove HAVE_CONFIG_H define
config.h is always included. This is not a library.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-05 14:33:28 +02:00
Rosen Penev ad862f4b44 get rid of fs_stat.h and configure checks
These are used in libtorrent, not here.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-05 14:33:28 +02:00
Jari Sundell 6c25e64c26 Moved curl to libtorrent. 2025-06-05 20:29:43 +09:00
rakshasa 231606afc1 Fix ExecFile waitpid error handling. 2025-06-01 18:41:22 +02:00
rakshasa a9196b43d4 Added missing header to Makefile.am. 2025-06-01 15:40:22 +02:00
rakshasa 8203949259 Removed deprecated headers from Makefile.am. 2025-06-01 15:27:42 +02:00
rakshasa 537c692f47 Tagged release 0.15.4. 2025-06-01 14:44:29 +02:00
Rosen Penev 95b1a19ef1 use _T sizes for curl
The non _T are deprecated.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-01 11:21:36 +02:00
Rosen Penev a4ab0112dc convert color_vars to std::array
Fixes:

warning: ‘display::color_vars’ defined but not used

Could also add const to it.

Do the same with color_names.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-01 08:31:16 +02:00
Rosen Penev 897a6face2 clang-tidy: use default member init
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-01 08:16:02 +02:00
Rosen Penev 3ab38583b8 remove __UNUSED
No need since we have C++17.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-01 08:07:37 +02:00
Rosen Penev 1003013f10 remove allocators.h
Unused.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-06-01 08:07:37 +02:00
rakshasa 7bbd9a02a0 Proper handling of DownloadList::clear(). 2025-05-31 23:16:23 +02:00
Jari Sundell f0809ec29d Various pool_event_* and thread API cleanups. 2025-06-01 01:22:14 +09:00
Jari Sundell e8c1f3ed2c Update to use new this_thread::Poll(). 2025-05-31 22:22:31 +09:00
Jari Sundell 3618b9dc4f Added system.files.advise_random.hashing.set command. 2025-05-31 19:19:08 +09:00
rakshasa df8cb53ed2 Properly clear out download list before calling torrent::cleanup(). 2025-05-30 14:31:52 +02:00
rakshasa 2d565d1c80 Do thread cleanup within the same thread context. 2025-05-30 14:31:52 +02:00
Jari Sundell de6c48ca3f Moved TrackerList and TrackerController out of the public API. 2025-05-28 17:11:29 +09:00
rakshasa 5fb61b2857 Removed old poll creation calls. 2025-05-27 12:23:39 +02:00
rakshasa 46e94259e8 Make sure threads are rejoined. 2025-05-26 15:18:59 +02:00
Jari Sundell 9ff373fe58 Related refactoring to updated of ThrottleList to use new Scheduler. 2025-05-12 17:38:07 +09:00
Fredrik Lindell 6d888c008d Align compact display download header labels
* Align compact display download header labels
2025-05-11 09:45:47 +02:00
rakshasa 9fe4d188e9 Cleaned up WindowHttpQueue. 2025-05-08 08:32:45 +02:00
Jari Sundell 9d5b769d78 Removed/replaced deprecated commands (execute/schedule/schedule_remove) and removed global lock in ExecFile. 2025-05-05 16:55:38 +09:00
rakshasa 55615abe9e Use poll interrupting callbacks for SCGI requests. 2025-05-04 11:57:04 +02:00
rakshasa 303edab9ec Detect content type when there's multiple elements. 2025-05-04 11:28:18 +02:00
rakshasa 877c00d54e Fixed missing return statement. 2025-05-03 18:09:28 +02:00
Jari Sundell 4c63cee7a2 Cleaned up Poll code and included missing rtorrent.lua in installer. 2025-05-03 21:07:16 +09:00
Jorge Israel Peña 58a74cee48 Wrap fault struct in value 2025-05-02 12:13:49 +02:00
Jari Sundell 85e74b5542 Removed priority_queue and rak/timer. 2025-05-02 18:03:51 +09:00
rakshasa 6f8c1246dc Tagged release 0.15.3. 2025-05-01 14:34:45 +02:00
Jari Sundell 97415c656b Various scheduler and therad cleanups. 2025-05-01 16:38:49 +09:00
rakshasa 3d9c083032 Fix scheduler access. 2025-04-21 11:09:26 +02:00
Jari Sundell dd221ac66a Replaced Thread::next_timeout_usec(). 2025-04-16 02:39:40 +09:00
Rosen Penev 25f729fab5 use priotity_enum
The _t typedef is only useful with C, not C++.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-04-15 10:07:29 +02:00
rakshasa 316b0b51d5 Use new thread event loop method. 2025-04-14 11:15:07 +02:00
rakshasa a8622e5c80 Cleaned up thread-related code. 2025-04-12 23:03:08 +02:00
Abzie d1dd5ac080 Add RPC options to rtorrent.rc-example documentation 2025-04-11 16:16:44 +02:00
Abzie 9f2b81534a Add RPC options to rtorrent.rc documentation 2025-04-11 16:16:44 +02:00
Jari Sundell 2ab7460cbc Fix SCGI threading and added missing header. 2025-04-01 01:26:07 +09:00
rakshasa 2a998df4f1 Fixed LUA compilaition issue. 2025-03-31 06:19:02 +02:00
rakshasa d5b28c30a9 Added default switch cases to RpcManager. 2025-03-30 15:38:07 +02:00
rakshasa a5a1e2fde5 Updated common.m4. 2025-03-30 15:38:07 +02:00
251 changed files with 3705 additions and 7271 deletions
@@ -16,6 +16,9 @@ jobs:
# OPTIONAL: auto-closing conversations requires the `contents` permission
contents: write
steps:
- name: Sleep for 30 seconds
run: sleep 30s
shell: bash
- name: Download analysis results
uses: actions/github-script@v7
with:
+6 -3
View File
@@ -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
+13 -5
View File
@@ -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
View File
@@ -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
View File
+3 -6
View File
@@ -3,21 +3,18 @@ SUBDIRS = \
src \
test
nobase_dist_pkgdata_DATA = \
lua/rtorrent.lua
EXTRA_DIST= \
rak/address_info.h \
rak/algorithm.h \
rak/allocators.h \
rak/error_number.h \
rak/file_stat.h \
rak/fs_stat.h \
rak/path.h \
rak/partial_queue.h \
rak/priority_queue.h \
rak/priority_queue_default.h \
rak/regex.h \
rak/socket_address.h \
rak/string_manip.h \
rak/timer.h \
rak/unordered_vector.h \
scripts/checks.m4 \
scripts/common.m4 \
View File
-41
View File
@@ -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.
+69 -21
View File
@@ -1,40 +1,88 @@
[![Donate](https://rakshasa.github.io/rtorrent/donate_paypal_green.svg)](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://github.com/rakshasa/libtorrent) 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://github.com/rakshasa/libtorrent) 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
+10 -23
View File
@@ -1,6 +1,6 @@
m4_pattern_allow([PKG_CHECK_EXISTS])
AC_INIT([rtorrent],[0.15.2],[sundell.software@gmail.com])
AC_INIT([rtorrent],[0.16.1],[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], [11], [api version])
AC_DEFINE([API_VERSION], [17], [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.2])
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.16.1])
AC_LANG_PUSH(C++)
TORRENT_WITH_XMLRPC_C
@@ -67,23 +61,15 @@ 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)
TORRENT_CHECK_CACHELINE()
TORRENT_CHECK_POPCOUNT()
CC_ATTRIBUTE_UNUSED(
AC_DEFINE([__UNUSED], [__attribute__((unused))], [Wrapper around unused attribute]),
AC_DEFINE([__UNUSED], [], [Null-wrapper if unused attribute is unsupported])
)
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_POPCOUNT()
AC_CONFIG_FILES([
Makefile
@@ -91,4 +77,5 @@ AC_CONFIG_FILES([
src/Makefile
test/Makefile
])
AC_OUTPUT
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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>
+8
View File
@@ -73,6 +73,10 @@
#
#network.port_random.set = no
# Set RPC type
#network.rpc.use_xmlrpc.set = true
#network.rpc.use_jsonrpc.set = true
# Check hash for finished torrents. Might be useful until the bug is
# fixed that causes lack of disk-space not to be properly reported.
#
@@ -115,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
+2
View File
@@ -76,6 +76,8 @@ schedule2 = monitor_diskspace, 15, 60, ((close_low_diskspace, 1000M))
##network.http.capath.set = "/etc/ssl/certs"
##network.http.ssl_verify_peer.set = 0
##network.http.ssl_verify_host.set = 0
#network.rpc.use_xmlrpc.set = true
#network.rpc.use_jsonrpc.set = true
# Some additional values and commands
method.insert = system.startup_time, value|const, (system.time)
+141
View File
@@ -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 ]]--
+127
View File
@@ -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
+4 -42
View File
@@ -1,39 +1,3 @@
// 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
// Wrapper for addrinfo with focus on zero-copy conversion to and from
// the c-type and wrapper.
//
@@ -44,7 +8,7 @@
#define RAK_ADDRESS_INFO_H
#include <netdb.h>
#include <rak/socket_address.h>
#include <cstring>
namespace rak {
@@ -60,13 +24,11 @@ public:
int socket_type() const { return m_addrinfo.ai_socktype; }
void set_socket_type(int t) { m_addrinfo.ai_socktype = t; }
int protocol() const { return m_addrinfo.ai_protocol; }
void set_protocol(int p) { m_addrinfo.ai_protocol = p; }
size_t length() const { return m_addrinfo.ai_addrlen; }
socket_address* address() { return reinterpret_cast<socket_address*>(m_addrinfo.ai_addr); }
size_t length() const { return m_addrinfo.ai_addrlen; }
addrinfo* c_addrinfo() { return &m_addrinfo; }
const addrinfo* c_addrinfo() const { return &m_addrinfo; }
@@ -89,7 +51,7 @@ address_info::get_address_info(const char* node, int pfamily, int stype, address
hints.clear();
hints.set_family(pfamily);
hints.set_socket_type(stype);
return ::getaddrinfo(node, NULL, hints.c_addrinfo(), reinterpret_cast<addrinfo**>(ai));
}
+3 -6
View File
@@ -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);
}
-110
View File
@@ -1,110 +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
// Some allocators for cacheline aligned chunks of memory, etc.
#ifndef RAK_ALLOCATORS_H
#define RAK_ALLOCATORS_H
#include <cstddef>
#include <limits>
#include <stdlib.h>
#include <sys/types.h>
namespace rak {
template <class T = void*>
class cacheline_allocator {
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef const void* const_void_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
cacheline_allocator() throw() { }
cacheline_allocator(const cacheline_allocator&) throw() { }
template <class U>
cacheline_allocator(const cacheline_allocator<U>&) throw() { }
~cacheline_allocator() throw() { }
template <class U>
struct rebind { typedef cacheline_allocator<U> other; };
// return address of values
pointer address (reference value) const { return &value; }
const_pointer address (const_reference value) const { return &value; }
size_type max_size () const throw() { return std::numeric_limits<size_t>::max() / sizeof(T); }
pointer allocate(size_type num, const_void_pointer hint = 0) { return alloc_size(num*sizeof(T)); }
static pointer alloc_size(size_type size) {
pointer ptr = NULL;
int __UNUSED result = posix_memalign((void**)&ptr, LT_SMP_CACHE_BYTES, size);
return ptr;
}
void construct (pointer p, const T& value) { new((void*)p)T(value); }
void destroy (pointer p) { p->~T(); }
void deallocate (pointer p, size_type num) { free((void*)p); }
};
template <class T1, class T2>
bool operator== (const cacheline_allocator<T1>&, const cacheline_allocator<T2>&) throw() {
return true;
}
template <class T1, class T2>
bool operator!= (const cacheline_allocator<T1>&, const cacheline_allocator<T2>&) throw() {
return false;
}
}
//
// Operator new with custom allocators:
//
template <typename T>
void* operator new(size_t s, rak::cacheline_allocator<T> a) { return a.alloc_size(s); }
#endif // namespace rak
+1 -4
View File
@@ -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
View File
@@ -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
-84
View File
@@ -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
View File
@@ -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
View File
@@ -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.
-79
View File
@@ -1,79 +0,0 @@
// priority_queue is a priority queue implemented using a binary
// heap. It can contain multiple instances of a value.
#ifndef RAK_PRIORITY_QUEUE_H
#define RAK_PRIORITY_QUEUE_H
#include <algorithm>
#include <functional>
#include <vector>
namespace rak {
template <typename Value, typename Compare, typename Equal>
class priority_queue : public std::vector<Value> {
public:
typedef std::vector<Value> base_type;
typedef typename base_type::reference reference;
typedef typename base_type::const_reference const_reference;
typedef typename base_type::iterator iterator;
typedef typename base_type::const_iterator const_iterator;
typedef typename base_type::value_type value_type;
using base_type::begin;
using base_type::end;
using base_type::size;
using base_type::empty;
using base_type::clear;
priority_queue(Compare l = Compare(), Equal e = Equal())
: m_compare(l), m_equal(e) {}
const_reference top() const {
return base_type::front();
}
void pop() {
std::pop_heap(begin(), end(), m_compare);
base_type::pop_back();
}
void update() {
std::make_heap(begin(), end(), m_compare);
}
void push(const value_type& value) {
base_type::push_back(value);
std::push_heap(begin(), end(), m_compare);
}
template <typename Key>
iterator find(const Key& key) {
return std::find_if(begin(), end(), [&](auto& value) { return m_equal(value, key); });
}
template <typename Key>
bool erase(const Key& key) {
iterator itr = find(key);
if (itr == end())
return false;
erase(itr);
return true;
}
// Removes 'itr' from the queue.
void erase(iterator itr) {
base_type::erase(itr);
std::make_heap(begin(), end(), m_compare);
}
private:
Compare m_compare;
Equal m_equal;
};
}
#endif
-122
View File
@@ -1,122 +0,0 @@
#ifndef RAK_PRIORITY_QUEUE_DEFAULT_H
#define RAK_PRIORITY_QUEUE_DEFAULT_H
#include <cassert>
#include <functional>
#include <rak/priority_queue.h>
#include <rak/timer.h>
#include "torrent/exceptions.h"
namespace rak {
class priority_item {
public:
typedef std::function<void (void)> slot_void;
priority_item() {}
~priority_item() {
assert(!is_queued() && "priority_item::~priority_item() called on a queued item.");
m_time = timer();
m_slot = slot_void();
}
bool is_valid() const { return (bool)m_slot; }
bool is_queued() const { return m_time != timer(); }
slot_void& slot() { return m_slot; }
const timer& time() const { return m_time; }
void clear_time() { m_time = timer(); }
void set_time(const timer& t) { m_time = t; }
bool compare(const timer& t) const { return m_time > t; }
private:
priority_item(const priority_item&);
void operator = (const priority_item&);
timer m_time;
slot_void m_slot;
};
struct priority_compare {
bool operator () (const priority_item* const p1, const priority_item* const p2) const {
return p1->time() > p2->time();
}
};
typedef std::equal_to<priority_item*> priority_equal;
typedef priority_queue<priority_item*, priority_compare, priority_equal> priority_queue_default;
inline void
priority_queue_perform(priority_queue_default* queue, timer t) {
while (!queue->empty() && queue->top()->time() <= t) {
priority_item* v = queue->top();
queue->pop();
v->clear_time();
v->slot()();
}
}
inline void
priority_queue_insert(priority_queue_default* queue, priority_item* item, timer t) {
if (t == timer())
throw torrent::internal_error("priority_queue_insert(...) received a bad timer.");
if (!item->is_valid())
throw torrent::internal_error("priority_queue_insert(...) called on an invalid item.");
if (item->is_queued())
throw torrent::internal_error("priority_queue_insert(...) called on an already queued item.");
if (queue->find(item) != queue->end())
throw torrent::internal_error("priority_queue_insert(...) item found in queue.");
item->set_time(t);
queue->push(item);
}
inline void
priority_queue_erase(priority_queue_default* queue, priority_item* item) {
if (!item->is_queued())
return;
// Check is_valid() after is_queued() so that it is safe to call
// erase on untouched instances.
if (!item->is_valid())
throw torrent::internal_error("priority_queue_erase(...) called on an invalid item.");
// Unqueue it before erasing.
item->clear_time();
if (!queue->erase(item))
throw torrent::internal_error("priority_queue_erase(...) could not find item in queue.");
}
inline void
priority_queue_update(priority_queue_default* queue, priority_item* item, timer t) {
if (t == timer())
throw torrent::internal_error("priority_queue_insert(...) received a bad timer.");
if (!item->is_valid())
throw torrent::internal_error("priority_queue_insert(...) called on an invalid item.");
if (queue->find(item) == queue->end()) {
if (item->is_queued())
throw torrent::internal_error("priority_queue_update(...) cannot insert an already queued item.");
item->set_time(t);
queue->push(item);
} else {
item->set_time(t);
queue->update();
}
}
}
#endif
+3 -5
View File
@@ -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) {}
-559
View File
@@ -1,559 +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
// Wrappers for the various sockaddr types with focus on zero-copy
// casting between the original type and the wrapper class.
//
// The default ctor does not initialize any data.
//
// _n suffixes indicate that the argument or return value is in
// network byte order, _h that they are in hardware byte order.
// Add define for inet6 scope id?
#ifndef RAK_SOCKET_ADDRESS_H
#define RAK_SOCKET_ADDRESS_H
#include <cinttypes>
#include <cstdint>
#include <cstring>
#include <stdexcept>
#include <string>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
namespace rak {
class socket_address_inet;
class socket_address_inet6;
class socket_address {
public:
static const sa_family_t af_inet = AF_INET;
static const int pf_inet = PF_INET;
static const sa_family_t af_inet6 = AF_INET6;
static const int pf_inet6 = PF_INET6;
static const sa_family_t af_unspec = AF_UNSPEC;
static const int pf_unspec = PF_UNSPEC;
#ifdef AF_LOCAL
static const sa_family_t af_local = AF_LOCAL;
static const int pf_local = PF_LOCAL;
#else
static const sa_family_t af_local = AF_UNIX;
static const int pf_local = PF_UNIX;
#endif
bool is_any() const;
bool is_valid() const;
bool is_bindable() const;
bool is_address_any() const;
bool is_valid_inet_class() const { return family() == af_inet || family() == af_inet6; }
void clear() { std::memset(this, 0, sizeof(socket_address)); set_family(); }
sa_family_t family() const { return m_sockaddr.sa_family; }
void set_family() { m_sockaddr.sa_family = af_unspec; }
uint16_t port() const;
void set_port(uint16_t p);
std::string address_str() const;
bool address_c_str(char* buf, socklen_t size) const;
std::string pretty_address_str() const;
// Attemts to set it as an inet, then an inet6 address. It will
// never set anything but net addresses, no local/unix.
bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
bool set_address_c_str(const char* a);
uint32_t length() const;
socket_address_inet* sa_inet() { return reinterpret_cast<socket_address_inet*>(this); }
const socket_address_inet* sa_inet() const { return reinterpret_cast<const socket_address_inet*>(this); }
sockaddr* c_sockaddr() { return &m_sockaddr; }
sockaddr_in* c_sockaddr_inet() { return &m_sockaddrInet; }
const sockaddr* c_sockaddr() const { return &m_sockaddr; }
const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddrInet; }
socket_address_inet6* sa_inet6() { return reinterpret_cast<socket_address_inet6*>(this); }
const socket_address_inet6* sa_inet6() const { return reinterpret_cast<const socket_address_inet6*>(this); }
sockaddr_in6* c_sockaddr_inet6() { return &m_sockaddrInet6; }
const sockaddr_in6* c_sockaddr_inet6() const { return &m_sockaddrInet6; }
// Copy a socket address which has the length 'length. Zero out any
// extranous bytes and ensure it does not go beyond the size of this
// struct.
void copy(const socket_address& src, size_t length);
void copy_sockaddr(const sockaddr* src);
static socket_address* cast_from(sockaddr* sa) { return reinterpret_cast<socket_address*>(sa); }
static const socket_address* cast_from(const sockaddr* sa) { return reinterpret_cast<const socket_address*>(sa); }
// The different families will be sorted according to the
// sa_family_t's numeric value.
bool operator == (const socket_address& rhs) const;
bool operator < (const socket_address& rhs) const;
bool operator == (const sockaddr& rhs) const { return *this == *cast_from(&rhs); }
bool operator == (const sockaddr* rhs) const { return *this == *cast_from(rhs); }
bool operator < (const sockaddr& rhs) const { return *this == *cast_from(&rhs); }
bool operator < (const sockaddr* rhs) const { return *this == *cast_from(rhs); }
private:
union {
sockaddr m_sockaddr;
sockaddr_in m_sockaddrInet;
sockaddr_in6 m_sockaddrInet6;
};
};
// Remember to set the AF_INET.
class socket_address_inet {
public:
bool is_any() const { return is_port_any() && is_address_any(); }
bool is_valid() const { return !is_port_any() && !is_address_any(); }
bool is_port_any() const { return port() == 0; }
bool is_address_any() const { return m_sockaddr.sin_addr.s_addr == htonl(INADDR_ANY); }
void clear() { std::memset(this, 0, sizeof(socket_address_inet)); set_family(); }
uint16_t port() const { return ntohs(m_sockaddr.sin_port); }
uint16_t port_n() const { return m_sockaddr.sin_port; }
void set_port(uint16_t p) { m_sockaddr.sin_port = htons(p); }
void set_port_n(uint16_t p) { m_sockaddr.sin_port = p; }
// Should address() return the uint32_t?
in_addr address() const { return m_sockaddr.sin_addr; }
uint32_t address_h() const { return ntohl(m_sockaddr.sin_addr.s_addr); }
uint32_t address_n() const { return m_sockaddr.sin_addr.s_addr; }
std::string address_str() const;
bool address_c_str(char* buf, socklen_t size) const;
void set_address(in_addr a) { m_sockaddr.sin_addr = a; }
void set_address_h(uint32_t a) { m_sockaddr.sin_addr.s_addr = htonl(a); }
void set_address_n(uint32_t a) { m_sockaddr.sin_addr.s_addr = a; }
bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
bool set_address_c_str(const char* a);
void set_address_any() { set_port(0); set_address_h(INADDR_ANY); }
sa_family_t family() const { return m_sockaddr.sin_family; }
void set_family() { m_sockaddr.sin_family = AF_INET; }
sockaddr* c_sockaddr() { return reinterpret_cast<sockaddr*>(&m_sockaddr); }
sockaddr_in* c_sockaddr_inet() { return &m_sockaddr; }
const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddr; }
socket_address_inet6 to_mapped_address() const;
bool operator == (const socket_address_inet& rhs) const;
bool operator < (const socket_address_inet& rhs) const;
private:
struct sockaddr_in m_sockaddr;
};
class socket_address_inet6 {
public:
bool is_any() const { return is_port_any() && is_address_any(); }
bool is_valid() const { return !is_port_any() && !is_address_any(); }
bool is_port_any() const { return port() == 0; }
bool is_address_any() const { return std::memcmp(&m_sockaddr.sin6_addr, &in6addr_any, sizeof(in6_addr)) == 0; }
void clear() { std::memset(this, 0, sizeof(socket_address_inet6)); set_family(); }
uint16_t port() const { return ntohs(m_sockaddr.sin6_port); }
uint16_t port_n() const { return m_sockaddr.sin6_port; }
void set_port(uint16_t p) { m_sockaddr.sin6_port = htons(p); }
void set_port_n(uint16_t p) { m_sockaddr.sin6_port = p; }
in6_addr address() const { return m_sockaddr.sin6_addr; }
const in6_addr* address_ptr() const { return &m_sockaddr.sin6_addr; }
std::string address_str() const;
bool address_c_str(char* buf, socklen_t size) const;
void set_address(in6_addr a) { m_sockaddr.sin6_addr = a; }
bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
bool set_address_c_str(const char* a);
void set_address_any() { set_port(0); set_address(in6addr_any); }
std::string pretty_address_str() const;
sa_family_t family() const { return m_sockaddr.sin6_family; }
void set_family() { m_sockaddr.sin6_family = AF_INET6; }
sockaddr* c_sockaddr() { return reinterpret_cast<sockaddr*>(&m_sockaddr); }
sockaddr_in6* c_sockaddr_inet6() { return &m_sockaddr; }
const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
const sockaddr_in6* c_sockaddr_inet6() const { return &m_sockaddr; }
socket_address normalize_address() const;
bool operator == (const socket_address_inet6& rhs) const;
bool operator < (const socket_address_inet6& rhs) const;
private:
struct sockaddr_in6 m_sockaddr;
};
inline bool
socket_address::is_any() const {
switch (family()) {
case af_inet:
return sa_inet()->is_any();
case af_inet6:
return sa_inet6()->is_any();
default:
return false;
}
}
inline bool
socket_address::is_valid() const {
switch (family()) {
case af_inet:
return sa_inet()->is_valid();
case af_inet6:
return sa_inet6()->is_valid();
default:
return false;
}
}
inline bool
socket_address::is_bindable() const {
switch (family()) {
case af_inet:
return !sa_inet()->is_address_any();
case af_inet6:
return !sa_inet6()->is_address_any();
default:
return false;
}
}
inline bool
socket_address::is_address_any() const {
switch (family()) {
case af_inet:
return sa_inet()->is_address_any();
case af_inet6:
return sa_inet6()->is_address_any();
default:
return true;
}
}
inline uint16_t
socket_address::port() const {
switch (family()) {
case af_inet:
return sa_inet()->port();
case af_inet6:
return sa_inet6()->port();
default:
return 0;
}
}
inline void
socket_address::set_port(uint16_t p) {
switch (family()) {
case af_inet:
return sa_inet()->set_port(p);
case af_inet6:
return sa_inet6()->set_port(p);
default:
break;
}
}
inline std::string
socket_address::address_str() const {
switch (family()) {
case af_inet:
return sa_inet()->address_str();
case af_inet6:
return sa_inet6()->address_str();
default:
return std::string();
}
}
inline bool
socket_address::address_c_str(char* buf, socklen_t size) const {
switch (family()) {
case af_inet:
return sa_inet()->address_c_str(buf, size);
case af_inet6:
return sa_inet6()->address_c_str(buf, size);
default:
return false;
}
}
inline std::string
socket_address::pretty_address_str() const {
switch (family()) {
case af_inet:
return sa_inet()->address_str();
case af_inet6:
return sa_inet6()->pretty_address_str();
case af_unspec:
return std::string("unspec");
default:
return std::string("invalid");
}
}
inline bool
socket_address::set_address_c_str(const char* a) {
if (sa_inet()->set_address_c_str(a)) {
sa_inet()->set_family();
return true;
} else if (sa_inet6()->set_address_c_str(a)) {
sa_inet6()->set_family();
return true;
} else {
return false;
}
}
// Is the zero length really needed, should we require some length?
inline uint32_t
socket_address::length() const {
switch(family()) {
case af_inet:
return sizeof(sockaddr_in);
case af_inet6:
return sizeof(sockaddr_in6);
default:
return 0;
}
}
inline void
socket_address::copy(const socket_address& src, size_t length) {
length = std::min(length, sizeof(socket_address));
std::memset(this, 0, sizeof(socket_address));
std::memcpy(this, &src, 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());
}
inline bool
socket_address::operator == (const socket_address& rhs) const {
if (family() != rhs.family())
return false;
switch (family()) {
case af_inet:
return *sa_inet() == *rhs.sa_inet();
case af_inet6:
return *sa_inet6() == *rhs.sa_inet6();
default:
throw std::logic_error("socket_address::operator == (rhs) invalid type comparison.");
}
}
inline bool
socket_address::operator < (const socket_address& rhs) const {
if (family() != rhs.family())
return family() < rhs.family();
switch (family()) {
case af_inet:
return *sa_inet() < *rhs.sa_inet();
case af_inet6:
return *sa_inet6() < *rhs.sa_inet6();
default:
throw std::logic_error("socket_address::operator < (rhs) invalid type comparison.");
}
}
inline std::string
socket_address_inet::address_str() const {
char buf[INET_ADDRSTRLEN];
if (!address_c_str(buf, INET_ADDRSTRLEN))
return std::string();
return std::string(buf);
}
inline bool
socket_address_inet::address_c_str(char* buf, socklen_t size) const {
return inet_ntop(family(), &m_sockaddr.sin_addr, buf, size);
}
inline bool
socket_address_inet::set_address_c_str(const char* a) {
return inet_pton(AF_INET, a, &m_sockaddr.sin_addr);
}
inline socket_address_inet6
socket_address_inet::to_mapped_address() const {
uint32_t addr32[4];
addr32[0] = 0;
addr32[1] = 0;
addr32[2] = htonl(0xffff);
addr32[3] = m_sockaddr.sin_addr.s_addr;
socket_address_inet6 sa;
sa.clear();
sa.set_address(*reinterpret_cast<in6_addr *>(addr32));
sa.set_port_n(m_sockaddr.sin_port);
return sa;
}
inline bool
socket_address_inet::operator == (const socket_address_inet& rhs) const {
return
m_sockaddr.sin_addr.s_addr == rhs.m_sockaddr.sin_addr.s_addr &&
m_sockaddr.sin_port == rhs.m_sockaddr.sin_port;
}
inline bool
socket_address_inet::operator < (const socket_address_inet& rhs) const {
return
m_sockaddr.sin_addr.s_addr < rhs.m_sockaddr.sin_addr.s_addr ||
(m_sockaddr.sin_addr.s_addr == rhs.m_sockaddr.sin_addr.s_addr &&
m_sockaddr.sin_port < rhs.m_sockaddr.sin_port);
}
inline std::string
socket_address_inet6::address_str() const {
char buf[INET6_ADDRSTRLEN];
if (!address_c_str(buf, INET6_ADDRSTRLEN))
return std::string();
return std::string(buf);
}
inline bool
socket_address_inet6::address_c_str(char* buf, socklen_t size) const {
return inet_ntop(family(), &m_sockaddr.sin6_addr, buf, size);
}
inline bool
socket_address_inet6::set_address_c_str(const char* a) {
return inet_pton(AF_INET6, a, &m_sockaddr.sin6_addr);
}
inline std::string
socket_address_inet6::pretty_address_str() const {
char buf[INET6_ADDRSTRLEN + 2 + 6];
if (inet_ntop(family(), &m_sockaddr.sin6_addr, buf + 1, INET6_ADDRSTRLEN) == NULL)
return std::string();
buf[0] = '[';
char* last_char = (char*)std::memchr(buf + 1, 0, INET6_ADDRSTRLEN);
// TODO: Throw exception here.
if (last_char == NULL || last_char >= buf + 1 + INET6_ADDRSTRLEN)
throw std::logic_error("inet_ntop for inet6 returned bad buffer");
*(last_char++) = ']';
if (!is_port_any()) {
if (snprintf(last_char, 7, ":%" PRIu16, port()) == -1)
return std::string("error"); // TODO: Throw here.
} else {
*last_char = '\0';
}
return std::string(buf);
}
inline socket_address
socket_address_inet6::normalize_address() const {
const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(m_sockaddr.sin6_addr.s6_addr);
if (addr32[0] == 0 && addr32[1] == 0 && addr32[2] == htonl(0xffff)) {
socket_address addr4;
addr4.sa_inet()->set_family();
addr4.sa_inet()->set_address_n(addr32[3]);
addr4.sa_inet()->set_port_n(m_sockaddr.sin6_port);
return addr4;
}
return *reinterpret_cast<const socket_address*>(this);
}
inline bool
socket_address_inet6::operator == (const socket_address_inet6& rhs) const {
return
memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr)) == 0 &&
m_sockaddr.sin6_port == rhs.m_sockaddr.sin6_port;
}
inline bool
socket_address_inet6::operator < (const socket_address_inet6& rhs) const {
int addr_comp = memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr));
return
addr_comp < 0 ||
(addr_comp == 0 ||
m_sockaddr.sin6_port < rhs.m_sockaddr.sin6_port);
}
}
#endif
+5 -7
View File
@@ -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
@@ -143,8 +141,8 @@ public:
return *this;
}
bool operator == (__UNUSED const split_iterator_t& itr) const { return m_pos == m_seq->end(); }
bool operator != (__UNUSED const split_iterator_t& itr) const { return m_pos != m_seq->end(); }
bool operator == (const split_iterator_t&) const { return m_pos == m_seq->end(); }
bool operator != (const split_iterator_t&) const { return m_pos != m_seq->end(); }
private:
const Sequence* m_seq;
@@ -161,7 +159,7 @@ split_iterator(const Sequence& seq, typename Sequence::value_type delim) {
template <typename Sequence>
inline split_iterator_t<Sequence>
split_iterator(__UNUSED const Sequence& seq) {
split_iterator(const Sequence&) {
return split_iterator_t<Sequence>();
}
-110
View File
@@ -1,110 +0,0 @@
// libTorrent - BitTorrent library
// 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_TIMER_H
#define RAK_TIMER_H
#include <limits>
#include <cinttypes>
#include <sys/time.h>
namespace rak {
// Don't convert negative Timer to timeval and then back to Timer, that will bork.
class timer {
public:
timer(int64_t usec = 0) : m_time(usec) {}
timer(timeval tv) : m_time((int64_t)(uint32_t)tv.tv_sec * 1000000 + (int64_t)(uint32_t)tv.tv_usec % 1000000) {}
bool is_zero() const { return m_time == 0; }
bool is_not_zero() const { return m_time != 0; }
int32_t seconds() const { return m_time / 1000000; }
int32_t seconds_ceiling() const { return (m_time + 1000000 - 1) / 1000000; }
int64_t usec() const { return m_time; }
timer round_seconds() const { return (m_time / 1000000) * 1000000; }
timer round_seconds_ceiling() const { return ((m_time + 1000000 - 1) / 1000000) * 1000000; }
timeval tval() const {
timeval val;
val.tv_sec = m_time / 1000000;
val.tv_usec = m_time % 1000000;
return val;
}
static timer current();
static int64_t current_seconds() { return current().seconds(); }
static int64_t current_usec() { return current().usec(); }
static timer from_minutes(uint32_t minutes) { return rak::timer((uint64_t)minutes * 60 * 1000000); }
static timer from_seconds(uint32_t seconds) { return rak::timer((uint64_t)seconds * 1000000); }
static timer from_milliseconds(uint32_t msec) { return rak::timer((uint64_t)msec * 1000); }
static timer max() { return std::numeric_limits<int64_t>::max(); }
bool operator < (const timer& t) const { return m_time < t.m_time; }
bool operator > (const timer& t) const { return m_time > t.m_time; }
bool operator <= (const timer& t) const { return m_time <= t.m_time; }
bool operator >= (const timer& t) const { return m_time >= t.m_time; }
bool operator == (const timer& t) const { return m_time == t.m_time; }
bool operator != (const timer& t) const { return m_time != t.m_time; }
timer operator - (const timer& t) const { return timer(m_time - t.m_time); }
timer operator + (const timer& t) const { return timer(m_time + t.m_time); }
timer operator * (int64_t t) const { return timer(m_time * t); }
timer operator / (int64_t t) const { return timer(m_time / t); }
timer operator -= (int64_t t) { m_time -= t; return *this; }
timer operator -= (const timer& t) { m_time -= t.m_time; return *this; }
timer operator += (int64_t t) { m_time += t; return *this; }
timer operator += (const timer& t) { m_time += t.m_time; return *this; }
private:
int64_t m_time;
};
inline timer
timer::current() {
timeval t;
gettimeofday(&t, 0);
return timer(t);
}
}
#endif
+2 -4
View File
@@ -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
-42
View File
@@ -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
-19
View File
@@ -107,25 +107,6 @@ AC_DEFUN([CC_ATTRIBUTE_NONNULL], [
fi
])
AC_DEFUN([CC_ATTRIBUTE_UNUSED], [
AC_CACHE_CHECK([if compiler supports __attribute__((unused))],
[cc_cv_attribute_unused],
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void some_function(void *foo, __attribute__((unused)) void *bar);
])],
[cc_cv_attribute_unused=yes],
[cc_cv_attribute_unused=no])
])
if test "x$cc_cv_attribute_unused" = "xyes"; then
AC_DEFINE([SUPPORT_ATTRIBUTE_UNUSED], 1, [Define this if the compiler supports the unused attribute])
$1
else
true
$2
fi
])
AC_DEFUN([CC_FUNC_EXPECT], [
AC_CACHE_CHECK([if compiler has __builtin_expect function],
[cc_cv_func_expect],
+1 -166
View File
@@ -88,49 +88,11 @@ AC_DEFUN([TORRENT_CHECK_KQUEUE], [
[
AC_DEFINE(USE_KQUEUE, 1, Use kqueue.)
AC_MSG_RESULT(yes)
TORRENT_CHECK_KQUEUE_SOCKET_ONLY
], [
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_CHECK_KQUEUE_SOCKET_ONLY], [
AC_MSG_CHECKING(whether kqueue supports pipes and ptys)
AC_LINK_IFELSE([AC_LANG_SOURCE([
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/event.h>
#include <sys/time.h>
int main() {
struct kevent ev@<:@2@:>@, ev_out@<:@2@:>@;
struct timespec ts = { 0, 0 };
int pfd@<:@2@:>@, pty@<:@2@:>@, kfd, n;
char buffer@<:@9001@:>@;
if (pipe(pfd) == -1) return 1;
if (fcntl(pfd@<:@1@:>@, F_SETFL, O_NONBLOCK) == -1) return 2;
while ((n = write(pfd@<:@1@:>@, buffer, sizeof(buffer))) == sizeof(buffer));
if ((pty@<:@0@:>@=posix_openpt(O_RDWR | O_NOCTTY)) == -1) return 3;
if ((pty@<:@1@:>@=grantpt(pty@<:@0@:>@)) == -1) return 4;
EV_SET(ev+0, pfd@<:@1@:>@, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, NULL);
EV_SET(ev+1, pty@<:@1@:>@, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, NULL);
if ((kfd = kqueue()) == -1) return 5;
if ((n = kevent(kfd, ev, 2, NULL, 0, NULL)) == -1) return 6;
if (ev_out@<:@0@:>@.flags & EV_ERROR) return 7;
if (ev_out@<:@1@:>@.flags & EV_ERROR) return 8;
read(pfd@<:@0@:>@, buffer, sizeof(buffer));
if ((n = kevent(kfd, NULL, 0, ev_out, 2, &ts)) < 1) return 9;
return 0;
}
])],
[
AC_MSG_RESULT(yes)
], [
AC_DEFINE(KQUEUE_SOCKET_ONLY, 1, kqueue only supports sockets.)
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_WITH_KQUEUE], [
AC_ARG_WITH(kqueue,
@@ -156,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)
@@ -208,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]]]),
@@ -450,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
+18 -7
View File
@@ -23,13 +23,14 @@ 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="$2"
else
result=`echo "${values_to_check}" | $GREP -Fvx -- "${unwanted_values}" | $GREP -v '^$'`
$1=${result//$'\n'/ }
$1=$(echo "$result" | tr -d '\n')
fi
])
@@ -117,7 +118,7 @@ AC_DEFUN([TORRENT_CHECK_MADVISE], [
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <sys/types.h>
#include <sys/mman.h>
void f() { static char test@<:@1024@:>@; madvise((void *)test, sizeof(test), MADV_NORMAL); }
void f() { static char test@<:@1024@:>@; madvise((void *)test, sizeof(test), MADV_NORMAL); }
])],
[
AC_MSG_RESULT(yes)
@@ -127,6 +128,21 @@ AC_DEFUN([TORRENT_CHECK_MADVISE], [
])
])
AC_DEFUN([TORRENT_CHECK_POSIX_FADVISE], [
AC_MSG_CHECKING(for posix_fadvise)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <fcntl.h>
void f() { posix_fadvise(0, 0, 0, POSIX_FADV_RANDOM); }
])],
[
AC_MSG_RESULT(yes)
AC_DEFINE(USE_POSIX_FADVISE, 1, Use posix_fadvise)
], [
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_CHECK_POPCOUNT], [
AC_MSG_CHECKING(for __builtin_popcount)
@@ -152,17 +168,12 @@ AC_DEFUN([TORRENT_CHECK_CACHELINE], [
])],
[
AC_MSG_RESULT(found builtin)
dnl AC_DEFINE(LT_SMP_CACHE_BYTES, SMP_CACHE_BYTES, Largest L1 cache size we know of, should work on all archs.)
dnl AC_DEFINE(lt_cacheline_aligned, __cacheline_aligned, LibTorrent defined cacheline aligned.)
dnl Need to fix this so that it uses the stuff defined by the system.
AC_DEFINE(LT_SMP_CACHE_BYTES, 128, Largest L1 cache size we know of should work on all archs.)
AC_DEFINE(lt_cacheline_aligned, __attribute__((__aligned__(LT_SMP_CACHE_BYTES))), LibTorrent defined cacheline aligned.)
], [
AC_MSG_RESULT(using default 128 bytes)
AC_DEFINE(LT_SMP_CACHE_BYTES, 128, Largest L1 cache size we know of should work on all archs.)
AC_DEFINE(lt_cacheline_aligned, __attribute__((__aligned__(LT_SMP_CACHE_BYTES))), LibTorrent defined cacheline aligned.)
])
])
+1 -12
View File
@@ -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,15 +13,12 @@ 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 \
core/http_queue.h \
core/manager.cc \
core/manager.h \
core/poll_manager.cc \
core/poll_manager.h \
core/range_map.h \
core/view.cc \
core/view.h \
@@ -200,10 +191,8 @@ libsub_root_a_SOURCES = \
option_parser.h \
signal_handler.cc \
signal_handler.h \
thread_base.cc \
thread_base.h \
thread_worker.cc \
thread_worker.h
AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir)
AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir) -DPACKAGE_DATADIR=\"$(pkgdatadir)\"
+52 -54
View File
@@ -1,19 +1,16 @@
#include "config.h"
#include <cassert>
#include <cstdio>
#include <functional>
#include <netdb.h>
#include <unistd.h>
#include <rak/file_stat.h>
#include <rak/error_number.h>
#include <rak/path.h>
#include <rak/socket_address.h>
#include <rak/string_manip.h>
#include <rak/regex.h>
#include <torrent/rate.h>
#include <torrent/throttle.h>
#include <torrent/tracker_controller.h>
#include <torrent/tracker_list.h>
#include <torrent/tracker/tracker.h>
#include <torrent/connection_manager.h>
#include <torrent/data/download_data.h>
@@ -105,22 +102,19 @@ apply_d_change_link(core::Download* download, const torrent::Object::list_type&
switch (changeType) {
case 0:
if (symlink(target.c_str(), link.c_str()) == -1){
lt_log_print(torrent::LOG_TORRENT_WARN, "create_link failed: %s",
rak::error_number::current().c_str());
}
if (symlink(target.c_str(), link.c_str()) == -1)
lt_log_print(torrent::LOG_TORRENT_WARN, "create_link failed: %s", std::strerror(errno));
break;
case 1:
{
rak::file_stat fileStat;
rak::error_number::clear_global();
errno = 0;
if (!fileStat.update_link(link) || !fileStat.is_link() || unlink(link.c_str()) == -1)
lt_log_print(torrent::LOG_TORRENT_WARN, "delete_link failed: %s", std::strerror(errno));
if (!fileStat.update_link(link) || !fileStat.is_link() ||
unlink(link.c_str()) == -1){
lt_log_print(torrent::LOG_TORRENT_WARN, "delete_link failed: %s",
rak::error_number::current().c_str());
}
break;
}
default:
@@ -138,7 +132,7 @@ apply_d_delete_tied(core::Download* download) {
return torrent::Object();
if (::unlink(rak::path_expand(tie).c_str()) == -1)
control->core()->push_log_std("Could not unlink tied file: " + std::string(rak::error_number::current().c_str()));
control->core()->push_log_std("Could not unlink tied file: " + std::string(std::strerror(errno)));
rpc::call_command("d.tied_to_file.set", std::string(), rpc::make_target(download));
return torrent::Object();
@@ -266,12 +260,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;
}
@@ -308,8 +302,10 @@ apply_d_add_peer(core::Download* download, const std::string& arg) {
if (port < 1 || port > 65535)
throw torrent::input_error("Invalid port number.");
assert(std::this_thread::get_id() == torrent::main_thread::thread()->thread_id());
// Currently discarding SOCK_STREAM.
torrent::main_thread()->resolver()->resolve_preferred(NULL, host, AF_UNSPEC, AF_INET, [download, port](torrent::c_sa_shared_ptr sa, int err) {
torrent::this_thread::resolver()->resolve_preferred(NULL, host, AF_UNSPEC, AF_INET, [download, port](torrent::c_sa_shared_ptr sa, int err) {
if (sa == nullptr) {
lt_log_print(torrent::LOG_TORRENT_WARN, "could not resolve hostname for added peer: %s", gai_strerror(err));
return;
@@ -352,25 +348,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);
}
}
@@ -387,21 +381,24 @@ t_multicall(core::Download* download, 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.
torrent::Object resultRaw = torrent::Object::create_list();
torrent::Object::list_type& result = resultRaw.as_list();
torrent::Object result_raw = torrent::Object::create_list();
torrent::Object::list_type& result = result_raw.as_list();
for (int itr = 0, last = download->tracker_list()->size(); itr != last; itr++) {
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
for (uint32_t idx = 0, last = download->tracker_list_size(); idx < last; idx++) {
auto& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
auto tracker = download->tracker_controller().at(idx);
if (!tracker.is_valid())
continue;
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string();
auto t = download->tracker_list()->at(itr);
row.push_back(rpc::parse_command(rpc::make_target(&t), cmd.c_str(), cmd.c_str() + cmd.size()).first);
row.push_back(rpc::parse_command(rpc::make_target(&tracker), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
return resultRaw;
return result_raw;
}
torrent::Object
@@ -417,14 +414,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);
}
}
@@ -482,7 +478,8 @@ download_tracker_insert(core::Download* download, const torrent::Object::list_ty
if (group < 0 || group > 32)
throw torrent::input_error("Tracker group number invalid.");
download->download()->tracker_list()->insert_url(group, args.back().as_string(), true);
download->tracker_controller().add_extra_tracker(group, args.back().as_string());
return torrent::Object();
}
@@ -542,19 +539,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();
}
@@ -564,7 +562,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
@@ -586,7 +584,7 @@ d_list_remove(core::Download* download, const torrent::Object& rawArgs, const ch
#define CMD2_BIND_CL std::bind(&core::Download::connection_list, std::placeholders::_1)
#define CMD2_BIND_FL std::bind(&core::Download::file_list, std::placeholders::_1)
#define CMD2_BIND_PL std::bind(&core::Download::c_peer_list, std::placeholders::_1)
#define CMD2_BIND_TL std::bind(&core::Download::tracker_list, std::placeholders::_1)
#define CMD2_BIND_TC std::bind(&core::Download::tracker_controller, std::placeholders::_1)
#define CMD2_BIND_INFO std::bind(&core::Download::info, std::placeholders::_1)
#define CMD2_BIND_DATA std::bind(&core::Download::data, std::placeholders::_1)
@@ -771,8 +769,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.
@@ -833,15 +831,15 @@ initialize_command_download() {
CMD2_DL_V ("d.tracker_announce", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, false));
CMD2_DL_V ("d.tracker_announce.force", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, true));
CMD2_DL ("d.tracker_numwant", std::bind(&torrent::TrackerList::numwant, CMD2_BIND_TL));
CMD2_DL_VALUE_V ("d.tracker_numwant.set", std::bind(&torrent::TrackerList::set_numwant, CMD2_BIND_TL, std::placeholders::_2));
CMD2_DL ("d.tracker_numwant", std::bind(&torrent::tracker::TrackerControllerWrapper::numwant, CMD2_BIND_TC));
CMD2_DL_VALUE_V ("d.tracker_numwant.set", std::bind(&torrent::tracker::TrackerControllerWrapper::set_numwant, CMD2_BIND_TC, std::placeholders::_2));
// TODO: Deprecate 'd.tracker_focus'.
CMD2_DL ("d.tracker_focus", std::bind(&core::Download::tracker_list_size, std::placeholders::_1));
CMD2_DL ("d.tracker_size", std::bind(&core::Download::tracker_list_size, std::placeholders::_1));
CMD2_DL ("d.tracker.has_active", std::bind(&torrent::TrackerList::has_active, CMD2_BIND_TL));
CMD2_DL ("d.tracker.has_active_not_scrape", std::bind(&torrent::TrackerList::has_active_not_scrape, CMD2_BIND_TL));
CMD2_DL ("d.tracker.has_usable", std::bind(&torrent::TrackerList::has_usable, CMD2_BIND_TL));
CMD2_DL ("d.tracker.has_active", std::bind(&torrent::tracker::TrackerControllerWrapper::has_active_trackers, CMD2_BIND_TC));
CMD2_DL ("d.tracker.has_active_not_scrape", std::bind(&torrent::tracker::TrackerControllerWrapper::has_active_trackers_not_scrape, CMD2_BIND_TC));
CMD2_DL ("d.tracker.has_usable", std::bind(&torrent::tracker::TrackerControllerWrapper::has_usable_trackers, CMD2_BIND_TC));
CMD2_DL_LIST ("d.tracker.insert", std::bind(&download_tracker_insert, std::placeholders::_1, std::placeholders::_2));
CMD2_DL_VALUE_V ("d.tracker.send_scrape", [](auto download, uint64_t arg) { download->tracker_controller().scrape_request(arg); });
+10 -47
View File
@@ -1,39 +1,3 @@
// 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
#include "config.h"
#include <algorithm>
@@ -61,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");
}
@@ -416,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;
}
@@ -443,12 +405,13 @@ cmd_catch(rpc::target_type target, const torrent::Object& args) {
void
initialize_command_dynamic() {
// clang-format off
#ifdef HAVE_XMLRPC_TINYXML2
#ifdef HAVE_XMLRPC_TINYXML2
CMD2_ANY ("system.listMethods", std::bind(&system_listMethods)); // only used by tinyxml2
#endif
#endif
CMD2_VAR_BOOL ("method.use_deprecated", true);
CMD2_VAR_VALUE ("method.use_intermediate", 1);
// Keep these for future use when we deprecate more commands.
CMD2_VAR_BOOL ("method.use_deprecated", false);
CMD2_VAR_VALUE ("method.use_intermediate", 3);
CMD2_ANY_LIST ("method.insert", std::bind(&system_method_insert, std::placeholders::_2));
CMD2_ANY_LIST ("method.insert.value", std::bind(&system_method_insert_object, std::placeholders::_2, rpc::object_storage::flag_value_type));
+62 -78
View File
@@ -11,6 +11,9 @@
#include <torrent/utils/log.h>
#include <torrent/utils/directory_events.h>
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
#include "core/download.h"
#include "core/download_list.h"
#include "core/manager.h"
@@ -19,75 +22,56 @@
#include "rpc/parse.h"
#include "rpc/parse_commands.h"
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
#include "thread_worker.h"
torrent::Object
apply_on_ratio(const torrent::Object& rawArgs) {
const std::string& groupName = rawArgs.as_string();
auto& group_name = rawArgs.as_string();
auto view_itr = control->view_manager()->find(rpc::commands.call("group." + group_name + ".view", rpc::make_target()).as_string());
char buffer[32 + groupName.size()];
snprintf(buffer, sizeof(buffer), "group2.%s.view", groupName.c_str());
core::ViewManager::iterator viewItr = control->view_manager()->find(rpc::commands.call(buffer, rpc::make_target()).as_string());
if (viewItr == control->view_manager()->end())
if (view_itr == control->view_manager()->end())
throw torrent::input_error("Could not find view.");
char* bufferStart = buffer + snprintf(buffer, sizeof(buffer), "group2.%s.ratio.", groupName.c_str());
// first argument: minimum ratio to reach
// second argument: minimum upload amount to reach [optional]
// third argument: maximum ratio to reach [optional]
std::strcpy(bufferStart, "min");
int64_t minRatio = rpc::commands.call(buffer, rpc::make_target()).as_value();
std::strcpy(bufferStart, "max");
int64_t maxRatio = rpc::commands.call(buffer, rpc::make_target()).as_value();
std::strcpy(bufferStart, "upload");
int64_t minUpload = rpc::commands.call(buffer, rpc::make_target()).as_value();
int64_t min_ratio = rpc::commands.call("group." + group_name + ".ratio.min", rpc::make_target()).as_value();
int64_t max_ratio = rpc::commands.call("group." + group_name + ".ratio.max", rpc::make_target()).as_value();
int64_t min_upload = rpc::commands.call("group." + group_name + ".ratio.upload", rpc::make_target()).as_value();
std::vector<core::Download*> downloads;
for (core::View::iterator itr = (*viewItr)->begin_visible(), last = (*viewItr)->end_visible(); itr != last; itr++) {
for (auto itr = (*view_itr)->begin_visible(), last = (*view_itr)->end_visible(); itr != last; itr++) {
if (!(*itr)->is_seeding() || rpc::call_command_value("d.ignore_commands", rpc::make_target(*itr)) != 0)
continue;
// rpc::parse_command_single(rpc::make_target(*itr), "print={Checked ratio of download.}");
int64_t total_done = (*itr)->download()->bytes_done();
int64_t total_upload = (*itr)->info()->up_rate()->total();
int64_t totalDone = (*itr)->download()->bytes_done();
int64_t totalUpload = (*itr)->info()->up_rate()->total();
if (!(totalUpload >= minUpload && totalUpload * 100 >= totalDone * minRatio) &&
!(maxRatio > 0 && totalUpload * 100 > totalDone * maxRatio))
if (!(total_upload >= min_upload && total_upload * 100 >= total_done * min_ratio) &&
!(max_ratio > 0 && total_upload * 100 > total_done * max_ratio))
continue;
downloads.push_back(*itr);
}
snprintf(buffer, sizeof(buffer), "group.%s.ratio.command", groupName.c_str());
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("print", rpc::make_target(*itr), "Calling ratio command.");
rpc::commands.call_catch(buffer, 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 (core::DownloadList::iterator 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& tiedToFile = 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 (!tiedToFile.empty() && fs.update(rak::path_expand(tiedToFile)))
rpc::parse_command_single(rpc::make_target(*itr), "d.try_start=");
if (!tied_to_file.empty() && fs.update(rak::path_expand(tied_to_file)))
rpc::parse_command_single(rpc::make_target(download), "d.try_start=");
}
return torrent::Object();
@@ -95,15 +79,15 @@ apply_start_tied() {
torrent::Object
apply_stop_untied() {
for (core::DownloadList::iterator 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& tiedToFile = 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 (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)))
rpc::parse_command_single(rpc::make_target(*itr), "d.try_stop=");
if (!tied_to_file.empty() && !fs.update(rak::path_expand(tied_to_file)))
rpc::parse_command_single(rpc::make_target(download), "d.try_stop=");
}
return torrent::Object();
@@ -111,12 +95,12 @@ apply_stop_untied() {
torrent::Object
apply_close_untied() {
for (core::DownloadList::iterator 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& tiedToFile = 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 && !tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)))
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();
@@ -124,11 +108,11 @@ apply_close_untied() {
torrent::Object
apply_remove_untied() {
for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ) {
for (auto itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ) {
rak::file_stat fs;
const std::string& tiedToFile = 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(*itr));
if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile))) {
if (!tied_to_file.empty() && !fs.update(rak::path_expand(tied_to_file))) {
// Need to clear tied_to_file so it doesn't try to delete it.
rpc::call_command("d.tied_to_file.set", std::string(), rpc::make_target(*itr));
@@ -149,9 +133,9 @@ apply_schedule(const torrent::Object::list_type& args) {
torrent::Object::list_const_iterator itr = args.begin();
const std::string& arg1 = (itr++)->as_string();
const std::string& arg2 = (itr++)->as_string();
const std::string& arg3 = (itr++)->as_string();
auto& arg1 = (itr++)->as_string();
auto& arg2 = (itr++)->as_string();
auto& arg3 = (itr++)->as_string();
control->command_scheduler()->parse(arg1, arg2, arg3, *itr);
@@ -165,7 +149,7 @@ apply_load(const torrent::Object::list_type& args, int flags) {
if (argsItr == args.end())
throw torrent::input_error("Too few arguments.");
const std::string& filename = argsItr->as_string();
auto& filename = argsItr->as_string();
core::Manager::command_list_type commands;
while (++argsItr != args.end())
@@ -210,20 +194,20 @@ apply_download_list(const torrent::Object::list_type& args) {
torrent::Object::list_const_iterator argsItr = args.begin();
core::ViewManager* viewManager = control->view_manager();
core::ViewManager::iterator viewItr;
core::ViewManager::iterator view_itr;
if (argsItr != args.end() && !argsItr->as_string().empty())
viewItr = viewManager->find((argsItr++)->as_string());
view_itr = viewManager->find((argsItr++)->as_string());
else
viewItr = viewManager->find("default");
view_itr = viewManager->find("default");
if (viewItr == viewManager->end())
if (view_itr == viewManager->end())
throw torrent::input_error("Could not find view.");
torrent::Object result = torrent::Object::create_list();
torrent::Object::list_type& resultList = result.as_list();
for (core::View::const_iterator itr = (*viewItr)->begin_visible(), last = (*viewItr)->end_visible(); itr != last; itr++) {
for (core::View::const_iterator itr = (*view_itr)->begin_visible(), last = (*view_itr)->end_visible(); itr != last; itr++) {
const torrent::HashString* hashString = &(*itr)->info()->hash();
resultList.push_back(rak::transform_hex(hashString->begin(), hashString->end()));
@@ -238,32 +222,29 @@ d_multicall(const torrent::Object::list_type& args) {
throw torrent::input_error("Too few arguments.");
core::ViewManager* viewManager = control->view_manager();
core::ViewManager::iterator viewItr;
core::ViewManager::iterator view_itr;
if (!args.front().as_string().empty())
viewItr = viewManager->find(args.front().as_string());
view_itr = viewManager->find(args.front().as_string());
else
viewItr = viewManager->find("default");
view_itr = viewManager->find("default");
if (viewItr == viewManager->end())
if (view_itr == viewManager->end())
throw torrent::input_error("Could not find view.");
// Add some pre-parsing of the commands, so we don't spend time
// parsing and searching command map for every single call.
unsigned int dlist_size = (*viewItr)->size_visible();
core::Download* dlist[dlist_size];
std::copy((*viewItr)->begin_visible(), (*viewItr)->end_visible(), dlist);
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();
for (core::Download** vItr = dlist; vItr != dlist + dlist_size; vItr++) {
for (auto download : dlist) {
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(*vItr), cmd.c_str(), cmd.c_str() + cmd.size()).first);
auto& cmd = cItr->as_string();
row.push_back(rpc::parse_command(rpc::make_target(download), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
@@ -278,28 +259,28 @@ d_multicall_filtered(const torrent::Object::list_type& args) {
// Find the given view
core::ViewManager* viewManager = control->view_manager();
core::ViewManager::iterator viewItr = viewManager->find(arg->as_string().empty() ? "default" : arg->as_string());
core::ViewManager::iterator view_itr = viewManager->find(arg->as_string().empty() ? "default" : arg->as_string());
if (viewItr == viewManager->end())
if (view_itr == viewManager->end())
throw torrent::input_error("Could not find view '" + arg->as_string() + "'.");
// Make a filtered copy of the current item list
core::View::base_type dlist;
(*viewItr)->filter_by(*++arg, dlist);
(*view_itr)->filter_by(*++arg, dlist);
// Generate result by iterating over all items
torrent::Object resultRaw = torrent::Object::create_list();
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++) {
const std::string& cmdstr = command->as_string();
row.push_back(rpc::parse_command(rpc::make_target(*item), cmdstr.c_str(), cmdstr.c_str() + cmdstr.size()).first);
auto& cmdstr = command->as_string();
row.push_back(rpc::parse_command(rpc::make_target(item), cmdstr.c_str(), cmdstr.c_str() + cmdstr.size()).first);
}
}
@@ -316,8 +297,8 @@ directory_watch_added(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Too few arguments.");
const std::string& path = args.front().as_string();
const std::string& command = args.back().as_string();
auto& path = args.front().as_string();
auto& command = args.back().as_string();
if (!control->directory_events()->open())
throw torrent::input_error("Could not open inotify:" + std::string(rak::error_number::current().c_str()));
@@ -337,7 +318,10 @@ initialize_command_events() {
CMD2_ANY ("close_untied", std::bind(&apply_close_untied));
CMD2_ANY ("remove_untied", std::bind(&apply_remove_untied));
// TODO: Deprecate schedule2 in the future.
CMD2_ANY_LIST ("schedule", std::bind(&apply_schedule, std::placeholders::_2));
CMD2_ANY_LIST ("schedule2", std::bind(&apply_schedule, std::placeholders::_2));
CMD2_ANY_STRING_V("schedule.remove", std::bind(&rpc::CommandScheduler::erase_str, control->command_scheduler(), std::placeholders::_2));
CMD2_ANY_STRING_V("schedule_remove2", std::bind(&rpc::CommandScheduler::erase_str, control->command_scheduler(), std::placeholders::_2));
CMD2_ANY_STRING_V("import", std::bind(&apply_import, std::placeholders::_2));
+5 -7
View File
@@ -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"
@@ -53,7 +51,7 @@ apply_f_set_priority(torrent::File* file, uint32_t value) {
if (value > torrent::PRIORITY_HIGH)
throw torrent::input_error("Invalid value.");
file->set_priority((torrent::priority_t)value);
file->set_priority(static_cast<torrent::priority_enum>(value));
}
// TODO: Redundant.
@@ -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;
}
+1 -2
View File
@@ -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());
+2 -4
View File
@@ -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"
+7 -12
View File
@@ -100,24 +100,19 @@ void initialize_commands();
CMD2_ANY(key, std::bind(&rpc::command_function_call_object, torrent::Object(torrent::raw_string::from_c_str(cmds)), \
std::placeholders::_1, std::placeholders::_2));
#define CMD2_REDIRECT(from_key, to_key) \
#define CMD2_REDIRECT(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_GENERIC(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_GENERIC_NO_EXPORT(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_NO_EXPORT(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_STR(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc;
#define CMD2_REDIRECT_STR_NO_EXPORT(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, 0);
#define CMD2_REDIRECT_FILE(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_file_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_TRACKER(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_tracker_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_GENERIC_STR(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, \
rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_no_target);
#define CMD2_REDIRECT_GENERIC_STR_NO_EXPORT(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, \
rpc::CommandMap::flag_no_target);
//
// Conversion of return types:
+2 -4
View File
@@ -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"
+36 -39
View File
@@ -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;
}
@@ -116,34 +116,22 @@ group_insert(const torrent::Object::list_type& args) {
"schedule_remove2=group." + name + ".ratio"));
rpc::commands.call("method.insert", rpc::create_object_list("group." + name + ".ratio.command", "simple",
"d.try_close= ;d.ignore_commands.set=1"));
rpc::commands.call("method.insert", rpc::create_object_list("group2." + name + ".view", "string", view));
rpc::commands.call("method.insert", rpc::create_object_list("group2." + name + ".ratio.min", "value", (int64_t)200));
rpc::commands.call("method.insert", rpc::create_object_list("group2." + name + ".ratio.max", "value", (int64_t)300));
rpc::commands.call("method.insert", rpc::create_object_list("group2." + name + ".ratio.upload", "value", (int64_t)20 << 20));
rpc::commands.call("method.insert", rpc::create_object_list("group." + name + ".view", "string", view));
rpc::commands.call("method.insert", rpc::create_object_list("group." + name + ".ratio.min", "value", (int64_t)200));
rpc::commands.call("method.insert", rpc::create_object_list("group." + name + ".ratio.max", "value", (int64_t)300));
rpc::commands.call("method.insert", rpc::create_object_list("group." + name + ".ratio.upload", "value", (int64_t)20 << 20));
if (rpc::call_command_value("method.use_intermediate") == 1) {
// Deprecated in 0.7.0:
if (rpc::call_command_value("method.use_intermediate") == 3) {
// Cleaned up in 0.16.1:
CMD2_REDIRECT_GENERIC_STR("group." + name + ".view", "group2." + name + ".view");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".view.set", "group2." + name + ".view.set");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".ratio.min", "group2." + name + ".ratio.min");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".ratio.min.set", "group2." + name + ".ratio.min.set");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".ratio.max", "group2." + name + ".ratio.max");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".ratio.max.set", "group2." + name + ".ratio.max.set");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".ratio.upload", "group2." + name + ".ratio.upload");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".ratio.upload.set", "group2." + name + ".ratio.upload.set");
} if (rpc::call_command_value("method.use_intermediate") == 2) {
// Deprecated in 0.7.0:
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".view", "group2." + name + ".view");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".view.set", "group2." + name + ".view.set");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".ratio.min", "group2." + name + ".ratio.min");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".ratio.min.set", "group2." + name + ".ratio.min.set");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".ratio.max", "group2." + name + ".ratio.max");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".ratio.max.set", "group2." + name + ".ratio.max.set");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".ratio.upload", "group2." + name + ".ratio.upload");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".ratio.upload.set", "group2." + name + ".ratio.upload.set");
CMD2_REDIRECT_STR_NO_EXPORT("group2." + name + ".view", "group." + name + ".view");
CMD2_REDIRECT_STR_NO_EXPORT("group2." + name + ".view.set", "group." + name + ".view.set");
CMD2_REDIRECT_STR_NO_EXPORT("group2." + name + ".ratio.min", "group." + name + ".ratio.min");
CMD2_REDIRECT_STR_NO_EXPORT("group2." + name + ".ratio.min.set", "group." + name + ".ratio.min.set");
CMD2_REDIRECT_STR_NO_EXPORT("group2." + name + ".ratio.max", "group." + name + ".ratio.max");
CMD2_REDIRECT_STR_NO_EXPORT("group2." + name + ".ratio.max.set", "group." + name + ".ratio.max.set");
CMD2_REDIRECT_STR_NO_EXPORT("group2." + name + ".ratio.upload", "group." + name + ".ratio.upload");
CMD2_REDIRECT_STR_NO_EXPORT("group2." + name + ".ratio.upload.set", "group." + name + ".ratio.upload.set");
}
return name;
@@ -220,9 +208,11 @@ initialize_command_local() {
CMD2_VAR_LIST ("file.prioritize_toc.first");
CMD2_VAR_LIST ("file.prioritize_toc.last");
CMD2_ANY ("system.files.advise_random", std::bind(&FM_t::advise_random, fileManager));
CMD2_ANY_VALUE_V ("system.files.advise_random.set", std::bind(&FM_t::set_advise_random, fileManager, std::placeholders::_2));
CMD2_VAR_BOOL ("system.files.session.fdatasync", true);
CMD2_ANY ("system.files.advise_random", std::bind(&FM_t::advise_random, fileManager));
CMD2_ANY_VALUE_V ("system.files.advise_random.set", std::bind(&FM_t::set_advise_random, fileManager, std::placeholders::_2));
CMD2_ANY ("system.files.advise_random.hashing", std::bind(&FM_t::advise_random_hashing, fileManager));
CMD2_ANY_VALUE_V ("system.files.advise_random.hashing.set", std::bind(&FM_t::set_advise_random_hashing, fileManager, std::placeholders::_2));
CMD2_VAR_BOOL ("system.files.session.fdatasync", true);
CMD2_ANY ("system.files.opened_counter", std::bind(&FM_t::files_opened_counter, fileManager));
CMD2_ANY ("system.files.closed_counter", std::bind(&FM_t::files_closed_counter, fileManager));
@@ -230,9 +220,15 @@ initialize_command_local() {
CMD2_ANY_STRING ("system.env", std::bind(&system_env, std::placeholders::_2));
CMD2_ANY ("system.time", std::bind(&rak::timer::seconds, &cachedTime));
CMD2_ANY ("system.time_seconds", std::bind(&rak::timer::current_seconds));
CMD2_ANY ("system.time_usec", std::bind(&rak::timer::current_usec));
CMD2_ANY ("system.time", []([[maybe_unused]] auto t, [[maybe_unused]] auto o) -> torrent::Object {
return torrent::this_thread::cached_seconds().count();
});
CMD2_ANY ("system.time_seconds", []([[maybe_unused]] auto t, [[maybe_unused]] auto o) -> torrent::Object {
return torrent::utils::cast_seconds(torrent::utils::time_since_epoch()).count();
});
CMD2_ANY ("system.time_usec", []([[maybe_unused]] auto t, [[maybe_unused]] auto o) -> torrent::Object {
return torrent::utils::time_since_epoch().count();
});
CMD2_ANY_VALUE_V ("system.umask.set", std::bind(&umask, std::placeholders::_2));
@@ -240,7 +236,7 @@ initialize_command_local() {
CMD2_ANY_V ("system.shutdown.normal", std::bind(&Control::receive_normal_shutdown, control));
CMD2_ANY_V ("system.shutdown.quick", std::bind(&Control::receive_quick_shutdown, control));
CMD2_REDIRECT_GENERIC_NO_EXPORT("system.shutdown", "system.shutdown.normal");
CMD2_REDIRECT_NO_EXPORT("system.shutdown", "system.shutdown.normal");
CMD2_ANY ("system.cwd", std::bind(&system_get_cwd));
CMD2_ANY_STRING ("system.cwd.set", std::bind(&system_set_cwd, std::placeholders::_2));
@@ -271,7 +267,7 @@ initialize_command_local() {
CMD2_ANY ("pieces.stats.total_size", std::bind(&apply_pieces_stats_total_size));
CMD2_ANY ("pieces.hash.queue_size", std::bind(&torrent::hash_queue_size));
CMD2_ANY ("pieces.hash.queue_size", std::bind(&torrent::main_thread::hash_queue_size));
CMD2_VAR_BOOL ("pieces.hash.on_completion", true);
CMD2_VAR_STRING ("directory.default", "./");
@@ -292,9 +288,10 @@ initialize_command_local() {
CMD2_ANY ("lua.execute.str", std::bind(&rpc::execute_lua, lua_engine, std::placeholders::_1, std::placeholders::_2, rpc::LuaEngine::flag_string));
#endif
#define CMD2_EXECUTE(key, flags) \
#define CMD2_EXECUTE(key, flags) \
CMD2_ANY(key, std::bind(&rpc::ExecFile::execute_object, &rpc::execFile, std::placeholders::_2, flags));
CMD2_EXECUTE ("execute", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw);
CMD2_EXECUTE ("execute2", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw);
CMD2_EXECUTE ("execute.throw", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw);
CMD2_EXECUTE ("execute.throw.bg", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw | rpc::ExecFile::flag_background);
+5 -6
View File
@@ -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);
+90 -94
View File
@@ -5,13 +5,15 @@
#include <unistd.h>
#include <rak/address_info.h>
#include <rak/path.h>
#include <torrent/connection_manager.h>
#include <torrent/tracker_list.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/net/network_config.h>
#include <torrent/net/socket_address.h>
#include <torrent/tracker/tracker.h>
#include <torrent/utils/log.h>
#include <torrent/utils/option_strings.h>
@@ -28,18 +30,18 @@
torrent::Object
apply_encryption(const torrent::Object::list_type& args) {
uint32_t options_mask = torrent::ConnectionManager::encryption_none;
uint32_t options_mask = torrent::net::NetworkConfig::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;
if (opt == torrent::net::NetworkConfig::encryption_none)
options_mask = torrent::net::NetworkConfig::encryption_none;
else
options_mask |= opt;
}
torrent::connection_manager()->set_encryption_options(options_mask);
torrent::config::network_config()->set_encryption_options(options_mask);
return torrent::Object();
}
@@ -51,7 +53,7 @@ apply_tos(const torrent::Object::string_type& arg) {
if (!rpc::parse_whole_value_nothrow(arg.c_str(), &value, 16, 1))
value = torrent::option_find_string(torrent::OPTION_IP_TOS, arg.c_str());
torrent::connection_manager()->set_priority(value);
torrent::config::network_config()->set_priority(value);
return torrent::Object();
}
@@ -59,43 +61,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_list()->size())
throw torrent::input_error("invalid parameters: index not found");
return d->tracker_list()->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
@@ -103,13 +82,12 @@ 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;
rak::address_info* ai = NULL;
rak::socket_address sa;
rak::socket_address* saPtr;
torrent::sa_unique_ptr sa;
try {
int port, err;
@@ -120,17 +98,17 @@ apply_scgi(const std::string& arg, int type) {
switch (type) {
case 1:
if (std::sscanf(arg.c_str(), ":%i%c", &port, &dummy) == 1) {
sa.sa_inet()->clear();
saPtr = &sa;
sa = torrent::sa_make_inet();
lt_log_print(torrent::LOG_RPC_EVENTS, "SCGI socket is open to any address and is a security risk");
} else if (std::sscanf(arg.c_str(), "%1023[^:]:%i%c", address, &port, &dummy) == 2 ||
std::sscanf(arg.c_str(), "[%64[^]]]:%i%c", address, &port, &dummy) == 2) { // [xx::xx]:port format
if ((err = rak::address_info::get_address_info(address,PF_UNSPEC, SOCK_STREAM, &ai)) != 0)
if ((err = rak::address_info::get_address_info(address, PF_UNSPEC, SOCK_STREAM, &ai)) != 0)
throw torrent::input_error("Could not bind address: " + std::string(rak::address_info::strerror(err)) + ".");
saPtr = ai->address();
sa = torrent::sa_copy(ai->c_addrinfo()->ai_addr);
lt_log_print(torrent::LOG_RPC_EVENTS, "SCGI socket is bound to an address and might be a security risk");
@@ -141,8 +119,8 @@ apply_scgi(const std::string& arg, int type) {
if (port <= 0 || port >= (1 << 16))
throw torrent::input_error("Invalid port number.");
saPtr->set_port(port);
scgi->open_port(saPtr, saPtr->length(), rpc::call_command_value("network.scgi.dont_route"));
torrent::sap_set_port(sa, port);
scgi->open_port(sa.get(), torrent::sap_length(sa), rpc::call_command_value("network.scgi.dont_route"));
break;
@@ -187,9 +165,10 @@ 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 file_manager = torrent::file_manager();
auto http_stack = torrent::net_thread::http_stack();
auto network_config = torrent::config::network_config();
CMD2_ANY_STRING ("encoding.add", std::bind(&apply_encoding_list, std::placeholders::_2));
@@ -198,8 +177,8 @@ initialize_command_network() {
CMD2_VAR_BOOL ("network.port_random", true);
CMD2_VAR_STRING ("network.port_range", "6881-6999");
CMD2_ANY ("network.listen.port", std::bind(&torrent::ConnectionManager::listen_port, cm));
CMD2_ANY ("network.listen.backlog", std::bind(&torrent::ConnectionManager::listen_backlog, cm));
CMD2_ANY ("network.listen.port", std::bind(&torrent::net::NetworkConfig::listen_port, network_config));
CMD2_ANY ("network.listen.backlog", std::bind(&torrent::net::NetworkConfig::listen_backlog, network_config));
CMD2_ANY_VALUE_V ("network.listen.backlog.set", std::bind(&torrent::ConnectionManager::set_listen_backlog, cm, std::placeholders::_2));
CMD2_VAR_BOOL ("protocol.pex", true);
@@ -213,42 +192,56 @@ 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->size(); });
CMD2_ANY ("network.http.max_cache_connections", [http_stack](auto, auto) { return http_stack->max_cache_connections(); });
CMD2_ANY_VALUE_V ("network.http.max_cache_connections.set", [http_stack](auto, auto& value) { return http_stack->set_max_cache_connections(value); });
CMD2_ANY ("network.http.max_host_connections", [http_stack](auto, auto) { return http_stack->max_host_connections(); });
CMD2_ANY_VALUE_V ("network.http.max_host_connections.set", [http_stack](auto, auto& value) { return http_stack->set_max_host_connections(value); });
CMD2_ANY ("network.http.max_total_connections", [http_stack](auto, auto) { return http_stack->max_total_connections(); });
CMD2_ANY_VALUE_V ("network.http.max_total_connections.set", [http_stack](auto, auto& value) { return http_stack->set_max_total_connections(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));
CMD2_ANY ("network.receive_buffer.size", std::bind(&torrent::ConnectionManager::receive_buffer_size, cm));
CMD2_ANY_VALUE_V ("network.receive_buffer.size.set", std::bind(&torrent::ConnectionManager::set_receive_buffer_size, cm, std::placeholders::_2));
CMD2_ANY_STRING ("network.tos.set", std::bind(&apply_tos, std::placeholders::_2));
CMD2_ANY ("network.send_buffer.size", [network_config](auto, auto) { return network_config->send_buffer_size(); });
CMD2_ANY_VALUE_V ("network.send_buffer.size.set", [network_config](auto, auto& value) { return network_config->set_send_buffer_size(value); });
CMD2_ANY ("network.receive_buffer.size", [network_config](auto, auto) { return network_config->receive_buffer_size(); });
CMD2_ANY_VALUE_V ("network.receive_buffer.size.set", [network_config](auto, auto& value) { return network_config->set_receive_buffer_size(value); });
CMD2_ANY_STRING ("network.tos.set", [](auto, auto& str) { return apply_tos(str); });
CMD2_ANY ("network.bind_address", std::bind(&core::Manager::bind_address, control->core()));
CMD2_ANY_STRING_V("network.bind_address.set", std::bind(&core::Manager::set_bind_address, control->core(), std::placeholders::_2));
CMD2_ANY ("network.local_address", std::bind(&core::Manager::local_address, control->core()));
CMD2_ANY_STRING_V("network.local_address.set", std::bind(&core::Manager::set_local_address, control->core(), std::placeholders::_2));
CMD2_ANY ("network.proxy_address", std::bind(&core::Manager::proxy_address, control->core()));
CMD2_ANY_STRING_V("network.proxy_address.set", std::bind(&core::Manager::set_proxy_address, control->core(), std::placeholders::_2));
CMD2_ANY ("network.bind_address", [network_config](auto, auto) { return network_config->bind_address_best_match_str(); });
CMD2_ANY_STRING_V("network.bind_address.set", [network_config](auto, auto& str) { return network_config->set_bind_address_str(str); });
CMD2_ANY ("network.bind_address.ipv4", [network_config](auto, auto) { return network_config->bind_inet_address_str(); });
CMD2_ANY_STRING_V("network.bind_address.ipv4.set", [network_config](auto, auto& str) { return network_config->set_bind_inet_address_str(str); });
CMD2_ANY ("network.bind_address.ipv6", [network_config](auto, auto) { return network_config->bind_inet6_address_str(); });
CMD2_ANY_STRING_V("network.bind_address.ipv6.set", [network_config](auto, auto& str) { return network_config->set_bind_inet6_address_str(str); });
CMD2_ANY ("network.open_files", std::bind(&torrent::FileManager::open_files, fileManager));
CMD2_ANY ("network.max_open_files", std::bind(&torrent::FileManager::max_open_files, fileManager));
CMD2_ANY_VALUE_V ("network.max_open_files.set", std::bind(&torrent::FileManager::set_max_open_files, fileManager, std::placeholders::_2));
CMD2_ANY ("network.total_handshakes", std::bind(&torrent::total_handshakes));
CMD2_ANY ("network.open_sockets", std::bind(&torrent::ConnectionManager::size, cm));
CMD2_ANY ("network.max_open_sockets", std::bind(&torrent::ConnectionManager::max_size, cm));
CMD2_ANY_VALUE_V ("network.max_open_sockets.set", std::bind(&torrent::ConnectionManager::set_max_size, cm, std::placeholders::_2));
CMD2_ANY ("network.local_address", [network_config](auto, auto) { return network_config->local_address_best_match_str(); });
CMD2_ANY_STRING_V("network.local_address.set", [network_config](auto, auto& str) { return network_config->set_local_address_str(str); });
CMD2_ANY ("network.local_address.ipv4", [network_config](auto, auto) { return network_config->local_inet_address_str(); });
CMD2_ANY_STRING_V("network.local_address.ipv4.set", [network_config](auto, auto& str) { return network_config->set_local_inet_address_str(str); });
CMD2_ANY ("network.local_address.ipv6", [network_config](auto, auto) { return network_config->local_inet6_address_str(); });
CMD2_ANY_STRING_V("network.local_address.ipv6.set", [network_config](auto, auto& str) { return network_config->set_local_inet6_address_str(str); });
CMD2_ANY ("network.proxy_address", [network_config](auto, auto) { return network_config->proxy_address_str(); });
CMD2_ANY_STRING_V("network.proxy_address.set", [](auto, auto& str) { return control->core()->set_proxy_address(str); });
CMD2_ANY ("network.open_files", [file_manager](auto, auto) { return file_manager->open_files(); });
CMD2_ANY ("network.max_open_files", [file_manager](auto, auto) { return file_manager->max_open_files(); });
CMD2_ANY_VALUE_V ("network.max_open_files.set", [file_manager](auto, auto& value) { return file_manager->set_max_open_files(value); });
CMD2_ANY ("network.total_handshakes", [](auto, auto) { return torrent::total_handshakes(); });
CMD2_ANY ("network.open_sockets", [cm](auto, auto) { return cm->size(); });
CMD2_ANY ("network.max_open_sockets", [cm](auto, auto) { return cm->max_size(); });
CMD2_ANY_VALUE_V ("network.max_open_sockets.set", [cm](auto, auto& value) { return cm->set_max_size(value); });
CMD2_ANY_STRING ("network.scgi.open_port", std::bind(&apply_scgi, std::placeholders::_2, 1));
CMD2_ANY_STRING ("network.scgi.open_local", std::bind(&apply_scgi, std::placeholders::_2, 2));
@@ -261,11 +254,14 @@ initialize_command_network() {
CMD2_VAR_BOOL ("network.rpc.use_xmlrpc", true);
CMD2_VAR_BOOL ("network.rpc.use_jsonrpc", true);
CMD2_ANY ("network.block.ipv4", std::bind(&torrent::ConnectionManager::is_block_ipv4, cm));
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.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));
CMD2_ANY ("network.block.ipv4", [network_config](auto, auto) { return network_config->is_block_ipv4(); });
CMD2_ANY_VALUE_V ("network.block.ipv4.set", [network_config](auto, auto& value) { return network_config->set_block_ipv4(value); });
CMD2_ANY ("network.block.ipv6", [network_config](auto, auto) { return network_config->is_block_ipv6(); });
CMD2_ANY_VALUE_V ("network.block.ipv6.set", [network_config](auto, auto& value) { return network_config->set_block_ipv6(value); });
CMD2_ANY ("network.block.ipv4in6", [network_config](auto, auto) { return network_config->is_block_ipv4in6(); });
CMD2_ANY_VALUE_V ("network.block.ipv4in6.set", [network_config](auto, auto& value) { return network_config->set_block_ipv4in6(value); });
CMD2_ANY ("network.block.outgoing", [network_config](auto, auto) { return network_config->is_block_outgoing(); });
CMD2_ANY_VALUE_V ("network.block.outgoing.set", [network_config](auto, auto& value) { return network_config->set_block_outgoing(value); });
CMD2_ANY ("network.prefer.ipv6", [network_config](auto, auto) { return network_config->is_prefer_ipv6(); });
CMD2_ANY_VALUE_V ("network.prefer.ipv6.set", [network_config](auto, auto& value) { return network_config->set_prefer_ipv6(value); });
}
+8 -45
View File
@@ -1,47 +1,9 @@
// 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
#include "config.h"
#include <rak/error_number.h>
#include <rak/path.h>
#include <rak/socket_address.h>
#include <rak/string_manip.h>
#include <torrent/bitfield.h>
#include <torrent/rate.h>
#include <torrent/net/socket_address.h>
#include <torrent/peer/connection_list.h>
#include <torrent/peer/peer.h>
#include <torrent/peer/peer_info.h>
@@ -69,17 +31,18 @@ retrieve_p_id_html(torrent::Peer* peer) {
torrent::Object
retrieve_p_address(torrent::Peer* peer) {
const rak::socket_address *addr = rak::socket_address::cast_from(peer->peer_info()->socket_address());
auto sa = peer->peer_info()->socket_address();
auto addr_str = torrent::sa_addr_str(sa);
if (addr->family() == rak::socket_address::af_inet6)
return "[" + addr->address_str() + "]";
else
return addr->address_str();
if (sa->sa_family == AF_INET6)
return "[" + addr_str + "]";
return addr_str;
}
torrent::Object
retrieve_p_port(torrent::Peer* peer) {
return rak::socket_address::cast_from(peer->peer_info()->socket_address())->port();
return torrent::sa_port(peer->peer_info()->socket_address());
}
torrent::Object
+3 -41
View File
@@ -1,39 +1,3 @@
// 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
#include "config.h"
#include <sys/types.h>
@@ -52,7 +16,7 @@ torrent::Object
cmd_scheduler_simple_added(core::Download* download) {
unsigned int numActive = (*control->view_manager()->find("active"))->size_visible();
int64_t maxActive = rpc::call_command("scheduler.max_active", torrent::Object()).as_value();
if (numActive < (uint64_t)maxActive)
control->core()->download_list()->resume(download);
@@ -83,7 +47,7 @@ cmd_scheduler_simple_removed(core::Download* download) {
}
torrent::Object
cmd_scheduler_simple_update(core::Download* download) {
cmd_scheduler_simple_update([[maybe_unused]] core::Download* download) {
core::View* viewActive = *control->view_manager()->find("active");
core::View* viewStarted = *control->view_manager()->find("started");
@@ -91,7 +55,6 @@ cmd_scheduler_simple_update(core::Download* download) {
uint64_t maxActive = rpc::call_command("scheduler.max_active", torrent::Object()).as_value();
if (viewActive->size_visible() < maxActive) {
for (core::View::iterator itr = viewStarted->begin_visible(), last = viewStarted->end_visible(); itr != last; itr++) {
if ((*itr)->is_active())
continue;
@@ -102,8 +65,7 @@ cmd_scheduler_simple_update(core::Download* download) {
break;
}
} else if (viewActive->size_visible() > maxActive) {
} else {
while (viewActive->size_visible() > maxActive)
control->core()->download_list()->pause(*viewActive->begin_visible());
}
+19 -48
View File
@@ -1,49 +1,14 @@
// 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
#include "config.h"
#include <cstdio>
#include <rak/address_info.h>
#include <torrent/throttle.h>
#include <torrent/rate.h>
#include <torrent/download/resource_manager.h>
#include <torrent/net/socket_address.h>
#include "core/manager.h"
#include "ui/root.h"
#include "rak/address_info.h"
#include "rpc/parse.h"
#include "rpc/parse_commands.h"
@@ -59,13 +24,16 @@ parse_address_range(const torrent::Object::list_type& args, torrent::Object::lis
rak::address_info* ai;
ret = std::sscanf(itr->as_string().c_str(), "%1023[^/]/%d%c", host, &prefixWidth, &dummy);
if (ret < 1 || rak::address_info::get_address_info(host, PF_INET, SOCK_STREAM, &ai) != 0)
throw torrent::input_error("Could not resolve host.");
uint32_t begin, end;
rak::socket_address sa;
sa.copy(*ai->address(), ai->length());
begin = end = sa.sa_inet()->address_h();
auto sa = torrent::sa_copy(ai->c_addrinfo()->ai_addr);
auto sa_addr = htonl(reinterpret_cast<sockaddr_in*>(sa.get())->sin_addr.s_addr);
begin = end = sa_addr;
rak::address_info::free_address_info(ai);
if (ret == 2) {
@@ -73,18 +41,21 @@ parse_address_range(const torrent::Object::list_type& args, torrent::Object::lis
throw torrent::input_error("Cannot specify both network and range end.");
uint32_t netmask = std::numeric_limits<uint32_t>::max() << (32 - prefixWidth);
if (prefixWidth >= 32 || sa.sa_inet()->address_h() & ~netmask)
if (prefixWidth >= 32 || sa_addr & ~netmask)
throw torrent::input_error("Invalid address/prefix.");
end = sa.sa_inet()->address_h() | ~netmask;
end = sa_addr | ~netmask;
} else if (++itr != args.end()) {
if (rak::address_info::get_address_info(itr->as_string().c_str(), PF_INET, SOCK_STREAM, &ai) != 0)
throw torrent::input_error("Could not resolve host.");
sa.copy(*ai->address(), ai->length());
sa = torrent::sa_copy(ai->c_addrinfo()->ai_addr);
sa_addr = htonl(reinterpret_cast<sockaddr_in*>(sa.get())->sin_addr.s_addr);
rak::address_info::free_address_info(ai);
end = sa.sa_inet()->address_h();
end = sa_addr;
}
// convert to [begin, end) making sure the end doesn't overflow
@@ -196,10 +167,10 @@ initialize_command_throttle() {
CMD2_VAR_VALUE ("throttle.max_downloads.div._val", 1);
CMD2_VAR_VALUE ("throttle.max_downloads.global._val", 0);
CMD2_REDIRECT_GENERIC("throttle.max_uploads.div", "throttle.max_uploads.div._val");
CMD2_REDIRECT_GENERIC("throttle.max_uploads.global", "throttle.max_uploads.global._val");
CMD2_REDIRECT_GENERIC("throttle.max_downloads.div", "throttle.max_downloads.div._val");
CMD2_REDIRECT_GENERIC("throttle.max_downloads.global", "throttle.max_downloads.global._val");
CMD2_REDIRECT ("throttle.max_uploads.div", "throttle.max_uploads.div._val");
CMD2_REDIRECT ("throttle.max_uploads.global", "throttle.max_uploads.global._val");
CMD2_REDIRECT ("throttle.max_downloads.div", "throttle.max_downloads.div._val");
CMD2_REDIRECT ("throttle.max_downloads.global", "throttle.max_downloads.global._val");
CMD2_ANY_VALUE ("throttle.max_uploads.div.set", std::bind(&throttle_update, "throttle.max_uploads.div._val.set", std::placeholders::_2));
CMD2_ANY_VALUE ("throttle.max_uploads.global.set", std::bind(&throttle_update, "throttle.max_uploads.global._val.set", std::placeholders::_2));
+41 -14
View File
@@ -1,9 +1,9 @@
#include "config.h"
#include <cassert>
#include <cstdio>
#include <netdb.h>
#include <rak/address_info.h>
#include <rak/error_number.h>
#include <torrent/net/network_config.h>
#include <torrent/net/resolver.h>
#include <torrent/tracker/dht_controller.h>
#include <torrent/tracker/tracker.h>
@@ -30,11 +30,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;
@@ -44,13 +44,20 @@ apply_dht_add_node(const std::string& arg) {
if (port < 1 || port > 65535)
throw torrent::input_error("Invalid port number.");
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::main_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);
});
@@ -59,11 +66,23 @@ apply_dht_add_node(const std::string& arg) {
torrent::Object
apply_enable_trackers(int64_t arg) {
for (core::Manager::DListItr itr = control->core()->download_list()->begin(), last = control->core()->download_list()->end(); itr != last; ++itr) {
std::for_each((*itr)->tracker_list()->begin(), (*itr)->tracker_list()->end(), std::mem_fn(arg ? &torrent::tracker::Tracker::enable : &torrent::tracker::Tracker::disable));
if (arg == 0) {
for (auto download : *control->core()->download_list())
download->tracker_controller().for_each([](auto& tracker) { tracker.disable(); });
if (arg && !rpc::call_command_value("trackers.use_udp"))
(*itr)->enable_udp_trackers(false);
} else if (rpc::call_command_value("trackers.use_udp") == 0) {
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 download : *control->core()->download_list())
download->tracker_controller().for_each([](auto& tracker) { tracker.enable(); });
}
return torrent::Object();
@@ -122,10 +141,18 @@ initialize_command_tracker() {
CMD2_VAR_VALUE ("trackers.numwant", -1);
CMD2_VAR_BOOL ("trackers.use_udp", true);
auto dht_manager = control->dht_manager();
CMD2_ANY_STRING_V ("dht.mode.set", std::bind(&core::DhtManager::set_mode, control->dht_manager(), std::placeholders::_2));
CMD2_VAR_VALUE ("dht.port", int64_t(6881));
CMD2_ANY ("dht.port", std::bind(&torrent::tracker::DhtController::port, torrent::dht_controller()));
CMD2_ANY_VALUE_V ("dht.port.set", [](auto, auto) {
lt_log_print(torrent::LOG_DHT_ERROR, "dht.port.set is no longer supported, use dht.override_port.set", 0);
});
CMD2_ANY ("dht.override_port", std::bind(&torrent::net::NetworkConfig::override_dht_port, torrent::config::network_config()));
CMD2_ANY_VALUE_V ("dht.override_port.set", std::bind(&torrent::net::NetworkConfig::set_override_dht_port, torrent::config::network_config(), std::placeholders::_2));
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()));
CMD2_ANY ("dht.throttle.name", std::bind(&core::DhtManager::throttle_name, control->dht_manager()));
CMD2_ANY_STRING_V ("dht.throttle.name.set", std::bind(&core::DhtManager::set_throttle_name, control->dht_manager(), std::placeholders::_2));
CMD2_ANY ("dht.statistics", std::bind(&core::DhtManager::dht_statistics, dht_manager));
CMD2_ANY ("dht.throttle.name", std::bind(&core::DhtManager::throttle_name, dht_manager));
CMD2_ANY_STRING_V ("dht.throttle.name.set", std::bind(&core::DhtManager::set_throttle_name, dht_manager, std::placeholders::_2));
}
+56 -46
View File
@@ -4,7 +4,6 @@
#include <ctime>
#include <regex>
#include <rak/algorithm.h>
#include <torrent/utils/log.h>
@@ -76,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;
}
@@ -95,7 +94,8 @@ apply_view_set(const torrent::Object::list_type& args) {
// if (args.front().as_string() == "main")
// control->ui()->download_list()->set_view(*itr);
// else
throw torrent::input_error("No such target.");
throw torrent::input_error("No such target.");
}
torrent::Object
@@ -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;
}
@@ -407,7 +407,9 @@ apply_to_time(const torrent::Object& rawArgs, int flags) {
torrent::Object
apply_to_elapsed_time(const torrent::Object& rawArgs) {
uint64_t arg = cachedTime.seconds() - rawArgs.as_value();
auto cached_seconds = torrent::this_thread::cached_seconds().count();
uint64_t arg = cached_seconds - rawArgs.as_value();
char buffer[48];
snprintf(buffer, 48, "%2d:%02d:%02d", (int)(arg / 3600), (int)((arg / 60) % 60), (int)(arg % 60));
@@ -524,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();
@@ -605,8 +607,9 @@ apply_elapsed_less(const torrent::Object::list_type& args) {
throw torrent::input_error("Wrong argument count.");
int64_t start_time = rpc::convert_to_value(args.front());
auto cached_seconds = torrent::this_thread::cached_seconds().count();
return (int64_t)(start_time != 0 && rak::timer::current_seconds() - start_time < rpc::convert_to_value(args.back()));
return (int64_t)(start_time != 0 && cached_seconds - start_time < rpc::convert_to_value(args.back()));
}
torrent::Object
@@ -615,8 +618,9 @@ apply_elapsed_greater(const torrent::Object::list_type& args) {
throw torrent::input_error("Wrong argument count.");
int64_t start_time = rpc::convert_to_value(args.front());
auto cached_seconds = torrent::this_thread::cached_seconds().count();
return (int64_t)(start_time != 0 && rak::timer::current_seconds() - start_time > rpc::convert_to_value(args.back()));
return (int64_t)(start_time != 0 && cached_seconds - start_time > rpc::convert_to_value(args.back()));
}
inline std::vector<int64_t>
@@ -626,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");
@@ -674,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.");
@@ -707,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;
@@ -748,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)
@@ -764,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();
}
@@ -820,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");
@@ -854,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));
@@ -871,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]);
});
+38 -58
View File
@@ -1,16 +1,18 @@
#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/manager.h"
#include "core/download_store.h"
#include "core/view_manager.h"
#include "core/dht_manager.h"
#include "core/download_store.h"
#include "core/http_queue.h"
#include "core/manager.h"
#include "core/view_manager.h"
#include "display/canvas.h"
#include "display/window.h"
#include "display/window_http_queue.h"
@@ -23,86 +25,64 @@
#include "rpc/command_scheduler.h"
#include "rpc/lua.h"
#include "rpc/parse_commands.h"
#include "rpc/scgi.h"
#include "rpc/object_storage.h"
#include "ui/root.h"
#include "control.h"
Control::Control()
: m_ui(new ui::Root()),
m_display(new display::Manager()),
m_input(new input::Manager()),
m_inputStdin(new input::InputEvent(STDIN_FILENO)),
m_commandScheduler(new rpc::CommandScheduler()),
m_objectStorage(new rpc::object_storage()),
m_lua_engine(new rpc::LuaEngine()),
m_directory_events(new torrent::directory_events()) {
Control::Control() :
m_ui(new ui::Root()),
m_display(new display::Manager()),
m_input(new input::Manager()),
m_inputStdin(new input::InputEvent(STDIN_FILENO)),
m_core = std::make_unique<core::Manager>();
m_viewManager = std::make_unique<core::ViewManager>();
m_dhtManager = std::make_unique<core::DhtManager>();
m_commandScheduler(new rpc::CommandScheduler()),
m_objectStorage(new rpc::object_storage()),
m_lua_engine(new rpc::LuaEngine()),
m_directory_events(new torrent::directory_events()),
m_inputStdin->slot_pressed(std::bind(&input::Manager::pressed, m_input.get(), std::placeholders::_1));
m_tick(0),
m_shutdownReceived(false),
m_shutdownQuick(false) {
m_core = new core::Manager();
m_viewManager = new core::ViewManager();
m_dhtManager = new core::DhtManager();
m_inputStdin->slot_pressed(std::bind(&input::Manager::pressed, m_input, std::placeholders::_1));
m_taskShutdown.slot() = std::bind(&Control::handle_shutdown, this);
m_task_shutdown.slot() = std::bind(&Control::handle_shutdown, this);
m_commandScheduler->set_slot_error_message([this](const std::string& msg) { m_core->push_log_std(msg); });
}
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
Control::initialize() {
display::Canvas::initialize();
display::Window::slot_schedule([this](display::Window* w, rak::timer t) { m_display->schedule(w, t); });
display::Window::slot_schedule([this](display::Window* w, std::chrono::microseconds t) { m_display->schedule(w, t); });
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_ui->init(this);
if(!display::Canvas::daemon()) {
m_inputStdin->insert(torrent::main_thread()->poll());
}
if(!display::Canvas::daemon())
m_inputStdin->insert(torrent::this_thread::poll());
}
void
Control::cleanup() {
// delete m_scgi; m_scgi = NULL;
rpc::rpc.cleanup();
priority_queue_erase(&taskScheduler, &m_taskShutdown);
torrent::this_thread::scheduler()->erase(&m_task_shutdown);
if(!display::Canvas::daemon()) {
m_inputStdin->remove(torrent::main_thread()->poll());
m_inputStdin->remove(torrent::this_thread::poll());
}
m_core->download_store()->disable();
@@ -118,8 +98,6 @@ Control::cleanup() {
void
Control::cleanup_exception() {
// delete m_scgi; m_scgi = NULL;
display::Canvas::cleanup();
}
@@ -131,7 +109,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()->size() != 0 || !core()->http_queue()->empty())
return false;
return torrent::is_inactive();
@@ -142,21 +123,20 @@ Control::handle_shutdown() {
rpc::commands.call_catch("event.system.shutdown", rpc::make_target(), "shutdown", "System shutdown event action failed: ");
if (!m_shutdownQuick) {
// Temporary hack:
if (worker_thread->is_active())
worker_thread->queue_item(&ThreadBase::stop_thread);
worker_thread->stop_thread_wait();
torrent::connection_manager()->listen_close();
m_directory_events->close();
m_core->shutdown(false);
if (!m_taskShutdown.is_queued())
priority_queue_insert(&taskScheduler, &m_taskShutdown, cachedTime + rak::timer::from_seconds(5));
if (!m_task_shutdown.is_scheduled())
torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_task_shutdown, 5s);
} else {
// Temporary hack:
if (worker_thread->is_active())
worker_thread->queue_item(&ThreadBase::stop_thread);
worker_thread->stop_thread_wait();
m_core->shutdown(true);
}
+30 -66
View File
@@ -1,48 +1,12 @@
// 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_CONTROL_H
#define RTORRENT_CONTROL_H
#include <atomic>
#include <cinttypes>
#include <memory>
#include <sys/types.h>
#include <rak/timer.h>
#include <rak/priority_queue_default.h>
#include <torrent/torrent.h>
#include <torrent/utils/scheduler.h>
namespace ui {
class Root;
@@ -61,7 +25,7 @@ namespace display {
namespace input {
class InputEvent;
class Manager;
}
}
namespace rpc {
class CommandScheduler;
@@ -78,7 +42,7 @@ class Control {
public:
Control();
~Control();
bool is_shutdown_completed();
bool is_shutdown_received() { return m_shutdownReceived; }
bool is_shutdown_started() { return m_shutdownQuick; }
@@ -92,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++; }
@@ -117,29 +81,29 @@ 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;
uint64_t m_tick{};
mode_t m_umask;
std::string m_workingDirectory;
rak::priority_item m_taskShutdown;
torrent::utils::SchedulerEntry m_task_shutdown;
std::atomic<bool> m_shutdownReceived;
std::atomic<bool> m_shutdownQuick;
std::atomic<bool> m_shutdownReceived{};
std::atomic<bool> m_shutdownQuick{};
};
#endif
-151
View File
@@ -1,151 +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
#include "config.h"
#include <iostream>
#include <curl/curl.h>
#include <curl/easy.h>
#include <torrent/exceptions.h>
#include "globals.h"
#include "curl_get.h"
#include "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() {
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.
m_taskTimeout.slot() = std::bind(&CurlGet::receive_timeout, this);
priority_queue_update(&taskScheduler, &m_taskTimeout, cachedTime + rak::timer::from_seconds(m_timeout + 5));
}
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() {
priority_queue_erase(&taskScheduler, &m_taskTimeout);
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");
}
double
CurlGet::size_done() {
double d = 0.0;
curl_easy_getinfo(m_handle, CURLINFO_SIZE_DOWNLOAD, &d);
return d;
}
double
CurlGet::size_total() {
double d = 0.0;
curl_easy_getinfo(m_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d);
return d;
}
}
-91
View File
@@ -1,91 +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_CURL_GET_H
#define RTORRENT_CORE_CURL_GET_H
#include <iosfwd>
#include <string>
#include <curl/curl.h>
#include <torrent/http.h>
#include "rak/priority_queue_default.h"
namespace core {
class CurlStack;
class CurlGet : public torrent::Http {
public:
friend class CurlStack;
CurlGet(CurlStack* s) : m_active(false), m_handle(NULL), m_stack(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; }
double size_done();
double size_total();
CURL* handle() { return m_handle; }
private:
CurlGet(const CurlGet&);
void operator = (const CurlGet&);
void receive_timeout();
bool m_active;
bool m_ipv6;
rak::priority_item m_taskTimeout;
CURL* m_handle;
CurlStack* m_stack;
};
}
#endif
-102
View File
@@ -1,102 +0,0 @@
#include "config.h"
#include <cassert>
#include <curl/curl.h>
#include <curl/multi.h>
#include <torrent/poll.h>
#include <torrent/exceptions.h>
#include <torrent/utils/thread.h>
#include "control.h"
#include "curl_socket.h"
#include "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::main_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::main_thread()->poll()->insert_error(socket);
}
if (what == CURL_POLL_NONE || what == CURL_POLL_OUT)
torrent::main_thread()->poll()->remove_read(socket);
else
torrent::main_thread()->poll()->insert_read(socket);
if (what == CURL_POLL_NONE || what == CURL_POLL_IN)
torrent::main_thread()->poll()->remove_write(socket);
else
torrent::main_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::main_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
}
}
-72
View File
@@ -1,72 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2008, 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_CURL_SOCKET_H
#define RTORRENT_CORE_CURL_SOCKET_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
-240
View File
@@ -1,240 +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);
priority_queue_erase(&taskScheduler, &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())
priority_queue_erase(&taskScheduler, &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);
// Sometimes libcurl forgets to reset the timeout. Try to poll the value in that case, or use 10 seconds.
if (!empty() && !m_task_timeout.is_queued()) {
long timeout;
curl_multi_timeout((CURLM*)m_handle, &timeout);
priority_queue_insert(&taskScheduler, &m_task_timeout,
cachedTime + rak::timer::from_milliseconds(std::max<unsigned long>(timeout, 10000)));
}
}
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(void* handle, long timeout_ms, void* userp) {
CurlStack* stack = (CurlStack*)userp;
priority_queue_update(&taskScheduler, &stack->m_task_timeout, cachedTime + rak::timer::from_milliseconds(timeout_ms));
return 0;
}
}
-121
View File
@@ -1,121 +0,0 @@
#ifndef RTORRENT_CORE_CURL_STACK_H
#define RTORRENT_CORE_CURL_STACK_H
#include <deque>
#include <string>
#include "rak/priority_queue_default.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, long timeout_ms, 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&);
void operator = (const CurlStack&);
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};
rak::priority_item 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
+28 -29
View File
@@ -18,22 +18,25 @@
#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 {
const char* DhtManager::dht_settings[dht_settings_num] = { "disable", "off", "auto", "on" };
DhtManager::~DhtManager() {
priority_queue_erase(&taskScheduler, &m_updateTimeout);
priority_queue_erase(&taskScheduler, &m_stopTimeout);
torrent::this_thread::scheduler()->erase(&m_update_timeout);
torrent::this_thread::scheduler()->erase(&m_stop_timeout);
}
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 +51,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);
@@ -66,15 +69,15 @@ DhtManager::load_dht_cache() {
void
DhtManager::start_dht() {
priority_queue_erase(&taskScheduler, &m_stopTimeout);
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,20 +85,16 @@ 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)
return;
if (!torrent::dht_controller()->start(port)) {
if (!torrent::dht_controller()->start()) {
m_start = dht_off;
return;
}
torrent::dht_controller()->reset_statistics();
m_updateTimeout.slot() = std::bind(&DhtManager::update, this);
priority_queue_insert(&taskScheduler, &m_updateTimeout, (cachedTime + rak::timer::from_seconds(60)).round_seconds());
m_update_timeout.slot() = std::bind(&DhtManager::update, this);
torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_update_timeout, 60s);
m_dhtPrevCycle = 0;
m_dhtPrevQueriesSent = 0;
@@ -107,11 +106,11 @@ DhtManager::start_dht() {
void
DhtManager::stop_dht() {
priority_queue_erase(&taskScheduler, &m_updateTimeout);
priority_queue_erase(&taskScheduler, &m_stopTimeout);
torrent::this_thread::scheduler()->erase(&m_update_timeout);
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();
@@ -165,7 +164,7 @@ DhtManager::update() {
if (!torrent::dht_controller()->is_active())
throw torrent::internal_error("DhtManager::update called with DHT inactive.");
if (m_start == dht_auto && !m_stopTimeout.is_queued()) {
if (m_start == dht_auto && !m_stop_timeout.is_scheduled()) {
DownloadList::const_iterator itr, end;
for (itr = control->core()->download_list()->begin(), end = control->core()->download_list()->end(); itr != end; ++itr)
@@ -173,16 +172,16 @@ DhtManager::update() {
break;
if (itr == end) {
m_stopTimeout.slot() = std::bind(&DhtManager::stop_dht, this);
priority_queue_insert(&taskScheduler, &m_stopTimeout, (cachedTime + rak::timer::from_seconds(15 * 60)).round_seconds());
m_stop_timeout.slot() = std::bind(&DhtManager::stop_dht, this);
torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_stop_timeout, 15min);
}
}
// While bootstrapping (log_statistics returns true), check every minute if it completed, otherwise update every 15 minutes.
if (log_statistics(false))
priority_queue_insert(&taskScheduler, &m_updateTimeout, (cachedTime + rak::timer::from_seconds(60)).round_seconds());
torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_update_timeout, 1min);
else
priority_queue_insert(&taskScheduler, &m_updateTimeout, (cachedTime + rak::timer::from_seconds(15 * 60)).round_seconds());
torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_update_timeout, 15min);
}
bool
@@ -195,7 +194,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);
}
@@ -203,7 +202,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;
+6 -7
View File
@@ -1,15 +1,13 @@
#ifndef RTORRENT_CORE_DHT_MANAGER_H
#define RTORRENT_CORE_DHT_MANAGER_H
#include <rak/priority_queue_default.h>
#include <torrent/object.h>
#include <torrent/utils/scheduler.h>
namespace core {
class DhtManager {
public:
DhtManager() : m_warned(false), m_start(dht_off) { }
~DhtManager();
void load_dht_cache();
@@ -44,11 +42,12 @@ private:
uint64_t m_dhtPrevBytesUp;
uint64_t m_dhtPrevBytesDown;
rak::priority_item m_updateTimeout;
rak::priority_item m_stopTimeout;
bool m_warned;
torrent::utils::SchedulerEntry m_update_timeout;
torrent::utils::SchedulerEntry m_stop_timeout;
bool m_warned{};
int m_start{dht_off};
int m_start;
std::string m_throttleName;
};
+13 -13
View File
@@ -6,8 +6,8 @@
#include <torrent/exceptions.h>
#include <torrent/rate.h>
#include <torrent/torrent.h>
#include <torrent/tracker_list.h>
#include <torrent/tracker/tracker.h>
#include <torrent/data/file.h>
#include <torrent/data/file_list.h>
#include "rpc/parse_commands.h"
@@ -19,11 +19,7 @@
namespace core {
Download::Download(download_type d) :
m_download(d),
m_hashFailed(false),
m_resumeFlags(~uint32_t()),
m_group(0) {
m_download(d) {
m_download.info()->signal_tracker_success().push_back(std::bind(&Download::receive_tracker_msg, this, ""));
m_download.info()->signal_tracker_failed().push_back(std::bind(&Download::receive_tracker_msg, this, std::placeholders::_1));
@@ -38,13 +34,17 @@ Download::~Download() {
void
Download::enable_udp_trackers(bool state) {
for (torrent::TrackerList::iterator itr = m_download.tracker_list()->begin(), last = m_download.tracker_list()->end(); itr != last; ++itr)
if (itr->type() == torrent::TRACKER_UDP) {
if (state)
itr->enable();
else
itr->disable();
}
for (int idx = 0, end = m_download.tracker_controller().size(); idx < end; ++idx) {
auto tracker = m_download.tracker_controller().at(idx);
if (tracker.type() != torrent::TRACKER_UDP)
continue;
if (state)
tracker.enable();
else
tracker.disable();
}
}
uint32_t
+5 -6
View File
@@ -5,9 +5,9 @@
#include <torrent/download.h>
#include <torrent/download_info.h>
#include <torrent/hash_string.h>
#include <torrent/tracker_list.h>
#include <torrent/data/file_list.h>
#include <torrent/peer/connection_list.h>
#include <torrent/tracker/wrappers.h>
#include "globals.h"
@@ -62,8 +62,7 @@ public:
torrent::Object* bencode() { return m_download.bencode(); }
auto tracker_controller() { return m_download.tracker_controller(); }
tracker_list_type* tracker_list() { return m_download.tracker_list(); }
uint32_t tracker_list_size() const { return m_download.tracker_list()->size(); }
uint32_t tracker_list_size() const { return m_download.c_tracker_controller().size(); }
auto connection_list() { return m_download.connection_list(); }
uint32_t connection_list_size() const;
@@ -101,10 +100,10 @@ private:
// Store the FileList instance so we can use slots etc on it.
download_type m_download;
bool m_hashFailed;
bool m_hashFailed{};
std::string m_message;
uint32_t m_resumeFlags;
unsigned int m_group;
uint32_t m_resumeFlags{~uint32_t{}};
unsigned int m_group{};
};
inline bool
+35 -47
View File
@@ -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 {
@@ -60,20 +58,10 @@ is_magnet_uri(const std::string& uri) {
}
DownloadFactory::DownloadFactory(Manager* m) :
m_manager(m),
m_stream(NULL),
m_object(NULL),
m_commited(false),
m_loaded(false),
m_manager(m) {
m_session(false),
m_start(false),
m_printLog(true),
m_isFile(false),
m_initLoad(false) {
m_taskLoad.slot() = std::bind(&DownloadFactory::receive_load, this);
m_taskCommit.slot() = std::bind(&DownloadFactory::receive_commit, this);
m_task_load.slot() = std::bind(&DownloadFactory::receive_load, this);
m_task_commit.slot() = std::bind(&DownloadFactory::receive_commit, this);
// m_variables["connection_leech"] = rpc::call_command("protocol.connection.leech");
// m_variables["connection_seed"] = rpc::call_command("protocol.connection.seed");
@@ -84,18 +72,16 @@ DownloadFactory::DownloadFactory(Manager* m) :
}
DownloadFactory::~DownloadFactory() {
priority_queue_erase(&taskScheduler, &m_taskLoad);
priority_queue_erase(&taskScheduler, &m_taskCommit);
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
DownloadFactory::load(const std::string& uri) {
m_uri = uri;
priority_queue_insert(&taskScheduler, &m_taskLoad, cachedTime);
torrent::this_thread::scheduler()->wait_for(&m_task_load, 0ms);
}
// This function must be called before DownloadFactory::commit().
@@ -104,13 +90,13 @@ 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;
}
void
DownloadFactory::commit() {
priority_queue_insert(&taskScheduler, &m_taskCommit, cachedTime);
torrent::this_thread::scheduler()->wait_for(&m_task_commit, 0ms);
}
void
@@ -120,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;
@@ -182,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;
@@ -204,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) {
@@ -225,7 +212,7 @@ DownloadFactory::receive_success() {
torrent::Object* rtorrent = &root->insert_preserve_copy("rtorrent", torrent::Object::create_map()).first->second;
torrent::Object& resumeObject = root->insert_preserve_copy("libtorrent_resume", torrent::Object::create_map()).first->second;
rtorrent->insert_key("key", download->tracker_list()->key());
rtorrent->insert_key("key", download->tracker_controller().key());
initialize_rtorrent(download, rtorrent);
@@ -299,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.");
@@ -346,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();
@@ -366,15 +352,17 @@ DownloadFactory::receive_failed(const std::string& msg) {
void
DownloadFactory::initialize_rtorrent(Download* download, torrent::Object* rtorrent) {
auto cached_seconds = torrent::this_thread::cached_seconds().count();
if (!rtorrent->has_key_value("state") || rtorrent->get_key_value("state") > 1) {
rtorrent->insert_key("state", (int64_t)m_start);
rtorrent->insert_key("state_changed", cachedTime.seconds());
rtorrent->insert_key("state_changed", cached_seconds);
rtorrent->insert_key("state_counter", int64_t());
} else if (!rtorrent->has_key_value("state_changed") ||
rtorrent->get_key_value("state_changed") > cachedTime.seconds() || rtorrent->get_key_value("state_changed") == 0 ||
rtorrent->get_key_value("state_changed") > cached_seconds || rtorrent->get_key_value("state_changed") == 0 ||
!rtorrent->has_key_value("state_counter") || (uint64_t)rtorrent->get_key_value("state_counter") > (1 << 20)) {
rtorrent->insert_key("state_changed", cachedTime.seconds());
rtorrent->insert_key("state_changed", cached_seconds);
rtorrent->insert_key("state_counter", int64_t());
}
+15 -50
View File
@@ -1,39 +1,3 @@
// 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
// The DownloadFactory class assures that loading torrents can be done
// anywhere in the code by queueing the task. The user may change
// settings while, or even after, the torrent is loading.
@@ -44,13 +8,14 @@
#include <functional>
#include <iosfwd>
#include <rak/priority_queue_default.h>
#include <torrent/object.h>
#include <torrent/utils/scheduler.h>
#include "http_queue.h"
namespace core {
class Download;
class Manager;
class DownloadFactory {
@@ -97,26 +62,26 @@ 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;
bool m_commited{};
bool m_loaded{};
std::string m_uri;
bool m_session;
bool m_start;
bool m_printLog;
bool m_isFile;
bool m_initLoad;
bool m_session{};
bool m_start{};
bool m_printLog{true};
bool m_isFile{};
bool m_initLoad{};
command_list_type m_commands;
torrent::Object::map_type m_variables;
slot_void m_slot_finished;
rak::priority_item m_taskLoad;
rak::priority_item m_taskCommit;
slot_void m_slot_finished;
torrent::utils::SchedulerEntry m_task_load;
torrent::utils::SchedulerEntry m_task_commit;
};
bool is_network_uri(const std::string& uri);
+37 -13
View File
@@ -43,10 +43,27 @@ DownloadList::check_contains([[maybe_unused]] Download* d) {
void
DownloadList::clear() {
std::for_each(begin(), end(), [&](Download* d) { close(d); });
std::for_each(begin(), end(), [](Download* d) { delete d; });
int error_count = 0;
base_type::clear();
while (!empty()) {
auto download = back();
try {
close(download);
base_type::pop_back();
torrent::download_remove(*download->download());
delete download;
} catch (torrent::internal_error& e) {
lt_log_print(torrent::LOG_ERROR, "DownloadList::clear() failed to close or remove download: %s", e.what());
error_count++;
continue;
}
}
if (error_count > 0)
throw torrent::internal_error("DownloadList::clear() failed to close or remove " + std::to_string(error_count) + " downloads.");
}
void
@@ -90,11 +107,11 @@ DownloadList::create(torrent::Object* obj, uint32_t tracker_key, bool printLog)
download = torrent::download_add(obj, tracker_key);
} catch (torrent::local_error& e) {
delete obj;
if (printLog)
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not create download: %s", e.what());
delete obj;
return NULL;
}
@@ -150,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");
@@ -184,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;
@@ -214,7 +234,7 @@ DownloadList::open_throw(Download* download) {
if (download->download()->info()->is_open())
return;
int openFlags = download->resume_flags();
if (rpc::call_command_value("system.file.allocate"))
@@ -253,7 +273,7 @@ void
DownloadList::close_quick(Download* download) {
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download quickly.");
close(download);
// Make sure we cancel any tracker requests. This should rather be
// handled by some parameter to the close function, or some other
// way of giving the client more control of when STOPPED requests
@@ -333,7 +353,9 @@ DownloadList::resume(Download* download, int flags) {
// This will never actually do anything due to the above hash check.
// open_throw(download);
rpc::call_command("d.state_changed.set", cachedTime.seconds(), rpc::make_target(download));
auto cached_seconds = torrent::this_thread::cached_seconds().count();
rpc::call_command("d.state_changed.set", cached_seconds, rpc::make_target(download));
rpc::call_command("d.state_counter.set", rpc::call_command_value("d.state_counter", rpc::make_target(download)) + 1, rpc::make_target(download));
if (download->is_done()) {
@@ -415,13 +437,15 @@ DownloadList::pause(Download* download, int flags) {
download->download()->stop(flags);
torrent::resume_save_progress(*download->download(), download->download()->bencode()->get_key("libtorrent_resume"));
// TODO: This is actually for pause, not stop... And doesn't get
// called when the download isn't active, but was in the 'started'
// view.
DL_TRIGGER_EVENT(download, "event.download.paused");
rpc::call_command("d.state_changed.set", cachedTime.seconds(), rpc::make_target(download));
auto cached_seconds = torrent::this_thread::cached_seconds().count();
rpc::call_command("d.state_changed.set", cached_seconds, rpc::make_target(download));
rpc::call_command("d.state_counter.set", rpc::call_command_value("d.state_counter", rpc::make_target(download)), rpc::make_target(download));
// If initial seeding is complete, don't try it again when restarting.
+1 -1
View File
@@ -39,7 +39,7 @@ public:
using base_type::empty;
using base_type::size;
DownloadList() { }
DownloadList() = default;
void clear();
-67
View File
@@ -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
+2 -1
View File
@@ -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 -61
View File
@@ -1,79 +1,37 @@
// 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
#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());
h->set_url(url);
h->set_stream(s);
h->set_timeout(5 * 60);
HttpQueue::insert(const std::string& url, std::shared_ptr<std::ostream> stream) {
auto itr = base_type::insert(end(), torrent::net::HttpGet(url, stream));
iterator signal_itr = base_type::insert(end(), h.get());
for (auto& slot : m_signal_insert)
slot(*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));
itr->add_done_slot([this, itr]() { erase(itr); });
itr->add_failed_slot([this, itr](auto) { erase(itr); });
(*signal_itr)->start();
// TODO: Downloading http torrents doesn't seem to work.
// TODO: Quitting no longer works.
h.release();
torrent::net_thread::http_stack()->start_get(*itr);
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);
}
@@ -81,8 +39,6 @@ void
HttpQueue::clear() {
while (!empty())
erase(begin());
base_type::clear();
}
}
+10 -47
View File
@@ -1,56 +1,22 @@
// 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_HTTP_QUEUE_H
#define RTORRENT_CORE_HTTP_QUEUE_H
#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;
@@ -65,7 +31,7 @@ public:
using base_type::empty;
using base_type::size;
HttpQueue() {}
HttpQueue() = default;
~HttpQueue() { clear(); }
// Note that any slots connected to the CurlGet signals must be
@@ -73,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;
};
+58 -147
View File
@@ -7,7 +7,6 @@
#include <unistd.h>
#include <sys/select.h>
#include <rak/address_info.h>
#include <rak/error_number.h>
#include <rak/regex.h>
#include <rak/path.h>
#include <rak/string_manip.h>
@@ -17,8 +16,10 @@
#include <torrent/error.h>
#include <torrent/exceptions.h>
#include <torrent/object_stream.h>
#include <torrent/tracker_list.h>
#include <torrent/throttle.h>
#include <torrent/net/http_stack.h>
#include <torrent/net/network_config.h>
#include <torrent/net/socket_address.h>
#include <torrent/utils/log.h>
#include "rpc/parse_commands.h"
@@ -27,15 +28,13 @@
#include "utils/file_status_cache.h"
#include "globals.h"
#include "curl_get.h"
#include "control.h"
#include "download.h"
#include "download_factory.h"
#include "download_store.h"
#include "http_queue.h"
#include "manager.h"
#include "poll_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 {
@@ -51,15 +50,13 @@ Manager::push_log(const char* msg) {
}
Manager::Manager() :
m_hashingView(NULL),
m_log_important(torrent::log_open_log_buffer("important")),
m_log_complete(torrent::log_open_log_buffer("complete"))
{
m_downloadStore = new DownloadStore();
m_downloadList = new DownloadList();
m_fileStatusCache = new FileStatusCache();
m_httpQueue = new HttpQueue();
m_httpStack = new CurlStack();
m_log_important(torrent::log_open_log_buffer("important")),
m_log_complete(torrent::log_open_log_buffer("complete")) {
m_download_store = std::make_unique<DownloadStore>();
m_download_list = std::make_unique<DownloadList>();
m_file_status_cache = std::make_unique<FileStatusCache>();
m_http_queue = std::make_unique<HttpQueue>();
torrent::Throttle* unthrottled = torrent::Throttle::create_throttle();
unthrottled->set_max_rate(0);
@@ -68,19 +65,12 @@ Manager::Manager() :
Manager::~Manager() {
torrent::Throttle::destroy_throttle(m_throttles["NULL"].first);
delete m_downloadList;
// TODO: Clean up logs objects.
delete m_downloadStore;
delete m_httpQueue;
delete m_fileStatusCache;
}
void
Manager::set_hashing_view(View* v) {
if (v == NULL || m_hashingView != NULL)
throw torrent::internal_error("Manager::set_hashing_view(...) received NULL or is already set.");
if (v == nullptr || m_hashingView != nullptr)
throw torrent::internal_error("Manager::set_hashing_view(...) received nullptr or is already set.");
m_hashingView = v;
m_hashingView->signal_changed().push_back(std::bind(&Manager::receive_hashing_changed, this));
@@ -89,12 +79,12 @@ Manager::set_hashing_view(View* v) {
torrent::ThrottlePair
Manager::get_throttle(const std::string& name) {
ThrottleMap::const_iterator itr = m_throttles.find(name);
torrent::ThrottlePair throttles = (itr == m_throttles.end() ? torrent::ThrottlePair(NULL, NULL) : itr->second);
torrent::ThrottlePair throttles = (itr == m_throttles.end() ? torrent::ThrottlePair(nullptr, nullptr) : itr->second);
if (throttles.first == NULL)
if (throttles.first == nullptr)
throttles.first = torrent::up_throttle_global();
if (throttles.second == NULL)
if (throttles.second == nullptr)
throttles.second = torrent::down_throttle_global();
return throttles;
@@ -108,7 +98,10 @@ Manager::set_address_throttle(uint32_t begin, uint32_t end, torrent::ThrottlePai
torrent::ThrottlePair
Manager::get_address_throttle(const sockaddr* addr) {
return m_addressThrottles.get(rak::socket_address::cast_from(addr)->sa_inet()->address_h(), torrent::ThrottlePair(NULL, NULL));
if (addr->sa_family != AF_INET)
return torrent::ThrottlePair(nullptr, nullptr);
return m_addressThrottles.get(ntohl(reinterpret_cast<const sockaddr_in*>(addr)->sin_addr.s_addr), torrent::ThrottlePair(nullptr, nullptr));
}
int64_t
@@ -121,7 +114,7 @@ Manager::retrieve_throttle_value(const torrent::Object::string_type& name, bool
torrent::Throttle* throttle = up ? itr->second.first : itr->second.second;
// check whether the actual up/down throttle exist (one of the pair can be missing)
if (throttle == NULL)
if (throttle == nullptr)
return (int64_t)-1;
int64_t throttle_max = (int64_t)throttle->max_rate();
@@ -140,39 +133,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_httpStack);
m_httpQueue->set_slot_factory(std::bind(&CurlStack::new_object, m_httpStack));
CurlStack::global_init();
}
void
Manager::cleanup() {
m_httpStack->shutdown();
// Need to disconnect log signals? Not really since we won't receive
// any more.
m_downloadList->clear();
// When we implement asynchronous DNS lookups, we need to cancel them
// here before the torrent::* objects are deleted.
m_download_list->clear();
torrent::cleanup();
delete m_httpStack;
CurlStack::global_cleanup();
}
void
Manager::shutdown(bool force) {
if (!force)
std::for_each(m_downloadList->begin(), m_downloadList->end(), [this](Download* d) { m_downloadList->pause_default(d); });
for (auto d : *m_download_list)
m_download_list->pause_default(d);
else
std::for_each(m_downloadList->begin(), m_downloadList->end(), [this](Download* d) { m_downloadList->close_quick(d); });
for (auto d : *m_download_list)
m_download_list->close_quick(d);
}
void
@@ -185,15 +163,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.");
@@ -210,72 +184,7 @@ Manager::listen_open() {
return;
}
throw torrent::input_error("Could not open/bind port for listening: " + std::string(rak::error_number::current().c_str()));
}
std::string
Manager::bind_address() const {
return rak::socket_address::cast_from(torrent::connection_manager()->bind_address())->address_str();
}
void
Manager::set_bind_address(const std::string& addr) {
int err;
rak::address_info* ai;
if ((err = rak::address_info::get_address_info(addr.c_str(), PF_INET, SOCK_STREAM, &ai)) != 0 &&
(err = rak::address_info::get_address_info(addr.c_str(), PF_INET6, SOCK_STREAM, &ai)) != 0)
throw torrent::input_error("Could not set bind address: " + std::string(rak::address_info::strerror(err)) + ".");
try {
if (torrent::connection_manager()->listen_port() != 0) {
torrent::connection_manager()->listen_close();
torrent::connection_manager()->set_bind_address(ai->address()->c_sockaddr());
listen_open();
} else {
torrent::connection_manager()->set_bind_address(ai->address()->c_sockaddr());
}
m_httpStack->set_bind_address(!ai->address()->is_address_any() ? ai->address()->address_str() : std::string());
rak::address_info::free_address_info(ai);
} catch (torrent::input_error& e) {
rak::address_info::free_address_info(ai);
throw e;
}
}
std::string
Manager::local_address() const {
return rak::socket_address::cast_from(torrent::connection_manager()->local_address())->address_str();
}
void
Manager::set_local_address(const std::string& addr) {
int err;
rak::address_info* ai;
if ((err = rak::address_info::get_address_info(addr.c_str(), PF_INET, SOCK_STREAM, &ai)) != 0 &&
(err = rak::address_info::get_address_info(addr.c_str(), PF_INET6, SOCK_STREAM, &ai)) != 0)
throw torrent::input_error("Could not set local address: " + std::string(rak::address_info::strerror(err)) + ".");
try {
torrent::connection_manager()->set_local_address(ai->address()->c_sockaddr());
rak::address_info::free_address_info(ai);
} catch (torrent::input_error& e) {
rak::address_info::free_address_info(ai);
throw e;
}
}
std::string
Manager::proxy_address() const {
return rak::socket_address::cast_from(torrent::connection_manager()->proxy_address())->address_str();
throw torrent::input_error("Could not open/bind port for listening: " + std::string(std::strerror(errno)));
}
void
@@ -283,9 +192,9 @@ Manager::set_proxy_address(const std::string& addr) {
int port;
rak::address_info* ai;
char buf[addr.length() + 1];
std::string buf(addr.length() + 1, '\0');
int err = std::sscanf(addr.c_str(), "%[^:]:%i", buf, &port);
int err = std::sscanf(addr.c_str(), "%[^:]:%i", buf.data(), &port);
if (err <= 0)
throw torrent::input_error("Could not parse proxy address.");
@@ -293,13 +202,15 @@ Manager::set_proxy_address(const std::string& addr) {
if (err == 1)
port = 80;
if ((err = rak::address_info::get_address_info(buf, PF_INET, SOCK_STREAM, &ai)) != 0)
if ((err = rak::address_info::get_address_info(buf.data(), PF_INET, SOCK_STREAM, &ai)) != 0)
throw torrent::input_error("Could not set proxy address: " + std::string(rak::address_info::strerror(err)) + ".");
try {
ai->address()->set_port(port);
torrent::connection_manager()->set_proxy_address(ai->address()->c_sockaddr());
auto sa = torrent::sa_copy(ai->c_addrinfo()->ai_addr);
torrent::sap_set_port(sa, port);
torrent::config::network_config()->set_proxy_address(sa.get());
rak::address_info::free_address_info(ai);
@@ -373,8 +284,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"));
@@ -427,22 +338,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
@@ -463,8 +374,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);
@@ -475,15 +386,15 @@ 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.
for (View::iterator itr = m_hashingView->begin_visible(), last = m_hashingView->end_visible(); itr != last; ++itr) {
if ((*itr)->is_hash_checked())
throw torrent::internal_error("core::Manager::receive_hashing_changed() (*itr)->is_hash_checked().");
if ((*itr)->is_hash_checking() || (*itr)->is_hash_failed())
continue;
@@ -495,7 +406,7 @@ Manager::receive_hashing_changed() {
continue;
try {
m_downloadList->open_throw(*itr);
m_download_list->open_throw(*itr);
// Since the bitfield is allocated on loading of resume load or
// hash start, and unallocated on close, we know that if it it
+9 -25
View File
@@ -4,13 +4,11 @@
#include <iosfwd>
#include <memory>
#include <vector>
#include <torrent/utils/log_buffer.h>
#include <torrent/connection_manager.h>
#include <torrent/object.h>
#include "download_list.h"
#include "poll_manager.h"
#include "range_map.h"
namespace torrent {
@@ -35,18 +33,14 @@ public:
typedef DownloadList::iterator DListItr;
typedef utils::FileStatusCache FileStatusCache;
// typedef std::function<void (DownloadList::iterator)> slot_ready;
// typedef std::function<void ()> slot_void;
Manager();
~Manager();
DownloadList* download_list() { return m_downloadList; }
DownloadStore* download_store() { return m_downloadStore; }
FileStatusCache* file_status_cache() { return m_fileStatusCache; }
DownloadList* download_list() { return m_download_list.get(); }
DownloadStore* download_store() { return m_download_store.get(); }
FileStatusCache* file_status_cache() { return m_file_status_cache.get(); }
HttpQueue* http_queue() { return m_httpQueue; }
CurlStack* http_stack() { return m_httpStack; }
HttpQueue* http_queue() { return m_http_queue.get(); }
View* hashing_view() { return m_hashingView; }
void set_hashing_view(View* v);
@@ -63,19 +57,10 @@ 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();
std::string bind_address() const;
void set_bind_address(const std::string& addr);
std::string local_address() const;
void set_local_address(const std::string& addr);
std::string proxy_address() const;
void set_proxy_address(const std::string& addr);
void shutdown(bool force);
@@ -109,13 +94,12 @@ private:
void receive_http_failed(std::string msg);
void receive_hashing_changed();
DownloadList* m_downloadList;
DownloadStore* m_downloadStore;
FileStatusCache* m_fileStatusCache;
HttpQueue* m_httpQueue;
CurlStack* m_httpStack;
std::unique_ptr<DownloadList> m_download_list;
std::unique_ptr<DownloadStore> m_download_store;
std::unique_ptr<FileStatusCache> m_file_status_cache;
std::unique_ptr<HttpQueue> m_http_queue;
View* m_hashingView;
View* m_hashingView{};
ThrottleMap m_throttles;
AddressThrottleMap m_addressThrottles;
-91
View File
@@ -1,91 +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
#include "config.h"
#include <stdexcept>
#include <unistd.h>
#include <torrent/exceptions.h>
#include <torrent/poll_epoll.h>
#include <torrent/poll_kqueue.h>
#include <torrent/poll_select.h>
#include "globals.h"
#include "control.h"
#include "manager.h"
#include "poll_manager.h"
namespace core {
torrent::Poll*
create_poll() {
const char* poll_name = getenv("RTORRENT_POLL");
int maxOpen = sysconf(_SC_OPEN_MAX);
torrent::Poll* poll = NULL;
if (poll_name != NULL) {
if (!strcmp(poll_name, "epoll"))
poll = torrent::PollEPoll::create(maxOpen);
else if (!strcmp(poll_name, "kqueue"))
poll = torrent::PollKQueue::create(maxOpen);
else if (!strcmp(poll_name, "select"))
poll = torrent::PollSelect::create(maxOpen);
if (poll == NULL)
control->core()->push_log_std(std::string("Cannot enable '") + poll_name + "' based polling.");
}
if (poll != NULL)
control->core()->push_log_std(std::string("Using '") + poll_name + "' based polling.");
else if ((poll = torrent::PollEPoll::create(maxOpen)) != NULL)
control->core()->push_log_std("Using 'epoll' based polling.");
else if ((poll = torrent::PollKQueue::create(maxOpen)) != NULL)
control->core()->push_log_std("Using 'kqueue' based polling.");
else if ((poll = torrent::PollSelect::create(maxOpen)) != NULL)
control->core()->push_log_std("Using 'select' based polling.");
else
throw torrent::internal_error("Could not create any Poll object.");
return poll;
}
}
-52
View File
@@ -1,52 +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_POLL_MANAGER_H
#define RTORRENT_CORE_POLL_MANAGER_H
#include "curl_stack.h"
namespace torrent {
class Poll;
}
namespace core {
torrent::Poll* create_poll();
}
#endif
+3 -5
View File
@@ -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
@@ -57,7 +55,7 @@ class RangeMap : private std::map<Key, std::pair<Key, T>, Compare,
//std::allocator_traits<Alloc>::template rebind_alloc<std::pair<const Key, std::pair<Key, T>>>
public:
RangeMap() {}
RangeMap() = default;
RangeMap(const Compare& c) : base_type(c) {}
typedef typename base_type::iterator iterator;
+10 -12
View File
@@ -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) {}
@@ -113,13 +113,13 @@ struct view_downloads_filter : std::function<bool (Download*)> {
void
View::emit_changed() {
priority_queue_update(&taskScheduler, &m_delayChanged, cachedTime);
torrent::this_thread::scheduler()->update_wait_for(&m_delay_changed, 0ms);
}
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() {
@@ -127,7 +127,7 @@ View::~View() {
return;
clear_filter_on();
priority_queue_erase(&taskScheduler, &m_delayChanged);
torrent::this_thread::scheduler()->erase(&m_delay_changed);
}
void
@@ -138,18 +138,16 @@ 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;
set_last_changed(rak::timer());
m_delayChanged.slot() = std::bind(&View::emit_changed_now, this);
m_delay_changed.slot() = [this]() { emit_changed_now(); };
}
void
@@ -348,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));
+8 -8
View File
@@ -14,11 +14,11 @@
#define RTORRENT_CORE_VIEW_DOWNLOADS_H
#include <functional>
#include <list>
#include <string>
#include <vector>
#include <rak/timer.h>
#include <torrent/object.h>
#include <torrent/utils/scheduler.h>
#include "globals.h"
@@ -39,7 +39,7 @@ public:
using base_type::size_type;
View() {}
View() = default;
~View();
void initialize(const std::string& name);
@@ -113,8 +113,8 @@ public:
//
// Currently initialized to rak::timer(), though perhaps we should
// use cachedTimer.
rak::timer last_changed() const { return m_lastChanged; }
void set_last_changed(const rak::timer& t = ::cachedTime) { m_lastChanged = t; }
auto last_changed() const { return m_last_changed; }
void set_last_changed(std::chrono::microseconds t = torrent::this_thread::cached_time()) { m_last_changed = t; }
// Don't connect any slots until after initialize else it get's
// triggered when adding the Download's in DownloadList.
@@ -151,10 +151,10 @@ private:
torrent::Object m_event_added;
torrent::Object m_event_removed;
rak::timer m_lastChanged;
std::chrono::microseconds m_last_changed{};
signal_void m_signal_changed;
rak::priority_item m_delayChanged;
signal_void m_signal_changed;
torrent::utils::SchedulerEntry m_delay_changed;
};
} // namespace core
+5 -40
View File
@@ -1,39 +1,3 @@
// 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
#include "config.h"
#include <algorithm>
@@ -54,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();
}
@@ -92,7 +57,7 @@ void
ViewManager::sort(const std::string& name, uint32_t timeout) {
iterator viewItr = find_throw(name);
if ((*viewItr)->last_changed() + rak::timer::from_seconds(timeout) > cachedTime)
if ((*viewItr)->last_changed() + std::chrono::seconds(timeout) > torrent::this_thread::cached_time())
return;
// Should we rename sort, or add a seperate function?
@@ -124,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);
}
}
+3 -39
View File
@@ -1,39 +1,3 @@
// 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_VIEW_MANAGER_H
#define RTORRENT_CORE_VIEW_MANAGER_H
@@ -48,12 +12,12 @@ class ViewManager : public rak::unordered_vector<View*> {
public:
typedef rak::unordered_vector<View*> base_type;
typedef std::list<std::string> filter_args;
using base_type::iterator;
using base_type::const_iterator;
using base_type::reverse_iterator;
using base_type::const_reverse_iterator;
using base_type::size_type;
using base_type::begin;
@@ -64,7 +28,7 @@ public:
using base_type::empty;
using base_type::size;
ViewManager() {}
ViewManager() = default;
~ViewManager() { clear(); }
// Ffff... Just throwing together an interface, need to think some
+1 -1
View File
@@ -35,7 +35,7 @@ public:
static const int color_invalid = ~int();
static const int color_default = 0;
Attributes() {}
Attributes() = default;
Attributes(const char* pos, int attr, int col) :
m_position(pos), m_attributes(attr), m_colors(col) {}
Attributes(const char* pos, const Attributes& old) :
+2 -2
View File
@@ -106,7 +106,7 @@ Canvas::build_colors() {
return;
// basic color names, index maps to ncurses COLOR_*
static const char* color_names[] = {
static constexpr std::array color_names{
"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"};
// Those hold the background colors of "odd" and "even"
@@ -170,7 +170,7 @@ Canvas::build_colors() {
// Check that fg & bg color index is valid
if ((color[0] != -1 && color[0] >= get_colors()) || (color[1] != -1 && color[1] >= get_colors())) {
char buf[33];
sprintf(buf, "%d", get_colors());
snprintf(buf, 33, "%d", get_colors());
Canvas::cleanup();
throw torrent::input_error(color_def + ": your terminal only supports " + buf + " colors.");
}
+7 -3
View File
@@ -1,6 +1,7 @@
#ifndef RTORRENT_DISPLAY_CANVAS_H
#define RTORRENT_DISPLAY_CANVAS_H
#include <cstdarg>
#include <string>
#include <unordered_map>
#include <vector>
@@ -136,7 +137,8 @@ Canvas::resize_term(std::pair<int, int> dim) {
inline unsigned int
Canvas::get_x() {
int x, __UNUSED y;
int x;
[[maybe_unused]] int y;
if (!m_isDaemon) {
getyx(m_window, y, x);
} else {
@@ -158,7 +160,8 @@ Canvas::get_y() {
inline unsigned int
Canvas::width() {
int x, __UNUSED y;
int x;
[[maybe_unused]] int y;
if (!m_isDaemon) {
getmaxyx(m_window, y, x);
} else {
@@ -259,7 +262,8 @@ Canvas::set_default_attributes(int attr) {
inline int
Canvas::get_screen_width() {
int x, __UNUSED y;
int x;
[[maybe_unused]] int y;
if (!m_isDaemon) {
getmaxyx(stdscr, y, x);
} else {
+3 -2
View File
@@ -1,6 +1,7 @@
#ifndef RTORRENT_DISPLAY_COLOR_MAP_H
#define RTORRENT_DISPLAY_COLOR_MAP_H
#include <array>
#include <map>
#include <curses.h>
@@ -26,8 +27,8 @@ enum ColorKind {
RCOLOR_MAX,
};
static const char* color_vars[RCOLOR_MAX] = {
0,
static const std::array<const char*, RCOLOR_MAX> color_vars{
nullptr,
"ui.color.title",
"ui.color.footer",
"ui.color.focus",
+2 -13
View File
@@ -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"
@@ -47,15 +45,6 @@
namespace display {
Frame::Frame() :
m_type(TYPE_NONE),
m_positionX(0),
m_positionY(0),
m_width(0),
m_height(0) {
}
bool
Frame::is_width_dynamic() const {
switch (m_type) {
+8 -12
View File
@@ -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
@@ -56,7 +54,7 @@ public:
};
struct bounds_type {
bounds_type() {}
bounds_type() = default;
bounds_type(extent_type minW, extent_type minH, extent_type maxW, extent_type maxH) :
minWidth(minW), minHeight(minH), maxWidth(maxW), maxHeight(maxH) {}
@@ -74,8 +72,6 @@ public:
static const size_type max_size = 5;
Frame();
bool is_width_dynamic() const;
bool is_height_dynamic() const;
@@ -116,12 +112,12 @@ private:
inline void balance_row(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
inline void balance_column(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
Type m_type;
Type m_type{TYPE_NONE};
uint32_t m_positionX;
uint32_t m_positionY;
uint32_t m_width;
uint32_t m_height;
uint32_t m_positionX{};
uint32_t m_positionY{};
uint32_t m_width{};
uint32_t m_height{};
union {
Window* m_window;
+29 -60
View File
@@ -1,39 +1,3 @@
// 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
#include "config.h"
#include <stdexcept>
@@ -46,74 +10,79 @@
namespace display {
Manager::Manager() :
m_forceRedraw(false) {
Manager::Manager() {
m_scheduler.external_set_thread_id(std::this_thread::get_id());
m_taskUpdate.slot() = std::bind(&Manager::receive_update, this);
m_task_update.slot() = std::bind(&Manager::receive_update, this);
}
Manager::~Manager() {
priority_queue_erase(&taskScheduler, &m_taskUpdate);
torrent::this_thread::scheduler()->erase(&m_task_update);
}
void
Manager::force_redraw() {
m_forceRedraw = true;
m_force_redraw = true;
}
void
Manager::schedule(Window* w, rak::timer t) {
rak::priority_queue_update(&m_scheduler, w->task_update(), t);
schedule_update(50000);
Manager::schedule(Window* w, std::chrono::microseconds t) {
m_scheduler.external_set_cached_time(torrent::this_thread::cached_time());
m_scheduler.update_wait_until(w->task_update(), t);
schedule_update(50ms);
}
void
Manager::unschedule(Window* w) {
rak::priority_queue_erase(&m_scheduler, w->task_update());
schedule_update(50000);
m_scheduler.external_set_cached_time(torrent::this_thread::cached_time());
m_scheduler.erase(w->task_update());
schedule_update(50ms);
}
void
Manager::adjust_layout() {
Canvas::redraw_std();
m_rootFrame.balance(0, 0, Canvas::get_screen_width(), Canvas::get_screen_height());
m_root_frame.balance(0, 0, Canvas::get_screen_width(), Canvas::get_screen_height());
schedule_update(0);
schedule_update(0ms);
}
void
Manager::receive_update() {
if (m_forceRedraw) {
m_forceRedraw = false;
if (m_force_redraw) {
m_force_redraw = false;
display::Canvas::resize_term(display::Canvas::term_size());
Canvas::redraw_std();
adjust_layout();
m_rootFrame.redraw();
m_root_frame.redraw();
}
Canvas::refresh_std();
rak::priority_queue_perform(&m_scheduler, cachedTime);
m_rootFrame.refresh();
m_scheduler.external_perform(torrent::this_thread::cached_time());
m_root_frame.refresh();
Canvas::do_update();
m_timeLastUpdate = cachedTime;
schedule_update(50000);
m_time_last_update = torrent::this_thread::cached_time();
schedule_update(50ms);
}
void
Manager::schedule_update(uint32_t minInterval) {
Manager::schedule_update(std::chrono::microseconds min_interval) {
if (m_scheduler.empty()) {
rak::priority_queue_erase(&taskScheduler, &m_taskUpdate);
torrent::this_thread::scheduler()->erase(&m_task_update);
return;
}
if (!m_taskUpdate.is_queued() || m_taskUpdate.time() > m_scheduler.top()->time()) {
rak::priority_queue_update(&taskScheduler, &m_taskUpdate, std::max(m_scheduler.top()->time(), m_timeLastUpdate + minInterval));
}
if (m_task_update.is_scheduled() && m_task_update.time() <= m_scheduler.front()->time())
return;
torrent::this_thread::scheduler()->update_wait_until(&m_task_update, std::max(m_scheduler.front()->time(), m_time_last_update + min_interval));
}
}
+9 -48
View File
@@ -1,44 +1,7 @@
// 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_MANAGER_H
#define RTORRENT_DISPLAY_MANAGER_H
#include <list>
#include <rak/priority_queue_default.h>
#include <torrent/utils/scheduler.h>
#include "frame.h"
@@ -53,26 +16,24 @@ public:
void force_redraw();
void schedule(Window* w, rak::timer t);
void schedule(Window* w, std::chrono::microseconds t);
void unschedule(Window* w);
void adjust_layout();
void receive_update();
// New interface.
Frame* root_frame() { return &m_rootFrame; }
Frame* root_frame() { return &m_root_frame; }
private:
void schedule_update(uint32_t minInterval);
void schedule_update(std::chrono::microseconds min_interval);
bool m_forceRedraw;
rak::timer m_timeLastUpdate;
bool m_force_redraw{false};
Frame m_root_frame;
rak::priority_queue_default m_scheduler;
rak::priority_item m_taskUpdate;
// New interface.
Frame m_rootFrame;
std::chrono::microseconds m_time_last_update{};
torrent::utils::ExternalScheduler m_scheduler;
torrent::utils::SchedulerEntry m_task_update;
};
}
+4 -6
View File
@@ -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
@@ -51,8 +49,8 @@ public:
static const extent_type extent_full = ~extent_type();
TextElement() {}
virtual ~TextElement() {}
TextElement() = default;
virtual ~TextElement() = default;
// The last element must point to a valid memory location into which
// the caller must write a '\0' to terminate the c string. The
+10 -11
View File
@@ -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;
}
+4 -7
View File
@@ -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
@@ -61,7 +59,6 @@ public:
using base_type::push_back;
TextElementList() : m_column(0), m_columnWidth(0) {}
virtual ~TextElementList() { clear(); }
void clear();
@@ -74,8 +71,8 @@ public:
virtual extent_type max_length();
private:
unsigned int m_column;
extent_type* m_columnWidth;
unsigned int m_column{};
extent_type* m_columnWidth{};
};
}
+8 -10
View File
@@ -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"
@@ -52,16 +50,16 @@ TextElementStringBase::print(char* first, char* last, Canvas::attributes_list* a
return first;
if (m_flags & flag_escape_hex) {
char buffer[last - first];
char* bufferLast = copy_string(buffer, buffer + (last - first), target);
auto buffer = std::make_unique<char[]>(last - first);
char* bufferLast = copy_string(buffer.get(), buffer.get() + (last - first), target);
first = rak::transform_hex(buffer, bufferLast, first, last);
first = rak::transform_hex(buffer.get(), bufferLast, first, last);
} else if (m_flags & flag_escape_html) {
char buffer[last - first];
char* bufferLast = copy_string(buffer, buffer + (last - first), target);
auto buffer = std::make_unique<char[]>(last - first);
char* bufferLast = copy_string(buffer.get(), buffer.get() + (last - first), target);
first = rak::copy_escape_html(buffer, bufferLast, first, last);
first = rak::copy_escape_html(buffer.get(), bufferLast, first, last);
} else {
first = copy_string(first, last, target);
+2 -4
View File
@@ -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
+10 -43
View File
@@ -1,45 +1,12 @@
// 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
#include "config.h"
#include "display/text_element_value.h"
#include <ctime>
#include <torrent/utils/chrono.h>
#include "globals.h"
#include "text_element_value.h"
namespace display {
@@ -47,7 +14,7 @@ namespace display {
void
TextElement::push_attribute(Canvas::attributes_list* attributes, Attributes value) {
Attributes base = attributes->back();
if (value.colors() == Attributes::color_invalid)
value.set_colors(base.colors());
@@ -69,12 +36,12 @@ TextElementValueBase::print(char* first, char* last, Canvas::attributes_list* at
// Transform the value if needed.
if (m_flags & flag_elapsed)
val = cachedTime.seconds() - val;
val = torrent::this_thread::cached_seconds().count() - val;
else if (m_flags & flag_remaining)
val = val - cachedTime.seconds();
val = val - torrent::this_thread::cached_seconds().count();
if (m_flags & flag_usec)
val = rak::timer(val).seconds();
val = torrent::utils::cast_seconds(std::chrono::microseconds(val)).count();
// Print the value.
if (first == last) {
@@ -108,7 +75,7 @@ TextElementValueBase::print(char* first, char* last, Canvas::attributes_list* at
} else if (m_flags & flag_date) {
time_t t = val;
std::tm *u = std::gmtime(&t);
if (u == NULL)
return first;
@@ -117,7 +84,7 @@ TextElementValueBase::print(char* first, char* last, Canvas::attributes_list* at
} else if (m_flags & flag_time) {
time_t t = val;
std::tm *u = std::gmtime(&t);
if (u == NULL)
return first;
+2 -38
View File
@@ -1,39 +1,3 @@
// 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_TEXT_ELEMENT_VALUE_H
#define RTORRENT_DISPLAY_TEXT_ELEMENT_VALUE_H
@@ -86,7 +50,7 @@ public:
virtual extent_type max_length() { return 12; }
private:
virtual int64_t value(void* object) { return m_value; }
virtual int64_t value([[maybe_unused]] void* object) { return m_value; }
int64_t m_value;
};
@@ -104,7 +68,7 @@ public:
virtual extent_type max_length() { return 12; }
private:
virtual int64_t value(void* object) { return m_slot(); }
virtual int64_t value([[maybe_unused]] void* object) { return m_slot(); }
slot_type m_slot;
};
+48 -48
View File
@@ -1,36 +1,36 @@
#include "config.h"
#include "display/utils.h"
#include <cstring>
#include <cstdio>
#include <sstream>
#include <iomanip>
#include <rak/socket_address.h>
#include <rak/timer.h>
#include <torrent/exceptions.h>
#include <torrent/connection_manager.h>
#include <torrent/rate.h>
#include <torrent/throttle.h>
#include <torrent/torrent.h>
#include <torrent/tracker_list.h>
#include <torrent/tracker/tracker.h>
#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/net/network_config.h>
#include <torrent/net/socket_address.h>
#include <torrent/peer/client_info.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*
print_string(char* first, char* last, char* str) {
print_string(char* first, char* last, const char* str) {
if (first == last)
return first;
@@ -79,17 +79,9 @@ print_ddmmyyyy(char* first, char* last, time_t t) {
return print_buffer(first, last, "%02u/%02u/%04u", u->tm_mday, (u->tm_mon + 1), (1900 + u->tm_year));
}
char*
print_address(char* first, char* last, const rak::socket_address* sa) {
if (!sa->address_c_str(first, last - first))
return first;
return std::find(first, last, '\0');
}
inline char*
print_address(char* first, char* last, const sockaddr* sa) {
return print_address(first, last, rak::socket_address::cast_from(sa));
return print_string(first, last, torrent::sa_addr_str(sa).c_str());
}
char*
@@ -112,7 +104,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),
@@ -160,14 +152,18 @@ print_download_status(char* first, char* last, core::Download* d) {
first = print_buffer(first, last, "Checking hash [%2i%%]",
(d->download()->chunks_hashed() * 100) / d->download()->file_list()->size_chunks());
} else if (d->tracker_list()->has_active_not_scrape()) {
torrent::TrackerList::iterator itr =
std::find_if(d->tracker_list()->begin(), d->tracker_list()->end(),
std::mem_fn(&torrent::tracker::Tracker::is_busy_not_scrape));
auto status = itr->status();
} else if (d->tracker_controller().has_active_trackers_not_scrape()) {
auto tracker = d->tracker_controller().find_if([](const auto& t) {
return t.is_busy_not_scrape();
});
first = print_buffer(first, last, "Tracker[%i:%i]: Connecting to %s %s",
itr->group(), std::distance(d->tracker_list()->begin(), itr), itr->url().c_str(), status.c_str());
if (tracker.is_valid()) {
auto status = tracker.status();
first = print_buffer(first, last, "Tracker[%i]: Connecting to %s %s", tracker.group(), tracker.url().c_str(), status.c_str());
} else {
first = print_buffer(first, last, "Tracker: Connecting ...");
}
} else if (!d->message().empty()) {
first = print_buffer(first, last, "%s", d->message().c_str());
@@ -185,7 +181,7 @@ print_download_status(char* first, char* last, core::Download* d) {
char*
print_download_column_compact(char* first, char* last) {
first = print_buffer(first, last, " %-64.64s", "Name");
first = print_buffer(first, last, "| Status | Downloaded | Size | Done | Up Rate | Down Rate | Uploaded | ETA | Ratio| Misc ");
first = print_buffer(first, last, "| Status | Downloaded | Size | Done | Up Rate | Down Rate | Uploaded | ETA | Ratio | Misc ");
if (first > last)
throw torrent::internal_error("print_download_column_compact(...) wrote past end of the buffer.");
@@ -201,7 +197,7 @@ print_download_info_compact(char* first, char* last, core::Download* d) {
if (!d->download()->info()->is_open())
first = print_buffer(first, last, " CLOSED ");
else if (!d->download()->info()->is_active())
first = print_buffer(first, last, " OPEN ");
first = print_buffer(first, last, " OPEN ");
else
first = print_buffer(first, last, " ");
@@ -221,12 +217,14 @@ print_download_info_compact(char* first, char* last, core::Download* d) {
first = print_buffer(first, last, "| %7.1f MB ", (double)d->info()->up_rate()->total() / (1 << 20));
first = print_buffer(first, last, "| ");
if (d->download()->info()->is_active() && !d->is_done())
if (d->download()->info()->is_active() && !d->is_done()) {
first = print_download_time_left(first, last, d);
else
first = print_buffer(first, last, " ");
first = print_buffer(first, last, " ");
} else {
first = print_buffer(first, last, " ");
}
first = print_buffer(first, last, "| %4.2f ", (double)rpc::call_command_value("d.ratio", rpc::make_target(d)) / 1000.0);
first = print_buffer(first, last, "| %5.2f ", (double)rpc::call_command_value("d.ratio", rpc::make_target(d)) / 1000.0);
first = print_buffer(first, last, "| %c%c",
rpc::call_command_string("d.tied_to_file", rpc::make_target(d)).empty() ? ' ' : 'T',
rpc::call_command_value("d.ignore_commands", rpc::make_target(d)) == 0 ? ' ' : 'I',
@@ -290,15 +288,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
@@ -316,10 +313,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;
@@ -328,7 +325,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
@@ -379,20 +375,24 @@ print_status_info(char* first, char* last) {
first = print_buffer(first, last, " KB]");
first = print_buffer(first, last, " [Port: %i]", (unsigned int)torrent::connection_manager()->listen_port());
first = print_buffer(first, last, " [Port: %i]", (unsigned int)torrent::config::network_config()->listen_port());
if (!rak::socket_address::cast_from(torrent::connection_manager()->local_address())->is_address_any()) {
auto local_address = torrent::config::network_config()->local_address_best_match();
if (!torrent::sa_is_any(local_address.get())) {
first = print_buffer(first, last, " [Local ");
first = print_address(first, last, torrent::connection_manager()->local_address());
first = print_address(first, last, local_address.get());
first = print_buffer(first, last, "]");
}
if (first > last)
throw torrent::internal_error("print_status_info(...) wrote past end of the buffer.");
if (!rak::socket_address::cast_from(torrent::connection_manager()->bind_address())->is_address_any()) {
auto bind_address = torrent::config::network_config()->bind_address_best_match();
if (!torrent::sa_is_any(bind_address.get())) {
first = print_buffer(first, last, " [Bind ");
first = print_address(first, last, torrent::connection_manager()->bind_address());
first = print_address(first, last, bind_address.get());
first = print_buffer(first, last, "]");
}
@@ -410,14 +410,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()->size(),
torrent::net_thread::http_stack()->max_total_connections());
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
View File
@@ -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;
+25 -49
View File
@@ -1,70 +1,36 @@
// 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
#include "config.h"
#include <stdexcept>
#include "window.h"
#include <stdexcept>
#include <torrent/utils/chrono.h>
namespace display {
Window::SlotTimer Window::m_slotSchedule;
Window::SlotWindow Window::m_slotUnschedule;
Window::Slot Window::m_slotAdjust;
Window::SlotTimer Window::m_slot_schedule;
Window::SlotWindow Window::m_slot_unschedule;
Window::Slot Window::m_slot_adjust;
// When constructing the window we set flag_offscreen so that redraw
// doesn't get triggered until after a successful Frame::balance call.
Window::Window(Canvas* canvas, int flags, extent_type minWidth, extent_type minHeight, extent_type maxWidth, extent_type maxHeight) :
Window::Window(Canvas* canvas, int flags, extent_type min_width, extent_type min_height, extent_type max_width, extent_type max_height) :
m_canvas(canvas),
m_flags(flags | flag_offscreen),
m_minWidth(minWidth),
m_minHeight(minHeight),
m_min_width(min_width),
m_min_height(min_height),
m_maxWidth(maxWidth),
m_maxHeight(maxHeight) {
m_max_width(max_width),
m_max_height(max_height) {
m_taskUpdate.slot() = std::bind(&Window::redraw, this);
m_task_update.slot() = [this] { redraw(); };
}
Window::~Window() {
if (is_active())
m_slotUnschedule(this);
m_slot_unschedule(this);
delete m_canvas;
}
@@ -82,7 +48,7 @@ Window::set_active(bool state) {
} else {
m_flags &= ~flag_active;
m_slotUnschedule(this);
m_slot_unschedule(this);
}
}
@@ -97,4 +63,14 @@ Window::resize(int x, int y, int w, int h) {
m_canvas->resize(x, y, w, h);
}
void
Window::schedule_update(unsigned int wait_seconds) {
if (wait_seconds == 0) {
m_slot_schedule(this, torrent::utils::ceil_seconds(torrent::this_thread::cached_time() + 100ms));
return;
}
m_slot_schedule(this, torrent::utils::ceil_seconds(torrent::this_thread::cached_time() + 1s*wait_seconds));
}
}
+27 -60
View File
@@ -1,44 +1,9 @@
// 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_WINDOW_BASE_H
#define RTORRENT_WINDOW_BASE_H
#include <rak/timer.h>
#include <functional>
#include <torrent/utils/scheduler.h>
#include <torrent/utils/thread.h>
#include "canvas.h"
#include "globals.h"
@@ -51,9 +16,9 @@ class Window {
public:
typedef uint32_t extent_type;
typedef std::function<void()> Slot;
typedef std::function<void(Window*)> SlotWindow;
typedef std::function<void(Window*, rak::timer)> SlotTimer;
typedef std::function<void()> Slot;
typedef std::function<void(Window*)> SlotWindow;
typedef std::function<void(Window*, std::chrono::microseconds)> SlotTimer;
static const int flag_active = (1 << 0);
static const int flag_offscreen = (1 << 1);
@@ -85,19 +50,19 @@ public:
bool is_bottom() const { return m_flags & flag_bottom; }
void set_bottom(bool state) { if (state) m_flags |= flag_bottom; else m_flags &= ~flag_bottom; }
bool is_width_dynamic() const { return m_maxWidth > m_minWidth; }
bool is_height_dynamic() const { return m_maxHeight > m_minHeight; }
bool is_width_dynamic() const { return m_max_width > m_min_width; }
bool is_height_dynamic() const { return m_max_height > m_min_height; }
// Do not call mark_dirty() from withing redraw() as it may cause
// infinite looping in the display scheduler.
bool is_dirty() { return m_taskUpdate.is_queued(); }
void mark_dirty() { if (!is_active()) return; m_slotSchedule(this, cachedTime); }
bool is_dirty() { return m_task_update.is_scheduled(); }
void mark_dirty() { if (!is_active()) return; m_slot_schedule(this, torrent::this_thread::cached_time()); }
extent_type min_width() const { return m_minWidth; }
extent_type min_height() const { return m_minHeight; }
extent_type min_width() const { return m_min_width; }
extent_type min_height() const { return m_min_height; }
extent_type max_width() const { return std::max(m_maxWidth, m_minWidth); }
extent_type max_height() const { return std::max(m_maxHeight, m_minHeight); }
extent_type max_width() const { return std::max(m_max_width, m_min_width); }
extent_type max_height() const { return std::max(m_max_height, m_min_height); }
extent_type width() const { return m_canvas->width(); }
extent_type height() const { return m_canvas->height(); }
@@ -107,32 +72,34 @@ public:
virtual void redraw() = 0;
rak::priority_item* task_update() { return &m_taskUpdate; }
auto task_update() { return &m_task_update; }
// Slot for adjust and refresh.
static void slot_schedule(SlotTimer s) { m_slotSchedule = s; }
static void slot_unschedule(SlotWindow s) { m_slotUnschedule = s; }
static void slot_adjust(Slot s) { m_slotAdjust = s; }
static void slot_schedule(SlotTimer s) { m_slot_schedule = s; }
static void slot_unschedule(SlotWindow s) { m_slot_unschedule = s; }
static void slot_adjust(Slot s) { m_slot_adjust = s; }
protected:
Window(const Window&);
void operator = (const Window&);
static SlotTimer m_slotSchedule;
static SlotWindow m_slotUnschedule;
static Slot m_slotAdjust;
void schedule_update(unsigned int wait_seconds = 0);
static SlotTimer m_slot_schedule;
static SlotWindow m_slot_unschedule;
static Slot m_slot_adjust;
Canvas* m_canvas;
int m_flags;
extent_type m_minWidth;
extent_type m_minHeight;
extent_type m_min_width;
extent_type m_min_height;
extent_type m_maxWidth;
extent_type m_maxHeight;
extent_type m_max_width;
extent_type m_max_height;
rak::priority_item m_taskUpdate;
torrent::utils::SchedulerEntry m_task_update;
};
}

Some files were not shown because too many files have changed in this diff Show More