Compare commits

...

158 Commits

Author SHA1 Message Date
rakshasa 34bc18940a Added missing color_map.h to Makefile.am. 2025-03-28 19:53:52 +01:00
rakshasa cde78f2353 Removed rak/functional.h from Makefile.am. 2025-03-28 19:14:57 +01:00
rakshasa cc59125116 Updated to release 0.15.2. 2025-03-28 19:14:57 +01:00
rakshasa 8ac31afd06 Fixed tinyxml2 compile error. 2025-03-28 16:07:55 +01:00
rakshasa 8d991b4ce5 Added 'system.files.session.fdatasync' config option. 2025-03-28 15:32:57 +01:00
Jari Sundell 3a227c190f Added system.files.advise_random.set command. 2025-03-28 19:21:25 +09:00
Jari Sundell 9a2ce2b231 Changes to support UDNS. 2025-03-27 21:36:10 +09:00
Jari Sundell f33fc331ce Thread-safe improvements to dht/tracker code and reorganized thread objects. 2025-03-13 22:15:12 +09:00
rakshasa 47af28aecd Cleaned up ui/root. 2025-03-11 14:13:05 +01:00
chros c6ebdf876a Fix possible crash with save_input_history (See #26) 2025-03-11 14:13:05 +01:00
rakshasa 5797ed9e7a Added new tracker list commands. 2025-03-11 13:45:18 +01:00
nick black 9465c94b31 Don't recommend obsolete option 'safe_sync'. 2025-03-11 13:24:17 +01:00
Jari Sundell 0adfc17335 Compatibility fixes with thread-safe list tracker changes. 2025-03-11 20:38:04 +09:00
rakshasa 37a5b7bccb Moved torrent::Tracker to torrent::tracker::Tracker. 2025-02-27 19:24:35 +01:00
rakshasa 80ef2e076d Fix trcker command. 2025-02-25 17:25:54 +01:00
rakshasa 4ac7313ff1 Pass tracker key at download creation. 2025-02-23 13:25:48 +01:00
rakshasa 6139217033 Compatibility with new tracker enum. 2025-02-12 14:38:08 +01:00
rakshasa 89b35af7a6 Fixed threaded tracker feature compatibility. 2025-02-11 09:01:52 +01:00
Auska 851ac469c3 Fix xmlrpc namespace 2025-02-03 17:37:01 +01:00
Rakshasa 1811248691 Add checks for liblua-*.so.0 for alpine compatibility. 2025-02-03 16:21:30 +00:00
rakshasa bacf60af89 Call atomic tracker state. 2025-02-02 21:03:26 +01:00
Jari Sundell 1f01b7e94d Fix various macos issues. 2025-01-28 00:18:41 +09:00
rakshasa d514e525ca Minor fixes. 2025-01-20 14:49:18 +01:00
pyroscope b2b723f248 close_low_diskspace.normal: use proper namespace (std) 2025-01-20 14:49:18 +01:00
pyroscope e3ab913f9a new method close_low_diskspace.normal
Skip downloads with prio=3 (high) when checking for disk space
2025-01-20 14:49:18 +01:00
Peter Woodman 787e23a25d clang-tidy: ignore third-party code nlohmann/json.h 2025-01-20 12:31:04 +01:00
kannibalox 9f48226663 Add JSON-RPC capability
Inline nlohmann/json for the JSON parsing itself, and handle requests
with the same SCGI interface as XML-RPC.

Based off the work in https://github.com/jesec/rtorrent
2025-01-20 12:31:04 +01:00
stickz 78915746ee Bump c++ standard to 17
This pull request bumps the rTorrent c++ standard from 17. This resolves various undefined behavior which could occur.
2025-01-19 14:59:02 +01:00
stickz e7fc891f11 cleanup: Changes for c++17
This cleanup adjusts the rTorrent code to comply with c++17 standard. It also simplifies various parts of the code.
2025-01-18 20:15:20 +01:00
Jari Sundell 2e0a417367 Add optional Lua scripting capabilties - kannibalox@gmail.com 2025-01-19 04:02:06 +09:00
Jari Sundell b5a6ee33a1 Merge pull request #1375 from rakshasa/fix/github-workflows
Added separate workflow for clang-tidy static analysis.
2025-01-15 08:45:06 +01:00
rakshasa 3378355b64 Added separate workflow for clang-tidy static analysis. 2025-01-15 07:38:30 +00:00
Jari Sundell 6f5d06907b Merge pull request #1374 from stickz/remove-rak-functional
cleanup: Remove rak/functional.h
2025-01-13 10:06:07 +01:00
stickz 712e7e5db0 cleanup: Remove rak/functional.h
This commit replaces the `rak/functional.h` features with lambdas and std functions.

There was one instance with `std::sort` where the comparison operator was always evaluating to false and it wasn't sorting anything. This is removed in favour of the default comparison operator.

`std::sort(transferChunks.begin(), transferChunks.end());`
2025-01-12 14:30:01 -05:00
Jari Sundell 2b73c92a3e Merge pull request #1372 from stickz/remove-rak-mem-fun
cleanup: Remove rak mem_fun
2025-01-12 18:43:15 +01:00
stickz c5563d65c5 cleanup: Remove rak mem_fun
This commit removes rak:mem_fun and replaces it with std::function and lambdas.
2025-01-12 10:18:50 -05:00
Jari Sundell d412caea66 Merge pull request #1370 from stickz/remove-rak-call-delete
cleanup: Replace rak::call_delete with lambdas
2025-01-12 11:40:10 +01:00
stickz 9c92bfc7e2 cleanup: Remove rak::call_delete 2025-01-11 21:22:40 -05:00
Jari Sundell 4a074adc7b Merge pull request #1369 from rakshasa/kannibalox-feature/color
Kannibalox feature/color
2025-01-09 17:12:23 +01:00
rakshasa 3bf494dbc6 Merge branch 'master' into kannibalox-feature/color 2025-01-09 15:55:11 +00:00
rakshasa b193fedc65 Moved inlined functions out of class declaration. 2025-01-09 15:51:04 +00:00
kannibalox 6c5a6a3bb3 Manually include config.h for clang-tidy
Specifically this fixes errors related to undefined macros in headers, since those aren't recorded
in compile_commands.json
2025-01-09 15:28:20 +00:00
kannibalox 7534b02815 Add page up/down and home/end bindings to download list 2025-01-09 15:28:16 +00:00
kannibalox 6d8c214d09 Manually include config.h for clang-tidy
Specifically this fixes errors related to undefined macros in headers, since those aren't recorded
in compile_commands.json
2025-01-08 19:49:59 +01:00
rakshasa 525b038dbb Inline test data instead of using separate text file. 2025-01-08 17:58:09 +00:00
kannibalox 06741a7578 Update XMLRPC unit tests to include <data> for arrays 2025-01-08 17:58:09 +00:00
rakshasa 4cc79590be Release 0.15.1. 2025-01-08 17:58:09 +00:00
simonc56 452397b8af tinyxml2: array with data for dict type 2025-01-08 17:58:09 +00:00
simonc56 c9a8a1e35c tinyxml2: in xmlrpc an array must include values in a data element 2025-01-08 17:58:09 +00:00
stickz 8f77d87994 tinyxml2: Change from i4 to i8
We need to follow the same specification as xmlrpc-c until we deprecate it. It is breaking various software such as sonarr. We can't have xmlrpc using i8 and tinyxml2 using i4, while we allow both to be used.
2025-01-08 17:58:09 +00:00
rakshasa 842edaa201 Added missing base64.h header. 2025-01-08 17:58:09 +00:00
kannibalox 4876301cf4 Add page up/down and home/end bindings to download list 2025-01-08 18:46:09 +01:00
rakshasa c2c6a4be26 Inline test data instead of using separate text file. 2025-01-03 06:04:09 +09:00
kannibalox 350d03ca04 Update XMLRPC unit tests to include <data> for arrays 2025-01-03 05:26:55 +09:00
rakshasa 31602917b7 Release 0.15.1. 2025-01-01 12:59:06 +00:00
rakshasa a9898c6ef6 Merge branch 'master' of github.com:rakshasa/rtorrent 2025-01-01 12:34:15 +00:00
simonc56 2bf81aa8f5 tinyxml2: array with data for dict type 2025-01-01 21:33:30 +09:00
simonc56 a9c0b65b9d tinyxml2: in xmlrpc an array must include values in a data element 2025-01-01 21:33:30 +09:00
stickz 73fed24459 tinyxml2: Change from i4 to i8
We need to follow the same specification as xmlrpc-c until we deprecate it. It is breaking various software such as sonarr. We can't have xmlrpc using i8 and tinyxml2 using i4, while we allow both to be used.
2025-01-01 21:32:23 +09:00
rakshasa f906e9a966 Added missing base64.h header. 2025-01-01 12:15:54 +00:00
kannibalox 090b3889ce Add color support for the TUI
Closes #398
2024-12-26 16:32:42 -05:00
rakshasa 68fdb86c72 Update configure.ac. 2024-12-26 16:50:18 +00:00
rakshasa 6b8a285e75 Release v0.15.0. 2024-12-26 16:29:16 +00:00
kannibalox 8f0331625a Correctly handle commands that are flagged as not using targets
Fixes #1346
2024-12-27 01:00:23 +09:00
stickz 3c65afcf8c tinyxml2: Resolve LTO issues
We can't have two classes with the same name in the rpc namespace. It causes ODR and lto-type-mismatches when compiling rTorrent with LTO.

This pull request addresses the problem by renaming the `xmlrpc_error` error class to `xmlrpc_error_c` in the xmlrpc_c file.
2024-12-27 00:55:29 +09:00
kannibalox cd9948a4a8 Remove/replace functional_fun.h functions 2024-12-22 19:17:36 +09:00
rakshasa 0d1b9e9d55 Removed cppunit ldflags from common flags. 2024-12-21 02:28:46 +09:00
rakshasa 6561c00ae3 Use std::array in partial_queue. 2024-12-21 02:23:58 +09:00
rakshasa b8cb828d96 Replaced depreacted rak/functional calls. 2024-12-15 00:54:20 +09:00
stickz e3be3b2c12 scgi: Fix Apple and Solaris compatibility
This is a follow up to #1310. Apple and Solaris do not support MSG_NOSIGNAL, so disable this flag for these platforms until we find a better solution. Other platforms remain unaffected.
2024-12-14 23:34:48 +09:00
Jari Sundell 0f93fa109c Fixed curl stack shutdown with active downloads. (#1338)
Fixed curl stack shutdown with active downloads.
2024-12-12 22:59:48 +09:00
Jari Sundell 7e1193acab Run unit test in workflow PR. 2024-12-08 01:32:46 +09:00
kannibalox 5792ed1ae2 Apply clang-format 2024-12-07 19:26:29 +09:00
kannibalox 8cfc71b936 Fix system.multicall parameter parsing 2024-12-07 19:26:29 +09:00
kannibalox f2b065a798 Fix typo 2024-12-07 19:26:29 +09:00
kannibalox f33c2560a3 Default to an empty list when not passed explicit <params> 2024-12-07 19:26:29 +09:00
kannibalox db1e78fa9d Update tests to fix typo 2024-12-07 19:26:29 +09:00
kannibalox 48c40ee0c6 Fix typo: methodReponse -> methodResponse 2024-12-07 19:26:29 +09:00
kannibalox 3aeb213dc4 Avoid <int> in tinyxml2 responses
It's part of the XML-RPC spec, but some clients only accept i4/i8, which
should be supported nearly universally.

Fixes #1330
2024-12-07 19:26:29 +09:00
trim21 5a200f5d8f fix: d.group.name should return group name instead of group index 2024-12-06 01:09:18 +09:00
rakshasa 713067ba94 Fixed minor syntax issues. 2024-12-05 04:00:54 +09:00
Jari Sundell fea2cbfac6 Use proper target namespace 2024-12-05 04:00:54 +09:00
kannibalox 6bf1731a1c Ensure compability check actually checks the type for files
Fixes https://github.com/rakshasa/rtorrent/issues/854
2024-12-05 04:00:54 +09:00
Jari Sundell f2caa2651d Added clang-tidy github action. (#1325)
Added clang-tidy github action.
2024-12-05 03:01:11 +09:00
kannibalox 511895a8b6 Add headers to enable compiling without the libtorrent change 2024-12-04 19:19:53 +09:00
kannibalox 4e64fbc78b Properly use compare_exchange_strong
In practice, calling `network.scgi.open_port` again doesn't trigger
this function.
2024-12-04 19:19:53 +09:00
kannibalox 93b3a34f28 Properly lock size check, and remove overall cacheline alignment 2024-12-04 19:19:53 +09:00
kannibalox ea1ca00f31 Remove cacheline alignment from atomic pointer 2024-12-04 19:19:53 +09:00
kannibalox 58b1fc4914 Ensure empty() is properly guarded 2024-12-04 19:19:53 +09:00
kannibalox 577818bde4 Remove cache alignment from atomic members 2024-12-04 19:19:53 +09:00
kannibalox 0ea7615d0a Convert __sync* built-ins to std::atomic
Also converts thread_queue_hack to a simpler reserved vector
2024-12-04 19:19:53 +09:00
PPN-SD 73c1233dc0 Fix calls ar directly
Signed-off-by: Nicolas PARLANT <nicolas.parlant@parhuet.fr>
2024-11-26 01:27:39 +09:00
rakshasa 11ddc35d02 Renamed tinyxml2.cpp file. 2024-11-25 18:44:28 +09:00
kannibalox 036916fd9f Fix typo in method name 2024-11-25 18:44:28 +09:00
kannibalox b3fabd2a2b Align argument name with header definition 2024-11-25 18:44:28 +09:00
kannibalox 4b7c3ffafe Use empty() instead of checking size
Also use a const pointer for a child element
2024-11-25 18:44:28 +09:00
kannibalox 730d43b6c7 Explicitly mark narrowing conversion 2024-11-25 18:44:28 +09:00
kannibalox af2f30c183 Remove unused variable 2024-11-25 18:44:28 +09:00
kannibalox 36fd837d27 Fix unnecessary narrowing with proper return type 2024-11-25 18:44:28 +09:00
kannibalox 8dd8d691c5 Explicitly check result of std::strncmp 2024-11-25 18:44:28 +09:00
kannibalox e367b162ab Share object_to_target between tinyxml2 and xmlrpc-c 2024-11-25 18:44:28 +09:00
kannibalox 49cdfee65a Avoid ambiguous value_* in variable names 2024-11-25 18:44:28 +09:00
kannibalox 5680db3598 Parse out target param first if available 2024-11-25 18:44:28 +09:00
kannibalox 4768eb8356 Fix test to match case change 2024-11-25 18:44:28 +09:00
kannibalox fa2c7d961b Remove unnecessary std::string() and use lowercase for error msgs 2024-11-25 18:44:28 +09:00
kannibalox d6dcbc4a69 Add size limit to XML-RPC documents, defaulting to max SCGI size 2024-11-25 18:44:28 +09:00
kannibalox cadfcb50d2 Print iterator for TYPE_DICT_KEY, not object 2024-11-25 18:44:28 +09:00
kannibalox 71a39cd8a0 Keep as_*() outside of loops 2024-11-25 18:44:28 +09:00
kannibalox 0658486966 Change base64 decoder name, and add util for removing newlines 2024-11-25 18:44:28 +09:00
kannibalox 687fbbb83d Formatting 2024-11-25 18:44:28 +09:00
kannibalox e355eb561f Clean up borrowed base64 code to match repo standards 2024-11-25 18:44:28 +09:00
kannibalox 902de0b258 Add test for empty int text 2024-11-25 18:44:28 +09:00
kannibalox 01e5df4167 Remove title printing from test 2024-11-25 18:44:28 +09:00
kannibalox 8d85ce5857 Add test case for empty integer 2024-11-25 18:44:28 +09:00
kannibalox f9c9fa2e3b Move int element converter to helper function
Also fix strncmp checks
2024-11-25 18:44:28 +09:00
kannibalox 337897784d Change rpc namespace to include static consts 2024-11-25 18:44:28 +09:00
kannibalox 782b1e4ea8 Skip converting value_element_type to std::string 2024-11-25 18:44:28 +09:00
kannibalox 3cfc213053 Fix missing header 2024-11-25 18:44:28 +09:00
kannibalox b789d83b70 Fix system.listMethods inclusion check 2024-11-25 18:44:28 +09:00
kannibalox 67babb65d6 Convert element_access to use initializer lists
Also remove uses element_access for single child accesses
2024-11-25 18:44:28 +09:00
kannibalox e0d5c95821 Use correct terminology in comment 2024-11-25 18:44:28 +09:00
kannibalox 7f4c5df5ee Use single namespace statement 2024-11-25 18:44:28 +09:00
kannibalox dd45684584 Move vendored tinyxml2 files to rpc namespace and directory 2024-11-25 18:44:28 +09:00
kannibalox fb8632e990 Change lingering camelCase to snake_case 2024-11-25 18:44:28 +09:00
kannibalox b043b7b39e Simplify iterator names 2024-11-25 18:44:28 +09:00
kannibalox 168093d256 Remove extra return 2024-11-25 18:44:28 +09:00
kannibalox 0c2f0b7715 Add test case for invalid floats 2024-11-25 18:44:28 +09:00
kannibalox 4a9d9952e1 Be explicit about the desired result 2024-11-25 18:44:28 +09:00
kannibalox fd1d5dbdb2 Add test case for bad boolean value 2024-11-25 18:44:28 +09:00
kannibalox dd0c62c7f7 Uncomment after testing 2024-11-25 18:44:28 +09:00
kannibalox 3a8e462bd3 Throw error if attempting to use both xmlrpc-c and tinyxml2 2024-11-25 18:44:28 +09:00
kannibalox b360a734f1 Use std::strtoll instead of std::stol 2024-11-25 18:44:28 +09:00
kannibalox c18df7a366 Use std::strncmp for string comparison 2024-11-25 18:44:28 +09:00
kannibalox a269f808e1 Fix swapped variable names 2024-11-25 18:44:28 +09:00
kannibalox 4444df2e97 Change internal error to type error 2024-11-25 18:44:28 +09:00
kannibalox 5a194ab037 Remove stack from exception message 2024-11-25 18:44:28 +09:00
kannibalox 1b43f8b591 Use snake case for variable names
Also use `||` instead of `or`, and throw an error if an unknown boolean
string is received
2024-11-25 18:44:28 +09:00
kannibalox d6427203a4 Refactor to only use a position variable 2024-11-25 18:44:28 +09:00
kannibalox 87c6422052 Allow using vendored tinyxml2 for XMLRPC
By default, builds will still not have XMLRPC enabled at all and the
configure flag `--with-xmlrpc-tinyxml2` must be specified. If both
xmlrpc-c and tinyxml2 are specified, xmlrpc-c takes precedence.

Basic benchmarks indicate tinyxml2 is 2x faster for small
requests/responses, and that only increases as response sizes get
larger.
2024-11-25 18:44:28 +09:00
rakshasa 6ab265ecd4 Fixed merge errors. 2024-11-14 00:33:03 +09:00
rakshasa 203c66a287 Merge branch 'kannibalox-feature/clang-format' 2024-11-13 10:53:28 +00:00
Jari Sundell c9fe2facfa Merge branch 'master' into feature/clang-format 2024-11-13 19:51:04 +09:00
kannibalox 5abcf52e55 Remove unused flag_delete_key 2024-11-13 19:22:34 +09:00
kannibalox f2f84dd97a Remove destructor definition entirely 2024-11-13 19:22:34 +09:00
kannibalox 34de2b4ac9 Convert CommandMap to use std::string instead of char*
This allows it to own its keys and clean them up automatically on
destruction.
2024-11-13 19:22:34 +09:00
rakshasa ef937863fd Removed unused code. 2024-11-13 18:59:57 +09:00
kannibalox 00fa4127e1 Respect existing line limits 2024-11-11 16:00:28 -05:00
kannibalox 1b0cb722e6 Remove non-naming checks 2024-11-10 09:18:59 -05:00
kannibalox af23ca8032 Convert some representative files 2024-11-10 09:17:12 -05:00
kannibalox c85f9d6318 Add clang tidy/format 2024-11-10 09:08:33 -05:00
Josh Ellithorpe ee120730cc Update README.md to spell Ethereum correctly 2024-10-29 22:44:09 +09:00
stickz b284be6a66 Resolve scgi software crash
This commit resolves a scgi software crash when the scgi socket is closed before the message can be sent. It instructs `::send()` not to send a SIGPIPE termination signal. Instead the value -1 is returned and handled bellow. The SCgiTask is closed and a new one is sent to complete the task.

```
Thread 3 "rtorrent scgi" received signal SIGPIPE, Broken pipe.
                                                             [Switching to Thread 0x7fffe635c6c0 (LWP 2443872)]
0x00007ffff7929a84 in send () from /lib/x86_64-linux-gnu/libc.so.6
```
2024-10-29 22:42:33 +09:00
kannibalox 6e976616a0 Simplify updating queue entries
The erase/insert pattern can be replaced by a single method that
updates an existing entry's timer, or inserting if it doesn't exist.

This has much less impact than the libtorrent change it's based on,
but might as well be consistent.
2024-10-20 18:33:33 +09:00
Adam Sampson 38b39bdafc Add ax_require_defined.m4 to scripts.
This is required now by ax_with_curses.m4, but wasn't added when the
script was updated.
2024-10-07 23:52:20 +09:00
Adam Sampson 48718bdac8 Remove unnecessary +x mode from some m4 files. 2024-10-07 23:52:20 +09:00
Rui Chen 5ce84929e4 fix: use fsync for osx builds
Signed-off-by: Rui Chen <rui@chenrui.dev>
2024-10-07 23:43:54 +09:00
stickz c1d076f182 Fixing static building
@rakshasa A major hosting provider with rTorrent has mentioned the following revision is required for static builds to pass.
2024-10-07 23:32:45 +09:00
Jari Sundell f929594763 Update README.md 2024-09-29 23:34:31 +09:00
140 changed files with 36336 additions and 5258 deletions
+33
View File
@@ -0,0 +1,33 @@
---
BasedOnStyle: LLVM
Standard: c++14
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AlwaysBreakAfterReturnType: TopLevelDefinitions
BinPackArguments: false
BinPackParameters: false
BreakConstructorInitializers: AfterColon
BreakStringLiterals: false
ColumnLimit: 0
ContinuationIndentWidth: 2
IndentCaseLabels: false
IndentWidth: 2
PenaltyReturnTypeOnItsOwnLine: 130
PointerAlignment: Left
AlignEscapedNewlines: Right
AlignConsecutiveDeclarations:
Enabled: true
AcrossEmptyLines: true
AcrossComments: false
AlignConsecutiveMacros:
Enabled: true
AlignConsecutiveAssignments:
Enabled: true
IncludeCategories:
- Regex: "^(config|globals)\\.h"
Priority: -1
- Regex: "^torrent/.*"
Priority: 1
+16
View File
@@ -0,0 +1,16 @@
---
Checks: '-*,readability-identifier-naming'
FormatStyle: 'file'
CheckOptions:
- key: readability-identifier-naming.LocalVariableCase
value: lower_case
- key: readability-identifier-naming.ParameterCase
value: lower_case
- key: readability-identifier-naming.FunctionCase
value: lower_case
- key: readability-identifier-naming.PrivateMemberPrefix
value: m_
- key: readability-identifier-naming.PrivateMemberCase
value: lower_case
- key: readability-identifier-naming.ClassConstantCase
value: lower_case
@@ -0,0 +1,93 @@
# Secure workflow with access to repository secrets and GitHub token for posting analysis results
name: Post the static analysis results
on:
workflow_run:
workflows: [ "Static analysis" ]
types: [ completed ]
jobs:
clang-tidy-results:
# Trigger the job only if the previous (insecure) workflow completed successfully
if: ${{ github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-22.04
permissions:
pull-requests: write
# OPTIONAL: auto-closing conversations requires the `contents` permission
contents: write
steps:
- name: Download analysis results
uses: actions/github-script@v7
with:
script: |
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{ github.event.workflow_run.id }},
});
const matchArtifact = artifacts.data.artifacts.filter((artifact) => {
return artifact.name == "clang-tidy-result"
})[0];
const download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: "zip",
});
const fs = require("fs");
fs.writeFileSync("${{ github.workspace }}/clang-tidy-result.zip", Buffer.from(download.data));
- name: Extract analysis results
run: |
mkdir clang-tidy-result
unzip -j clang-tidy-result.zip -d clang-tidy-result
- name: Set environment variables
uses: actions/github-script@v7
with:
script: |
const assert = require("node:assert").strict;
const fs = require("fs");
function exportVar(varName, fileName, regEx) {
const val = fs.readFileSync("${{ github.workspace }}/clang-tidy-result/" + fileName, {
encoding: "ascii"
}).trimEnd();
assert.ok(regEx.test(val), "Invalid value format for " + varName);
core.exportVariable(varName, val);
}
exportVar("PR_ID", "pr-id.txt", /^[0-9]+$/);
exportVar("PR_HEAD_REPO", "pr-head-repo.txt", /^[-./0-9A-Z_a-z]+$/);
exportVar("PR_HEAD_SHA", "pr-head-sha.txt", /^[0-9A-Fa-f]+$/);
- uses: actions/checkout@v4
with:
repository: ${{ env.PR_HEAD_REPO }}
ref: ${{ env.PR_HEAD_SHA }}
persist-credentials: false
- name: Redownload analysis results
uses: actions/github-script@v7
with:
script: |
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{ github.event.workflow_run.id }},
});
const matchArtifact = artifacts.data.artifacts.filter((artifact) => {
return artifact.name == "clang-tidy-result"
})[0];
const download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: "zip",
});
const fs = require("fs");
fs.writeFileSync("${{ github.workspace }}/clang-tidy-result.zip", Buffer.from(download.data));
- name: Extract analysis results
run: |
mkdir clang-tidy-result
unzip -j clang-tidy-result.zip -d clang-tidy-result
- name: Run clang-tidy-pr-comments action
uses: platisd/clang-tidy-pr-comments@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
clang_tidy_fixes: clang-tidy-result/fixes.yml
pull_request_id: ${{ env.PR_ID }}
+80
View File
@@ -0,0 +1,80 @@
name: Static analysis
on: pull_request
jobs:
clang-tidy:
runs-on: ubuntu-22.04
steps:
- name: Update Packages
run: |
sudo apt-get update
- name: Fetch libtorrent
run: |
git clone https://github.com/rakshasa/libtorrent
- name: Build libtorrent
run: |
cd libtorrent
libtoolize
aclocal -I scripts
autoconf -i
autoheader
automake --add-missing
./configure
make
sudo make install
cd ..
rm -rf libtorrent
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Fetch base branch
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
aclocal -I scripts
autoconf -i
autoheader
automake --add-missing
./configure
- name: Prepare compile_commands.json
run: |
bear -- make
- name: Create results directory
run: |
mkdir clang-tidy-result
- name: Analyze
run: |
git diff -U0 "$(git merge-base HEAD "upstream/${{ github.event.pull_request.base.ref }}")" | clang-tidy-diff -p1 -path build -export-fixes clang-tidy-result/fixes.yml "-extra-arg=-include/${PWD}/config.h"
- name: Save PR metadata
run: |
echo "${{ github.event.number }}" > clang-tidy-result/pr-id.txt
echo "${{ github.event.pull_request.head.repo.full_name }}" > clang-tidy-result/pr-head-repo.txt
echo "${{ github.event.pull_request.head.sha }}" > clang-tidy-result/pr-head-sha.txt
- uses: actions/upload-artifact@v4
with:
name: clang-tidy-result
path: clang-tidy-result/
# - name: Run clang-tidy-pr-comments action
# uses: platisd/clang-tidy-pr-comments@v1
# with:
# # The GitHub token (or a personal access token)
# github_token: ${{ secrets.GITHUB_TOKEN }}
# # The path to the clang-tidy fixes generated previously
# clang_tidy_fixes: clang-tidy-result/fixes.yml
# # Optionally set to true if you want the Action to request
# # changes in case warnings are found
# request_changes: true
# # Optionally set the number of comments per review
# # to avoid GitHub API timeouts for heavily loaded
# # pull requests
# suggestions_per_comment: 10
+56
View File
@@ -0,0 +1,56 @@
name: Static analysis
on: pull_request
jobs:
unit-tests:
runs-on: ubuntu-22.04
steps:
- name: Update Packages
run: |
sudo apt-get update
- name: Fetch libtorrent
run: |
git clone https://github.com/rakshasa/libtorrent
- name: Build libtorrent
run: |
cd libtorrent
libtoolize
aclocal -I scripts
autoconf -i
autoheader
automake --add-missing
./configure
make
sudo make install
cd ..
rm -rf libtorrent
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Fetch base branch
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
aclocal -I scripts
autoconf -i
autoheader
automake --add-missing
./configure
- name: Build Project
run: |
make
- name: Run Unit Tests
run: |
make check
+2 -2
View File
@@ -18,6 +18,7 @@
.libs
Makefile
aclocal.m4
ar-lib
autom4te.cache
compile
config.h
@@ -67,6 +68,5 @@ TAGS
# rTorrent specific files
###########################
src/rtorrent
test/rtorrentTest
test/rtorrent_Test*
test-driver
test/rtorrentTest.trs
-2
View File
@@ -10,8 +10,6 @@ EXTRA_DIST= \
rak/error_number.h \
rak/file_stat.h \
rak/fs_stat.h \
rak/functional.h \
rak/functional_fun.h \
rak/path.h \
rak/partial_queue.h \
rak/priority_queue.h \
+7 -1
View File
@@ -14,6 +14,12 @@ 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)
Related Projects
----------------
@@ -26,7 +32,7 @@ Donate to rTorrent development
* [Patreon](https://www.patreon.com/rtorrent)
* [SubscribeStar](https://www.subscribestar.com/rtorrent)
* Bitcoin: 1MpmXm5AHtdBoDaLZstJw8nupJJaeKu8V8
* Etherium: 0x9AB1e3C3d8a875e870f161b3e9287Db0E6DAfF78
* Ethereum: 0x9AB1e3C3d8a875e870f161b3e9287Db0E6DAfF78
* Litecoin: LdyaVR67LBnTf6mAT4QJnjSG2Zk67qxmfQ
* Cardano: addr1qytaslmqmk6dspltw06sp0zf83dh09u79j49ceh5y26zdcccgq4ph7nmx6kgmzeldauj43254ey97f3x4xw49d86aguqwfhlte
Executable → Regular
+21 -9
View File
@@ -1,18 +1,23 @@
m4_pattern_allow([PKG_CHECK_EXISTS])
AC_INIT([rtorrent], [0.10.0], [sundell.software@gmail.com])
AC_INIT([rtorrent],[0.15.2],[sundell.software@gmail.com])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIRS([scripts])
AM_INIT_AUTOMAKE([foreign subdir-objects])
AM_PROG_AR
AC_DEFINE([API_VERSION], [10], [api version])
LT_INIT
AC_PROG_RANLIB
AC_PROG_CXX
AC_SYS_LARGEFILE
AC_DEFINE([API_VERSION], [11], [api version])
AX_CXX_COMPILE_STDCXX([14], [noext], [mandatory])
# Filter out unwanted flags added by autoconf on some systems, e.g. MacOS.
TORRENT_REMOVE_UNWANTED(CXX, $CXX, -std=c++11 -std=gnu++11)
AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory])
AC_SYS_LARGEFILE
RAK_CHECK_CFLAGS
RAK_CHECK_CXXFLAGS
@@ -49,12 +54,19 @@ fi
PKG_CHECK_MODULES([LIBCURL], [libcurl],, [LIBCURL_CHECK_CONFIG])
PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"])
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.14.0])
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.15.2])
AC_LANG_PUSH(C++)
TORRENT_WITH_XMLRPC_C
AC_LANG_POP(C++)
TORRENT_WITH_LUA
TORRENT_WITH_TINYXML2
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)
@@ -69,9 +81,9 @@ CC_ATTRIBUTE_UNUSED(
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 $CPPUNIT_LIBS $LIBCURL $LIBCURL_LIBS $DEPENDENCIES_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $CPPUNIT_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS $CPPUNIT_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
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"
AC_CONFIG_FILES([
Makefile
-4
View File
@@ -499,10 +499,6 @@ Number of attempts to check the hash while using the mincore status,
before forcing. Overworked systems might need lower values to get a
decent hash checking rate.
.TP
\fBsafe_sync = \fIyes|no\fB\fR
Always use MS_SYNC rather than MS_ASYNC when syncing chunks. This may
be nessesary in case of filesystem bugs like NFS in linux ~2.6.13.
.TP
\fBmax_open_files = \fIvalue\fB\fR
Number of files to simultaneously keep open. LibTorrent dynamically
opens and closes files as necessary when mapping files to
-10
View File
@@ -978,16 +978,6 @@ decent hash checking rate.
</para></listitem>
</varlistentry>
<varlistentry>
<term>safe_sync = <replaceable>yes|no</replaceable></term>
<listitem><para>
Always use MS_SYNC rather than MS_ASYNC when syncing chunks. This may
be nessesary in case of filesystem bugs like NFS in linux ~2.6.13.
</para></listitem>
</varlistentry>
<varlistentry>
<term>max_open_files = <replaceable>value</replaceable></term>
<listitem><para>
+1 -1
View File
@@ -115,7 +115,7 @@ advance_backward(_InputIter __first, _InputIter __last, _Distance __distance) {
}
template <typename _Value>
struct compare_base : public std::binary_function<_Value, _Value, bool> {
struct compare_base : public std::function<bool(_Value, _Value)> {
bool operator () (const _Value& complete, const _Value& base) const {
return !complete.compare(0, base.size(), base);
}
-683
View File
@@ -1,683 +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_FUNCTIONAL_H
#define RAK_FUNCTIONAL_H
#include <cstddef>
#include <functional>
namespace rak {
template <typename Type>
struct reference_fix {
typedef Type type;
};
template <typename Type>
struct reference_fix<Type&> {
typedef Type type;
};
template <typename Type>
struct value_t {
value_t(Type v) : m_v(v) {}
Type operator () () const { return m_v; }
Type m_v;
};
template <typename Type>
inline value_t<Type>
value(Type v) {
return value_t<Type>(v);
}
template <typename Type, typename Ftor>
struct accumulate_t {
accumulate_t(Type t, Ftor f) : result(t), m_f(f) {}
template <typename Arg>
void operator () (const Arg& a) { result += m_f(a); }
Type result;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline accumulate_t<Type, Ftor>
accumulate(Type t, Ftor f) {
return accumulate_t<Type, Ftor>(t, f);
}
// Operators:
template <typename Type, typename Ftor>
struct equal_t {
typedef bool result_type;
equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t == m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline equal_t<Type, Ftor>
equal(Type t, Ftor f) {
return equal_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct equal_ptr_t {
typedef bool result_type;
equal_ptr_t(Type* t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (const Arg& a) {
return *m_t == *m_f(a);
}
Type* m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline equal_ptr_t<Type, Ftor>
equal_ptr(Type* t, Ftor f) {
return equal_ptr_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct not_equal_t {
typedef bool result_type;
not_equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t != m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline not_equal_t<Type, Ftor>
not_equal(Type t, Ftor f) {
return not_equal_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct less_t {
typedef bool result_type;
less_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t < m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline less_t<Type, Ftor>
less(Type t, Ftor f) {
return less_t<Type, Ftor>(t, f);
}
template <typename FtorA, typename FtorB>
struct less2_t : public std::binary_function<typename FtorA::argument_type, typename FtorB::argument_type, bool> {
less2_t(FtorA f_a, FtorB f_b) : m_f_a(f_a), m_f_b(f_b) {}
bool operator () (typename FtorA::argument_type a, typename FtorB::argument_type b) {
return m_f_a(a) < m_f_b(b);
}
FtorA m_f_a;
FtorB m_f_b;
};
template <typename FtorA, typename FtorB>
inline less2_t<FtorA, FtorB>
less2(FtorA f_a, FtorB f_b) {
return less2_t<FtorA,FtorB>(f_a,f_b);
}
template <typename Type, typename Ftor>
struct _greater {
typedef bool result_type;
_greater(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t > m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline _greater<Type, Ftor>
greater(Type t, Ftor f) {
return _greater<Type, Ftor>(t, f);
}
template <typename FtorA, typename FtorB>
struct greater2_t : public std::binary_function<typename FtorA::argument_type, typename FtorB::argument_type, bool> {
greater2_t(FtorA f_a, FtorB f_b) : m_f_a(f_a), m_f_b(f_b) {}
bool operator () (typename FtorA::argument_type a, typename FtorB::argument_type b) {
return m_f_a(a) > m_f_b(b);
}
FtorA m_f_a;
FtorB m_f_b;
};
template <typename FtorA, typename FtorB>
inline greater2_t<FtorA, FtorB>
greater2(FtorA f_a, FtorB f_b) {
return greater2_t<FtorA,FtorB>(f_a,f_b);
}
template <typename Type, typename Ftor>
struct less_equal_t {
typedef bool result_type;
less_equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t <= m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline less_equal_t<Type, Ftor>
less_equal(Type t, Ftor f) {
return less_equal_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct greater_equal_t {
typedef bool result_type;
greater_equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t >= m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline greater_equal_t<Type, Ftor>
greater_equal(Type t, Ftor f) {
return greater_equal_t<Type, Ftor>(t, f);
}
template<typename Tp>
struct invert : public std::unary_function<Tp, Tp> {
Tp
operator () (const Tp& x) const { return ~x; }
};
template <typename Src, typename Dest>
struct on_t : public std::unary_function<typename Src::argument_type, typename Dest::result_type> {
typedef typename Dest::result_type result_type;
on_t(Src s, Dest d) : m_dest(d), m_src(s) {}
result_type operator () (typename reference_fix<typename Src::argument_type>::type arg) {
return m_dest(m_src(arg));
}
Dest m_dest;
Src m_src;
};
template <typename Src, typename Dest>
inline on_t<Src, Dest>
on(Src s, Dest d) {
return on_t<Src, Dest>(s, d);
}
template <typename Src, typename Dest>
struct on2_t : public std::binary_function<typename Src::argument_type, typename Dest::second_argument_type, typename Dest::result_type> {
typedef typename Dest::result_type result_type;
on2_t(Src s, Dest d) : m_dest(d), m_src(s) {}
result_type operator () (typename reference_fix<typename Src::argument_type>::type first, typename reference_fix<typename Dest::second_argument_type>::type second) {
return m_dest(m_src(first), second);
}
Dest m_dest;
Src m_src;
};
template <typename Src, typename Dest>
inline on2_t<Src, Dest>
on2(Src s, Dest d) {
return on2_t<Src, Dest>(s, d);
}
// Creates a functor for accessing a member.
template <typename Class, typename Member>
struct mem_ptr_t : public std::unary_function<Class*, Member&> {
mem_ptr_t(Member Class::*m) : m_member(m) {}
Member& operator () (Class* c) {
return c->*m_member;
}
const Member& operator () (const Class* c) {
return c->*m_member;
}
Member Class::*m_member;
};
template <typename Class, typename Member>
inline mem_ptr_t<Class, Member>
mem_ptr(Member Class::*m) {
return mem_ptr_t<Class, Member>(m);
}
template <typename Class, typename Member>
struct mem_ref_t : public std::unary_function<Class&, Member&> {
mem_ref_t(Member Class::*m) : m_member(m) {}
Member& operator () (Class& c) {
return c.*m_member;
}
Member Class::*m_member;
};
template <typename Class, typename Member>
struct const_mem_ref_t : public std::unary_function<const Class&, const Member&> {
const_mem_ref_t(const Member Class::*m) : m_member(m) {}
const Member& operator () (const Class& c) {
return c.*m_member;
}
const Member Class::*m_member;
};
template <typename Class, typename Member>
inline mem_ref_t<Class, Member>
mem_ref(Member Class::*m) {
return mem_ref_t<Class, Member>(m);
}
template <typename Class, typename Member>
inline const_mem_ref_t<Class, Member>
const_mem_ref(const Member Class::*m) {
return const_mem_ref_t<Class, Member>(m);
}
template <typename Cond, typename Then>
struct if_then_t {
if_then_t(Cond c, Then t) : m_cond(c), m_then(t) {}
template <typename Arg>
void operator () (Arg& a) {
if (m_cond(a))
m_then(a);
}
Cond m_cond;
Then m_then;
};
template <typename Cond, typename Then>
inline if_then_t<Cond, Then>
if_then(Cond c, Then t) {
return if_then_t<Cond, Then>(c, t);
}
template <typename T>
struct call_delete : public std::unary_function<T*, void> {
void operator () (T* t) {
delete t;
}
};
template <typename T>
inline void
call_delete_func(T* t) {
delete t;
}
template <typename Operation>
class bind1st_t : public std::unary_function<typename Operation::second_argument_type, typename Operation::result_type> {
public:
typedef typename reference_fix<typename Operation::first_argument_type>::type value_type;
typedef typename reference_fix<typename Operation::second_argument_type>::type argument_type;
bind1st_t(const Operation& op, const value_type v) :
m_op(op), m_value(v) {}
typename Operation::result_type
operator () (const argument_type arg) {
return m_op(m_value, arg);
}
protected:
Operation m_op;
value_type m_value;
};
template <typename Operation, typename Type>
inline bind1st_t<Operation>
bind1st(const Operation& op, const Type& val) {
return bind1st_t<Operation>(op, val);
}
template <typename Operation>
class bind2nd_t : public std::unary_function<typename Operation::first_argument_type, typename Operation::result_type> {
public:
typedef typename reference_fix<typename Operation::first_argument_type>::type argument_type;
typedef typename reference_fix<typename Operation::second_argument_type>::type value_type;
bind2nd_t(const Operation& op, const value_type v) :
m_op(op), m_value(v) {}
typename Operation::result_type
operator () (argument_type arg) {
return m_op(arg, m_value);
}
protected:
Operation m_op;
value_type m_value;
};
template <typename Operation, typename Type>
inline bind2nd_t<Operation>
bind2nd(const Operation& op, const Type& val) {
return bind2nd_t<Operation>(op, val);
}
// Lightweight callback function including pointer to object. Should
// be replaced by TR1 stuff later. Requires an object to bind, instead
// of using a seperate functor for that.
template <typename Ret>
class ptr_fun0 {
public:
typedef Ret result_type;
typedef Ret (*Function)();
ptr_fun0() {}
ptr_fun0(Function f) : m_function(f) {}
bool is_valid() const { return m_function; }
Ret operator () () { return m_function(); }
private:
Function m_function;
};
template <typename Object, typename Ret>
class mem_fun0 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)();
mem_fun0() : m_object(NULL) {}
mem_fun0(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () () { return (m_object->*m_function)(); }
private:
Object* m_object;
Function m_function;
};
template <typename Object, typename Ret>
class const_mem_fun0 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)() const;
const_mem_fun0() : m_object(NULL) {}
const_mem_fun0(const Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () () const { return (m_object->*m_function)(); }
private:
const Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1>
class mem_fun1 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1);
mem_fun1() : m_object(NULL) {}
mem_fun1(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () (Arg1 a1) { return (m_object->*m_function)(a1); }
private:
Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1>
class const_mem_fun1 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1) const;
const_mem_fun1() : m_object(NULL) {}
const_mem_fun1(const Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () (Arg1 a1) const { return (m_object->*m_function)(a1); }
private:
const Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1, typename Arg2>
class mem_fun2 : public std::binary_function<Arg1, Arg2, Ret> {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1, Arg2);
typedef Object object_type;
mem_fun2() : m_object(NULL) {}
mem_fun2(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
object_type* object() { return m_object; }
const object_type* object() const { return m_object; }
Ret operator () (Arg1 a1, Arg2 a2) { return (m_object->*m_function)(a1, a2); }
private:
Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1, typename Arg2, typename Arg3>
class mem_fun3 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1, Arg2, Arg3);
mem_fun3() : m_object(NULL) {}
mem_fun3(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () (Arg1 a1, Arg2 a2, Arg3 a3) { return (m_object->*m_function)(a1, a2, a3); }
private:
Object* m_object;
Function m_function;
};
template <typename Ret>
inline ptr_fun0<Ret>
ptr_fun(Ret (*f)()) { return ptr_fun0<Ret>(f); }
template <typename Object, typename Ret>
inline mem_fun0<Object, Ret>
make_mem_fun(Object* o, Ret (Object::*f)()) {
return mem_fun0<Object, Ret>(o, f);
}
template <typename Object, typename Ret>
inline const_mem_fun0<Object, Ret>
make_mem_fun(const Object* o, Ret (Object::*f)() const) {
return const_mem_fun0<Object, Ret>(o, f);
}
template <typename Object, typename Ret, typename Arg1>
inline mem_fun1<Object, Ret, Arg1>
make_mem_fun(Object* o, Ret (Object::*f)(Arg1)) {
return mem_fun1<Object, Ret, Arg1>(o, f);
}
template <typename Object, typename Ret, typename Arg1>
inline const_mem_fun1<Object, Ret, Arg1>
make_mem_fun(const Object* o, Ret (Object::*f)(Arg1) const) {
return const_mem_fun1<Object, Ret, Arg1>(o, f);
}
template <typename Object, typename Ret, typename Arg1, typename Arg2>
inline mem_fun2<Object, Ret, Arg1, Arg2>
make_mem_fun(Object* o, Ret (Object::*f)(Arg1, Arg2)) {
return mem_fun2<Object, Ret, Arg1, Arg2>(o, f);
}
template <typename Object, typename Ret, typename Arg1, typename Arg2, typename Arg3>
inline mem_fun3<Object, Ret, Arg1, Arg2, Arg3>
make_mem_fun(Object* o, Ret (Object::*f)(Arg1, Arg2, Arg3)) {
return mem_fun3<Object, Ret, Arg1, Arg2, Arg3>(o, f);
}
template <typename Container>
inline void
slot_list_call(const Container& slot_list) {
if (slot_list.empty())
return;
typename Container::const_iterator first = slot_list.begin();
typename Container::const_iterator next = slot_list.begin();
while (++next != slot_list.end()) {
(*first)();
first = next;
}
(*first)();
}
template <typename Container, typename Arg1>
inline void
slot_list_call(const Container& slot_list, Arg1 arg1) {
if (slot_list.empty())
return;
typename Container::const_iterator first = slot_list.begin();
typename Container::const_iterator next = slot_list.begin();
while (++next != slot_list.end()) {
(*first)(arg1);
first = next;
}
(*first)(arg1);
}
template <typename Container, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
inline void
slot_list_call(const Container& slot_list, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) {
if (slot_list.empty())
return;
typename Container::const_iterator first = slot_list.begin();
typename Container::const_iterator next = slot_list.begin();
while (++next != slot_list.end()) {
(*first)(arg1, arg2, arg3, arg4);
first = next;
}
(*first)(arg1, arg2, arg3, arg4);
}
}
#endif
-655
View File
@@ -1,655 +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
// This file contains functors that wrap function pointers and member
// function pointers.
//
// 'fn' functors are polymorphic and derives from 'rak::function' and
// thus is less strict about types, this adds the cost of calling a
// virtual function.
//
// 'fun' functors are non-polymorphic and thus cheaper, but requires
// the target object's type in the functor's template arguments.
//
// This should be replaced with TR1 stuff when it becomes widely
// available. At the moment it behaves like std::auto_ptr, so be
// careful when copying.
#ifndef RAK_FUNCTIONAL_FUN_H
#define RAK_FUNCTIONAL_FUN_H
#include <memory>
#include <functional>
#include <memory>
namespace rak {
template <typename Result>
class function_base0 {
public:
virtual ~function_base0() {}
virtual Result operator () () = 0;
};
template <typename Result, typename Arg1>
class function_base1 : public std::unary_function<Arg1, Result> {
public:
virtual ~function_base1() {}
virtual Result operator () (Arg1 arg1) = 0;
};
template <typename Result, typename Arg1, typename Arg2>
class function_base2 : public std::binary_function<Arg1, Arg2, Result> {
public:
virtual ~function_base2() {}
virtual Result operator () (Arg1 arg1, Arg2 arg2) = 0;
};
template <typename Result, typename Arg1, typename Arg2, typename Arg3>
class function_base3 {
public:
virtual ~function_base3() {}
virtual Result operator () (Arg1 arg1, Arg2 arg2, Arg3 arg3) = 0;
};
template <typename Result>
class function0 {
public:
typedef Result result_type;
typedef function_base0<Result> base_type;
bool is_valid() const { return m_base.get() != NULL; }
void set(base_type* base) { m_base = std::shared_ptr<base_type>(base); }
base_type* release() { return m_base.release(); }
Result operator () () { return (*m_base)(); }
private:
std::shared_ptr<base_type> m_base;
};
template <typename Result, typename Arg1>
class function1 {
public:
typedef Result result_type;
typedef function_base1<Result, Arg1> base_type;
bool is_valid() const { return m_base.get() != NULL; }
void set(base_type* base) { m_base = std::shared_ptr<base_type>(base); }
base_type* release() { return m_base.release(); }
Result operator () (Arg1 arg1) { return (*m_base)(arg1); }
private:
std::shared_ptr<base_type> m_base;
};
template <typename Result, typename Arg1, typename Arg2>
class function2 {
public:
typedef Result result_type;
typedef function_base2<Result, Arg1, Arg2> base_type;
bool is_valid() const { return m_base.get() != NULL; }
void set(base_type* base) { m_base = std::shared_ptr<base_type>(base); }
base_type* release() { return m_base.release(); }
Result operator () (Arg1 arg1, Arg2 arg2) { return (*m_base)(arg1, arg2); }
private:
std::shared_ptr<base_type> m_base;
};
template <typename Result, typename Arg2>
class function2<Result, void, Arg2> {
public:
typedef Result result_type;
typedef function_base1<Result, Arg2> base_type;
bool is_valid() const { return m_base.get() != NULL; }
void set(base_type* base) { m_base = std::shared_ptr<base_type>(base); }
base_type* release() { return m_base.release(); }
Result operator () (Arg2 arg2) { return (*m_base)(arg2); }
template <typename Discard>
Result operator () (Discard discard, Arg2 arg2) { return (*m_base)(arg2); }
private:
std::shared_ptr<base_type> m_base;
};
template <typename Result, typename Arg1, typename Arg2, typename Arg3>
class function3 {
public:
typedef Result result_type;
typedef function_base3<Result, Arg1, Arg2, Arg3> base_type;
bool is_valid() const { return m_base.get() != NULL; }
void set(base_type* base) { m_base = std::shared_ptr<base_type>(base); }
base_type* release() { return m_base.release(); }
Result operator () (Arg1 arg1, Arg2 arg2, Arg3 arg3) { return (*m_base)(arg1, arg2, arg3); }
private:
std::shared_ptr<base_type> m_base;
};
template <typename Result>
class ptr_fn0_t : public function_base0<Result> {
public:
typedef Result (*Func)();
ptr_fn0_t(Func func) : m_func(func) {}
virtual ~ptr_fn0_t() {}
virtual Result operator () () { return m_func(); }
private:
Func m_func;
};
template <typename Result, typename Arg1>
class ptr_fn1_t : public function_base1<Result, Arg1> {
public:
typedef Result (*Func)(Arg1);
ptr_fn1_t(Func func) : m_func(func) {}
virtual ~ptr_fn1_t() {}
virtual Result operator () (Arg1 arg1) { return m_func(arg1); }
private:
Func m_func;
};
template <typename Result, typename Arg1, typename Arg2>
class ptr_fn2_t : public function_base2<Result, Arg1, Arg2> {
public:
typedef Result (*Func)(Arg1, Arg2);
ptr_fn2_t(Func func) : m_func(func) {}
virtual ~ptr_fn2_t() {}
virtual Result operator () (Arg1 arg1, Arg2 arg2) { return m_func(arg1, arg2); }
private:
Func m_func;
};
template <typename Object, typename Result>
class mem_fn0_t : public function_base0<Result> {
public:
typedef Result (Object::*Func)();
mem_fn0_t(Object* object, Func func) : m_object(object), m_func(func) {}
virtual ~mem_fn0_t() {}
virtual Result operator () () { return (m_object->*m_func)(); }
private:
Object* m_object;
Func m_func;
};
template <typename Object, typename Result, typename Arg1>
class mem_fn1_t : public function_base1<Result, Arg1> {
public:
typedef Result (Object::*Func)(Arg1);
mem_fn1_t(Object* object, Func func) : m_object(object), m_func(func) {}
virtual ~mem_fn1_t() {}
virtual Result operator () (Arg1 arg1) { return (m_object->*m_func)(arg1); }
private:
Object* m_object;
Func m_func;
};
template <typename Object, typename Result, typename Arg1, typename Arg2, typename Arg3>
class mem_fn3_t : public function_base3<Result, Arg1, Arg2, Arg3> {
public:
typedef Result (Object::*Func)(Arg1, Arg2, Arg3);
mem_fn3_t(Object* object, Func func) : m_object(object), m_func(func) {}
virtual ~mem_fn3_t() {}
virtual Result operator () (Arg1 arg1, Arg2 arg2, Arg3 arg3) { return (m_object->*m_func)(arg1, arg2, arg3); }
private:
Object* m_object;
Func m_func;
};
template <typename Object, typename Result, typename Arg1, typename Arg2>
class mem_fn2_t : public function_base2<Result, Arg1, Arg2> {
public:
typedef Result (Object::*Func)(Arg1, Arg2);
mem_fn2_t(Object* object, Func func) : m_object(object), m_func(func) {}
virtual ~mem_fn2_t() {}
virtual Result operator () (Arg1 arg1, Arg2 arg2) { return (m_object->*m_func)(arg1, arg2); }
private:
Object* m_object;
Func m_func;
};
template <typename Object, typename Result>
class const_mem_fn0_t : public function_base0<Result> {
public:
typedef Result (Object::*Func)() const;
const_mem_fn0_t(const Object* object, Func func) : m_object(object), m_func(func) {}
virtual ~const_mem_fn0_t() {}
virtual Result operator () () { return (m_object->*m_func)(); }
private:
const Object* m_object;
Func m_func;
};
template <typename Object, typename Result, typename Arg1>
class const_mem_fn1_t : public function_base1<Result, Arg1> {
public:
typedef Result (Object::*Func)(Arg1) const;
const_mem_fn1_t(const Object* object, Func func) : m_object(object), m_func(func) {}
virtual ~const_mem_fn1_t() {}
virtual Result operator () (Arg1 arg1) { return (m_object->*m_func)(arg1); }
private:
const Object* m_object;
Func m_func;
};
// Unary functor with a bound argument.
template <typename Object, typename Result, typename Arg1>
class mem_fn0_b1_t : public function_base0<Result> {
public:
typedef Result (Object::*Func)(Arg1);
mem_fn0_b1_t(Object* object, Func func, const Arg1 arg1) : m_object(object), m_func(func), m_arg1(arg1) {}
virtual ~mem_fn0_b1_t() {}
virtual Result operator () () { return (m_object->*m_func)(m_arg1); }
private:
Object* m_object;
Func m_func;
const Arg1 m_arg1;
};
template <typename Object, typename Result, typename Arg1, typename Arg2>
class mem_fn1_b1_t : public function_base1<Result, Arg2> {
public:
typedef Result (Object::*Func)(Arg1, Arg2);
mem_fn1_b1_t(Object* object, Func func, const Arg1 arg1) : m_object(object), m_func(func), m_arg1(arg1) {}
virtual ~mem_fn1_b1_t() {}
virtual Result operator () (const Arg2 arg2) { return (m_object->*m_func)(m_arg1, arg2); }
private:
Object* m_object;
Func m_func;
const Arg1 m_arg1;
};
template <typename Object, typename Result, typename Arg1, typename Arg2>
class mem_fn1_b2_t : public function_base1<Result, Arg1> {
public:
typedef Result (Object::*Func)(Arg1, Arg2);
mem_fn1_b2_t(Object* object, Func func, const Arg2 arg2) : m_object(object), m_func(func), m_arg2(arg2) {}
virtual ~mem_fn1_b2_t() {}
virtual Result operator () (const Arg1 arg1) { return (m_object->*m_func)(arg1, m_arg2); }
private:
Object* m_object;
Func m_func;
const Arg2 m_arg2;
};
template <typename Result, typename Arg1>
class ptr_fn0_b1_t : public function_base0<Result> {
public:
typedef Result (*Func)(Arg1);
ptr_fn0_b1_t(Func func, const Arg1 arg1) : m_func(func), m_arg1(arg1) {}
virtual ~ptr_fn0_b1_t() {}
virtual Result operator () () { return m_func(m_arg1); }
private:
Func m_func;
Arg1 m_arg1;
};
template <typename Result, typename Arg1, typename Arg2>
class ptr_fn1_b1_t : public function_base1<Result, Arg2> {
public:
typedef Result (*Func)(Arg1, Arg2);
ptr_fn1_b1_t(Func func, const Arg1 arg1) : m_func(func), m_arg1(arg1) {}
virtual ~ptr_fn1_b1_t() {}
virtual Result operator () (Arg2 arg2) { return m_func(m_arg1, arg2); }
private:
Func m_func;
Arg1 m_arg1;
};
template <typename Result, typename Arg1, typename Arg2, typename Arg3>
class ptr_fn2_b1_t : public function_base2<Result, Arg2, Arg3> {
public:
typedef Result (*Func)(Arg1, Arg2, Arg3);
ptr_fn2_b1_t(Func func, const Arg1 arg1) : m_func(func), m_arg1(arg1) {}
virtual ~ptr_fn2_b1_t() {}
virtual Result operator () (Arg2 arg2, Arg3 arg3) { return m_func(m_arg1, arg2, arg3); }
private:
Func m_func;
Arg1 m_arg1;
};
template <typename Ftor>
class ftor_fn1_t : public function_base1<typename Ftor::result_type, typename Ftor::argument_type> {
public:
typedef typename Ftor::result_type result_type;
typedef typename Ftor::argument_type argument_type;
ftor_fn1_t(Ftor ftor) : m_ftor(ftor) {}
virtual ~ftor_fn1_t() {}
virtual result_type operator () (argument_type arg1) { return m_ftor(arg1); }
private:
Ftor m_ftor;
};
template <typename Ftor>
class ftor_fn2_t : public function_base2<typename Ftor::result_type, typename Ftor::first_argument_type, typename Ftor::second_argument_type> {
public:
typedef typename Ftor::result_type result_type;
typedef typename Ftor::first_argument_type first_argument_type;
typedef typename Ftor::second_argument_type second_argument_type;
ftor_fn2_t(Ftor ftor) : m_ftor(ftor) {}
virtual ~ftor_fn2_t() {}
virtual result_type operator () (first_argument_type arg1, second_argument_type arg2) { return m_ftor(arg1, arg2); }
private:
Ftor m_ftor;
};
template <typename Result>
class value_fn0_t : public function_base0<Result> {
public:
value_fn0_t(const Result& val) : m_value(val) {}
virtual Result operator () () { return m_value; }
private:
Result m_value;
};
template <typename Result, typename SrcResult>
class convert_fn0_t : public function_base0<Result> {
public:
typedef function0<SrcResult> src_type;
convert_fn0_t(typename src_type::base_type* object) { m_object.set(object); }
virtual ~convert_fn0_t() {}
virtual Result operator () () {
return m_object();
}
private:
src_type m_object;
};
template <typename Result, typename Arg1, typename SrcResult, typename SrcArg1>
class convert_fn1_t : public function_base1<Result, Arg1> {
public:
typedef function1<SrcResult, SrcArg1> src_type;
convert_fn1_t(typename src_type::base_type* object) { m_object.set(object); }
virtual ~convert_fn1_t() {}
virtual Result operator () (Arg1 arg1) {
return m_object(arg1);
}
private:
src_type m_object;
};
template <typename Result, typename Arg1, typename Arg2, typename SrcResult, typename SrcArg1, typename SrcArg2>
class convert_fn2_t : public function_base2<Result, Arg1, Arg2> {
public:
typedef function2<SrcResult, SrcArg1, SrcArg2> src_type;
convert_fn2_t(typename src_type::base_type* object) { m_object.set(object); }
virtual ~convert_fn2_t() {}
virtual Result operator () (Arg1 arg1, Arg2 arg2) {
return m_object(arg1, arg2);
}
private:
src_type m_object;
};
template <typename Result>
inline function_base0<Result>*
ptr_fn(Result (*func)()) {
return new ptr_fn0_t<Result>(func);
}
template <typename Arg1, typename Result>
inline function_base1<Result, Arg1>*
ptr_fn(Result (*func)(Arg1)) {
return new ptr_fn1_t<Result, Arg1>(func);
}
template <typename Arg1, typename Arg2, typename Result>
inline function_base2<Result, Arg1, Arg2>*
ptr_fn(Result (*func)(Arg1, Arg2)) {
return new ptr_fn2_t<Result, Arg1, Arg2>(func);
}
template <typename Result, typename Object>
inline function_base0<Result>*
mem_fn(Object* object, Result (Object::*func)()) {
return new mem_fn0_t<Object, Result>(object, func);
}
template <typename Arg1, typename Result, typename Object>
inline function_base1<Result, Arg1>*
mem_fn(Object* object, Result (Object::*func)(Arg1)) {
return new mem_fn1_t<Object, Result, Arg1>(object, func);
}
template <typename Arg1, typename Arg2, typename Result, typename Object>
inline function_base2<Result, Arg1, Arg2>*
mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2)) {
return new mem_fn2_t<Object, Result, Arg1, Arg2>(object, func);
}
template <typename Arg1, typename Arg2, typename Arg3, typename Result, typename Object>
inline function_base3<Result, Arg1, Arg2, Arg3>*
mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2, Arg3)) {
return new mem_fn3_t<Object, Result, Arg1, Arg2, Arg3>(object, func);
}
template <typename Result, typename Object>
inline function_base0<Result>*
mem_fn(const Object* object, Result (Object::*func)() const) {
return new const_mem_fn0_t<Object, Result>(object, func);
}
template <typename Arg1, typename Result, typename Object>
inline function_base1<Result, Arg1>*
mem_fn(const Object* object, Result (Object::*func)(Arg1) const) {
return new const_mem_fn1_t<Object, Result, Arg1>(object, func);
}
template <typename Arg1, typename Result, typename Object>
inline function_base0<Result>*
bind_mem_fn(Object* object, Result (Object::*func)(Arg1), const Arg1 arg1) {
return new mem_fn0_b1_t<Object, Result, Arg1>(object, func, arg1);
}
template <typename Arg1, typename Arg2, typename Result, typename Object>
inline function_base1<Result, Arg2>*
bind_mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2), const Arg1 arg1) {
return new mem_fn1_b1_t<Object, Result, Arg1, Arg2>(object, func, arg1);
}
template <typename Arg1, typename Arg2, typename Result, typename Object>
inline function_base1<Result, Arg1>*
bind2_mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2), const Arg2 arg2) {
return new mem_fn1_b2_t<Object, Result, Arg1, Arg2>(object, func, arg2);
}
template <typename Arg1, typename Result>
inline function_base0<Result>*
bind_ptr_fn(Result (*func)(Arg1), const Arg1 arg1) {
return new ptr_fn0_b1_t<Result, Arg1>(func, arg1);
}
template <typename Arg1, typename Arg2, typename Result>
inline function_base1<Result, Arg2>*
bind_ptr_fn(Result (*func)(Arg1, Arg2), const Arg1 arg1) {
return new ptr_fn1_b1_t<Result, Arg1, Arg2>(func, arg1);
}
template <typename Arg1, typename Arg2, typename Arg3, typename Result>
inline function_base2<Result, Arg2, Arg3>*
bind_ptr_fn(Result (*func)(Arg1, Arg2, Arg3), const Arg1 arg1) {
return new ptr_fn2_b1_t<Result, Arg1, Arg2, Arg3>(func, arg1);
}
template <typename Ftor>
inline function_base1<typename Ftor::result_type, typename Ftor::argument_type>*
ftor_fn1(Ftor ftor) {
return new ftor_fn1_t<Ftor>(ftor);
}
template <typename Ftor>
inline function_base2<typename Ftor::result_type, typename Ftor::first_argument_type, typename Ftor::second_argument_type>*
ftor_fn2(Ftor ftor) {
return new ftor_fn2_t<Ftor>(ftor);
}
template <typename Result>
inline function_base0<Result>*
value_fn(const Result& val) {
return new value_fn0_t<Result>(val);
}
template <typename A, typename B>
struct equal_types_t {
typedef A first_type;
typedef B second_type;
const static int result = 0;
};
template <typename A>
struct equal_types_t<A, A> {
typedef A first_type;
typedef A second_type;
const static int result = 1;
};
template <typename Result, typename SrcResult>
inline function_base0<Result>*
convert_fn(function_base0<SrcResult>* src) {
if (equal_types_t<function_base0<Result>, function_base0<SrcResult> >::result)
// The pointer cast never gets done if the types are different,
// but needs to be here to pleasant the compiler.
return reinterpret_cast<typename equal_types_t<function_base0<Result>, function_base0<SrcResult> >::first_type*>(src);
else
return new convert_fn0_t<Result, SrcResult>(src);
}
template <typename Result, typename Arg1, typename SrcResult, typename SrcArg1>
inline function_base1<Result, Arg1>*
convert_fn(function_base1<SrcResult, SrcArg1>* src) {
if (equal_types_t<function_base1<Result, Arg1>, function_base1<SrcResult, SrcArg1> >::result)
// The pointer cast never gets done if the types are different,
// but needs to be here to pleasant the compiler.
return reinterpret_cast<typename equal_types_t<function_base1<Result, Arg1>, function_base1<SrcResult, SrcArg1> >::first_type*>(src);
else
return new convert_fn1_t<Result, Arg1, SrcResult, SrcArg1>(src);
}
template <typename Result, typename Arg1, typename Arg2, typename SrcResult, typename SrcArg1, typename SrcArg2>
inline function_base2<Result, Arg1, Arg2>*
convert_fn(function_base2<SrcResult, SrcArg1, SrcArg2>* src) {
if (equal_types_t<function_base2<Result, Arg1, Arg2>, function_base2<SrcResult, SrcArg1, SrcArg2> >::result)
// The pointer cast never gets done if the types are different,
// but needs to be here to pleasant the compiler.
return reinterpret_cast<typename equal_types_t<function_base2<Result, Arg1, Arg2>, function_base2<SrcResult, SrcArg1, SrcArg2> >::first_type*>(src);
else
return new convert_fn2_t<Result, Arg1, Arg2, SrcResult, SrcArg1, SrcArg2>(src);
}
}
#endif
+3 -2
View File
@@ -37,6 +37,7 @@
#ifndef RAK_PARTIAL_QUEUE_H
#define RAK_PARTIAL_QUEUE_H
#include <array>
#include <cstring>
#include <stdexcept>
#include <cinttypes>
@@ -107,7 +108,7 @@ private:
size_type m_index;
size_type m_ceiling;
size_pair_type m_layers[num_layers];
std::array<size_pair_type, num_layers> m_layers;
};
inline void
@@ -137,7 +138,7 @@ partial_queue::clear() {
m_index = 0;
m_ceiling = ceiling(num_layers - 1);
std::memset(m_layers, 0, num_layers * sizeof(size_pair_type));
m_layers = {};
}
inline bool
+9 -75
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
// priority_queue is a priority queue implemented using a binary
// heap. It can contain multiple instances of a value.
@@ -46,10 +10,10 @@
namespace rak {
template <typename Value, typename Compare, typename Equal, typename Alloc = std::allocator<Value> >
class priority_queue : public std::vector<Value, Alloc> {
template <typename Value, typename Compare, typename Equal>
class priority_queue : public std::vector<Value> {
public:
typedef std::vector<Value, Alloc> base_type;
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;
@@ -74,6 +38,10 @@ public:
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);
@@ -81,7 +49,7 @@ public:
template <typename Key>
iterator find(const Key& key) {
return std::find_if(begin(), end(), std::bind2nd(m_equal, key));
return std::find_if(begin(), end(), [&](auto& value) { return m_equal(value, key); });
}
template <typename Key>
@@ -95,12 +63,8 @@ public:
return true;
}
// Removes 'itr' from the queue. This assumes 'itr' has been
// modified such that it has a higher priority than any other
// element in the queue.
// Removes 'itr' from the queue.
void erase(iterator itr) {
// std::push_heap(begin(), ++itr, m_compare);
// pop();
base_type::erase(itr);
std::make_heap(begin(), end(), m_compare);
}
@@ -110,36 +74,6 @@ private:
Equal m_equal;
};
// Iterate while the top node has higher priority, as 'Compare'
// returns false.
template <typename Queue, typename Compare>
class queue_pop_iterator
: public std::iterator<std::forward_iterator_tag, void, void, void, void> {
public:
typedef Queue container_type;
queue_pop_iterator() : m_queue(NULL) {}
queue_pop_iterator(Queue* q, Compare c) : m_queue(q), m_compare(c) {}
queue_pop_iterator& operator ++ () { m_queue->pop(); return *this; }
queue_pop_iterator& operator ++ (int) { m_queue->pop(); return *this; }
typename container_type::const_reference operator * () { return m_queue->top(); }
bool operator != (const queue_pop_iterator& itr) { return !m_queue->empty() && !m_compare(m_queue->top()); }
bool operator == (const queue_pop_iterator& itr) { return m_queue->empty() || m_compare(m_queue->top()); }
private:
Queue* m_queue;
Compare m_compare;
};
template <typename Queue, typename Compare>
inline queue_pop_iterator<Queue, Compare>
queue_popper(Queue& queue, Compare comp) {
return queue_pop_iterator<Queue, Compare>(&queue, comp);
}
}
#endif
+25 -45
View File
@@ -1,44 +1,8 @@
// 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_PRIORITY_QUEUE_DEFAULT_H
#define RAK_PRIORITY_QUEUE_DEFAULT_H
#include <cassert>
#include <functional>
#include <rak/allocators.h>
#include <rak/priority_queue.h>
#include <rak/timer.h>
@@ -52,8 +16,7 @@ public:
priority_item() {}
~priority_item() {
if (is_queued())
throw torrent::internal_error("priority_item::~priority_item() called on a queued item.");
assert(!is_queued() && "priority_item::~priority_item() called on a queued item.");
m_time = timer();
m_slot = slot_void();
@@ -85,8 +48,7 @@ struct priority_compare {
};
typedef std::equal_to<priority_item*> priority_equal;
typedef priority_queue<priority_item*, priority_compare, priority_equal,
cacheline_allocator<priority_item*> > priority_queue_default;
typedef priority_queue<priority_item*, priority_compare, priority_equal> priority_queue_default;
inline void
priority_queue_perform(priority_queue_default* queue, timer t) {
@@ -127,14 +89,32 @@ priority_queue_erase(priority_queue_default* queue, priority_item* item) {
if (!item->is_valid())
throw torrent::internal_error("priority_queue_erase(...) called on an invalid item.");
// Clear time before erasing to force it to the top.
// Unqueue it before erasing.
item->clear_time();
if (!queue->erase(item))
throw torrent::internal_error("priority_queue_erase(...) could not find item in queue.");
}
if (queue->find(item) != queue->end())
throw torrent::internal_error("priority_queue_erase(...) item still 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();
}
}
}
+1 -1
View File
@@ -50,7 +50,7 @@
namespace rak {
class regex : public std::unary_function<std::string, bool> {
class regex : public std::function<bool (std::string)> {
public:
regex() {}
regex(const std::string& p) : m_pattern(p) {}
+42
View File
@@ -0,0 +1,42 @@
-- 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
Executable → Regular
View File
Executable → Regular
View File
+661
View File
@@ -0,0 +1,661 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_lua.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PROG_LUA[([MINIMUM-VERSION], [TOO-BIG-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
# AX_LUA_HEADERS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
# AX_LUA_LIBS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
# AX_LUA_READLINE[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
#
# DESCRIPTION
#
# Detect a Lua interpreter, optionally specifying a minimum and maximum
# version number. Set up important Lua paths, such as the directories in
# which to install scripts and modules (shared libraries).
#
# Also detect Lua headers and libraries. The Lua version contained in the
# header is checked to match the Lua interpreter version exactly. When
# searching for Lua libraries, the version number is used as a suffix.
# This is done with the goal of supporting multiple Lua installs (5.1,
# 5.2, and 5.3 side-by-side).
#
# A note on compatibility with previous versions: This file has been
# mostly rewritten for serial 18. Most developers should be able to use
# these macros without needing to modify configure.ac. Care has been taken
# to preserve each macro's behavior, but there are some differences:
#
# 1) AX_WITH_LUA is deprecated; it now expands to the exact same thing as
# AX_PROG_LUA with no arguments.
#
# 2) AX_LUA_HEADERS now checks that the version number defined in lua.h
# matches the interpreter version. AX_LUA_HEADERS_VERSION is therefore
# unnecessary, so it is deprecated and does not expand to anything.
#
# 3) The configure flag --with-lua-suffix no longer exists; the user
# should instead specify the LUA precious variable on the command line.
# See the AX_PROG_LUA description for details.
#
# Please read the macro descriptions below for more information.
#
# This file was inspired by Andrew Dalke's and James Henstridge's
# python.m4 and Tom Payne's, Matthieu Moy's, and Reuben Thomas's ax_lua.m4
# (serial 17). Basically, this file is a mash-up of those two files. I
# like to think it combines the best of the two!
#
# AX_PROG_LUA: Search for the Lua interpreter, and set up important Lua
# paths. Adds precious variable LUA, which may contain the path of the Lua
# interpreter. If LUA is blank, the user's path is searched for an
# suitable interpreter.
#
# If MINIMUM-VERSION is supplied, then only Lua interpreters with a
# version number greater or equal to MINIMUM-VERSION will be accepted. If
# TOO-BIG-VERSION is also supplied, then only Lua interpreters with a
# version number greater or equal to MINIMUM-VERSION and less than
# TOO-BIG-VERSION will be accepted.
#
# The Lua version number, LUA_VERSION, is found from the interpreter, and
# substituted. LUA_PLATFORM is also found, but not currently supported (no
# standard representation).
#
# Finally, the macro finds four paths:
#
# luadir Directory to install Lua scripts.
# pkgluadir $luadir/$PACKAGE
# luaexecdir Directory to install Lua modules.
# pkgluaexecdir $luaexecdir/$PACKAGE
#
# These paths are found based on $prefix, $exec_prefix, Lua's
# package.path, and package.cpath. The first path of package.path
# beginning with $prefix is selected as luadir. The first path of
# package.cpath beginning with $exec_prefix is used as luaexecdir. This
# should work on all reasonable Lua installations. If a path cannot be
# determined, a default path is used. Of course, the user can override
# these later when invoking make.
#
# luadir Default: $prefix/share/lua/$LUA_VERSION
# luaexecdir Default: $exec_prefix/lib/lua/$LUA_VERSION
#
# These directories can be used by Automake as install destinations. The
# variable name minus 'dir' needs to be used as a prefix to the
# appropriate Automake primary, e.g. lua_SCRIPS or luaexec_LIBRARIES.
#
# If an acceptable Lua interpreter is found, then ACTION-IF-FOUND is
# performed, otherwise ACTION-IF-NOT-FOUND is preformed. If ACTION-IF-NOT-
# FOUND is blank, then it will default to printing an error. To prevent
# the default behavior, give ':' as an action.
#
# AX_LUA_HEADERS: Search for Lua headers. Requires that AX_PROG_LUA be
# expanded before this macro. Adds precious variable LUA_INCLUDE, which
# may contain Lua specific include flags, e.g. -I/usr/include/lua5.1. If
# LUA_INCLUDE is blank, then this macro will attempt to find suitable
# flags.
#
# LUA_INCLUDE can be used by Automake to compile Lua modules or
# executables with embedded interpreters. The *_CPPFLAGS variables should
# be used for this purpose, e.g. myprog_CPPFLAGS = $(LUA_INCLUDE).
#
# This macro searches for the header lua.h (and others). The search is
# performed with a combination of CPPFLAGS, CPATH, etc, and LUA_INCLUDE.
# If the search is unsuccessful, then some common directories are tried.
# If the headers are then found, then LUA_INCLUDE is set accordingly.
#
# The paths automatically searched are:
#
# * /usr/include/luaX.Y
# * /usr/include/lua/X.Y
# * /usr/include/luaXY
# * /usr/local/include/luaX.Y
# * /usr/local/include/lua-X.Y
# * /usr/local/include/lua/X.Y
# * /usr/local/include/luaXY
#
# (Where X.Y is the Lua version number, e.g. 5.1.)
#
# The Lua version number found in the headers is always checked to match
# the Lua interpreter's version number. Lua headers with mismatched
# version numbers are not accepted.
#
# If headers are found, then ACTION-IF-FOUND is performed, otherwise
# ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then
# it will default to printing an error. To prevent the default behavior,
# set the action to ':'.
#
# AX_LUA_LIBS: Search for Lua libraries. Requires that AX_PROG_LUA be
# expanded before this macro. Adds precious variable LUA_LIB, which may
# contain Lua specific linker flags, e.g. -llua5.1. If LUA_LIB is blank,
# then this macro will attempt to find suitable flags.
#
# LUA_LIB can be used by Automake to link Lua modules or executables with
# embedded interpreters. The *_LIBADD and *_LDADD variables should be used
# for this purpose, e.g. mymod_LIBADD = $(LUA_LIB).
#
# This macro searches for the Lua library. More technically, it searches
# for a library containing the function lua_load. The search is performed
# with a combination of LIBS, LIBRARY_PATH, and LUA_LIB.
#
# If the search determines that some linker flags are missing, then those
# flags will be added to LUA_LIB.
#
# If libraries are found, then ACTION-IF-FOUND is performed, otherwise
# ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then
# it will default to printing an error. To prevent the default behavior,
# set the action to ':'.
#
# AX_LUA_READLINE: Search for readline headers and libraries. Requires the
# AX_LIB_READLINE macro, which is provided by ax_lib_readline.m4 from the
# Autoconf Archive.
#
# If a readline compatible library is found, then ACTION-IF-FOUND is
# performed, otherwise ACTION-IF-NOT-FOUND is performed.
#
# LICENSE
#
# Copyright (c) 2015 Reuben Thomas <rrt@sc3d.org>
# Copyright (c) 2014 Tim Perkins <tprk77@gmail.com>
#
# 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 3 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, see <https://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 42
dnl =========================================================================
dnl AX_PROG_LUA([MINIMUM-VERSION], [TOO-BIG-VERSION],
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl =========================================================================
AC_DEFUN([AX_PROG_LUA],
[
dnl Check for required tools.
AC_REQUIRE([AC_PROG_GREP])
AC_REQUIRE([AC_PROG_SED])
dnl Make LUA a precious variable.
AC_ARG_VAR([LUA], [The Lua interpreter, e.g. /usr/bin/lua5.1])
dnl Find a Lua interpreter.
m4_define_default([_AX_LUA_INTERPRETER_LIST],
[lua lua5.3 lua53 lua5.2 lua52 lua5.1 lua51 lua50])
m4_if([$1], [],
[ dnl No version check is needed. Find any Lua interpreter.
AS_IF([test "x$LUA" = 'x'],
[AC_PATH_PROGS([LUA], [_AX_LUA_INTERPRETER_LIST], [:])])
ax_display_LUA='lua'
AS_IF([test "x$LUA" != 'x:'],
[ dnl At least check if this is a Lua interpreter.
AC_MSG_CHECKING([if $LUA is a Lua interpreter])
_AX_LUA_CHK_IS_INTRP([$LUA],
[AC_MSG_RESULT([yes])],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([not a Lua interpreter])
])
])
],
[ dnl A version check is needed.
AS_IF([test "x$LUA" != 'x'],
[ dnl Check if this is a Lua interpreter.
AC_MSG_CHECKING([if $LUA is a Lua interpreter])
_AX_LUA_CHK_IS_INTRP([$LUA],
[AC_MSG_RESULT([yes])],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([not a Lua interpreter])
])
dnl Check the version.
m4_if([$2], [],
[_ax_check_text="whether $LUA version >= $1"],
[_ax_check_text="whether $LUA version >= $1, < $2"])
AC_MSG_CHECKING([$_ax_check_text])
_AX_LUA_CHK_VER([$LUA], [$1], [$2],
[AC_MSG_RESULT([yes])],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([version is out of range for specified LUA])])
ax_display_LUA=$LUA
],
[ dnl Try each interpreter until we find one that satisfies VERSION.
m4_if([$2], [],
[_ax_check_text="for a Lua interpreter with version >= $1"],
[_ax_check_text="for a Lua interpreter with version >= $1, < $2"])
AC_CACHE_CHECK([$_ax_check_text],
[ax_cv_pathless_LUA],
[ for ax_cv_pathless_LUA in _AX_LUA_INTERPRETER_LIST none; do
test "x$ax_cv_pathless_LUA" = 'xnone' && break
_AX_LUA_CHK_IS_INTRP([$ax_cv_pathless_LUA], [], [continue])
_AX_LUA_CHK_VER([$ax_cv_pathless_LUA], [$1], [$2], [break])
done
])
dnl Set $LUA to the absolute path of $ax_cv_pathless_LUA.
AS_IF([test "x$ax_cv_pathless_LUA" = 'xnone'],
[LUA=':'],
[AC_PATH_PROG([LUA], [$ax_cv_pathless_LUA])])
ax_display_LUA=$ax_cv_pathless_LUA
])
])
AS_IF([test "x$LUA" = 'x:'],
[ dnl Run any user-specified action, or abort.
m4_default([$4], [AC_MSG_ERROR([cannot find suitable Lua interpreter])])
],
[ dnl Query Lua for its version number.
AC_CACHE_CHECK([for $ax_display_LUA version],
[ax_cv_lua_version],
[ dnl Get the interpreter version in X.Y format. This should work for
dnl interpreters version 5.0 and beyond.
ax_cv_lua_version=[`$LUA -e '
-- return a version number in X.Y format
local _, _, ver = string.find(_VERSION, "^Lua (%d+%.%d+)")
print(ver)'`]
])
AS_IF([test "x$ax_cv_lua_version" = 'x'],
[AC_MSG_ERROR([invalid Lua version number])])
AC_SUBST([LUA_VERSION], [$ax_cv_lua_version])
AC_SUBST([LUA_SHORT_VERSION], [`echo "$LUA_VERSION" | $SED 's|\.||'`])
dnl The following check is not supported:
dnl At times (like when building shared libraries) you may want to know
dnl which OS platform Lua thinks this is.
AC_CACHE_CHECK([for $ax_display_LUA platform],
[ax_cv_lua_platform],
[ax_cv_lua_platform=[`$LUA -e 'print("unknown")'`]])
AC_SUBST([LUA_PLATFORM], [$ax_cv_lua_platform])
dnl Use the values of $prefix and $exec_prefix for the corresponding
dnl values of LUA_PREFIX and LUA_EXEC_PREFIX. These are made distinct
dnl variables so they can be overridden if need be. However, the general
dnl consensus is that you shouldn't need this ability.
AC_SUBST([LUA_PREFIX], ['${prefix}'])
AC_SUBST([LUA_EXEC_PREFIX], ['${exec_prefix}'])
dnl Lua provides no way to query the script directory, and instead
dnl provides LUA_PATH. However, we should be able to make a safe educated
dnl guess. If the built-in search path contains a directory which is
dnl prefixed by $prefix, then we can store scripts there. The first
dnl matching path will be used.
AC_CACHE_CHECK([for $ax_display_LUA script directory],
[ax_cv_lua_luadir],
[ AS_IF([test "x$prefix" = 'xNONE'],
[ax_lua_prefix=$ac_default_prefix],
[ax_lua_prefix=$prefix])
dnl Initialize to the default path.
ax_cv_lua_luadir="$LUA_PREFIX/share/lua/$LUA_VERSION"
dnl Try to find a path with the prefix.
_AX_LUA_FND_PRFX_PTH([$LUA], [$ax_lua_prefix], [script])
AS_IF([test "x$ax_lua_prefixed_path" != 'x'],
[ dnl Fix the prefix.
_ax_strip_prefix=`echo "$ax_lua_prefix" | $SED 's|.|.|g'`
ax_cv_lua_luadir=`echo "$ax_lua_prefixed_path" | \
$SED "s|^$_ax_strip_prefix|$LUA_PREFIX|"`
])
])
AC_SUBST([luadir], [$ax_cv_lua_luadir])
AC_SUBST([pkgluadir], [\${luadir}/$PACKAGE])
dnl Lua provides no way to query the module directory, and instead
dnl provides LUA_PATH. However, we should be able to make a safe educated
dnl guess. If the built-in search path contains a directory which is
dnl prefixed by $exec_prefix, then we can store modules there. The first
dnl matching path will be used.
AC_CACHE_CHECK([for $ax_display_LUA module directory],
[ax_cv_lua_luaexecdir],
[ AS_IF([test "x$exec_prefix" = 'xNONE'],
[ax_lua_exec_prefix=$ax_lua_prefix],
[ax_lua_exec_prefix=$exec_prefix])
dnl Initialize to the default path.
ax_cv_lua_luaexecdir="$LUA_EXEC_PREFIX/lib/lua/$LUA_VERSION"
dnl Try to find a path with the prefix.
_AX_LUA_FND_PRFX_PTH([$LUA],
[$ax_lua_exec_prefix], [module])
AS_IF([test "x$ax_lua_prefixed_path" != 'x'],
[ dnl Fix the prefix.
_ax_strip_prefix=`echo "$ax_lua_exec_prefix" | $SED 's|.|.|g'`
ax_cv_lua_luaexecdir=`echo "$ax_lua_prefixed_path" | \
$SED "s|^$_ax_strip_prefix|$LUA_EXEC_PREFIX|"`
])
])
AC_SUBST([luaexecdir], [$ax_cv_lua_luaexecdir])
AC_SUBST([pkgluaexecdir], [\${luaexecdir}/$PACKAGE])
dnl Run any user specified action.
$3
])
])
dnl AX_WITH_LUA is now the same thing as AX_PROG_LUA.
AC_DEFUN([AX_WITH_LUA],
[
AC_MSG_WARN([[$0 is deprecated, please use AX_PROG_LUA instead]])
AX_PROG_LUA
])
dnl =========================================================================
dnl _AX_LUA_CHK_IS_INTRP(PROG, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
dnl =========================================================================
AC_DEFUN([_AX_LUA_CHK_IS_INTRP],
[
dnl A minimal Lua factorial to prove this is an interpreter. This should work
dnl for Lua interpreters version 5.0 and beyond.
_ax_lua_factorial=[`$1 2>/dev/null -e '
-- a simple factorial
function fact (n)
if n == 0 then
return 1
else
return n * fact(n-1)
end
end
print("fact(5) is " .. fact(5))'`]
AS_IF([test "$_ax_lua_factorial" = 'fact(5) is 120'],
[$2], [$3])
])
dnl =========================================================================
dnl _AX_LUA_CHK_VER(PROG, MINIMUM-VERSION, [TOO-BIG-VERSION],
dnl [ACTION-IF-TRUE], [ACTION-IF-FALSE])
dnl =========================================================================
AC_DEFUN([_AX_LUA_CHK_VER],
[
dnl Check that the Lua version is within the bounds. Only the major and minor
dnl version numbers are considered. This should work for Lua interpreters
dnl version 5.0 and beyond.
_ax_lua_good_version=[`$1 -e '
-- a script to compare versions
function verstr2num(verstr)
local _, _, majorver, minorver = string.find(verstr, "^(%d+)%.(%d+)")
if majorver and minorver then
return tonumber(majorver) * 100 + tonumber(minorver)
end
end
local minver = verstr2num("$2")
local _, _, trimver = string.find(_VERSION, "^Lua (.*)")
local ver = verstr2num(trimver)
local maxver = verstr2num("$3") or 1e9
if minver <= ver and ver < maxver then
print("yes")
else
print("no")
end'`]
AS_IF([test "x$_ax_lua_good_version" = "xyes"],
[$4], [$5])
])
dnl =========================================================================
dnl _AX_LUA_FND_PRFX_PTH(PROG, PREFIX, SCRIPT-OR-MODULE-DIR)
dnl =========================================================================
AC_DEFUN([_AX_LUA_FND_PRFX_PTH],
[
dnl Get the script or module directory by querying the Lua interpreter,
dnl filtering on the given prefix, and selecting the shallowest path. If no
dnl path is found matching the prefix, the result will be an empty string.
dnl The third argument determines the type of search, it can be 'script' or
dnl 'module'. Supplying 'script' will perform the search with package.path
dnl and LUA_PATH, and supplying 'module' will search with package.cpath and
dnl LUA_CPATH. This is done for compatibility with Lua 5.0.
ax_lua_prefixed_path=[`$1 -e '
-- get the path based on search type
local searchtype = "$3"
local paths = ""
if searchtype == "script" then
paths = (package and package.path) or LUA_PATH
elseif searchtype == "module" then
paths = (package and package.cpath) or LUA_CPATH
end
-- search for the prefix
local prefix = "'$2'"
local minpath = ""
local mindepth = 1e9
string.gsub(paths, "(@<:@^;@:>@+)",
function (path)
path = string.gsub(path, "%?.*$", "")
path = string.gsub(path, "/@<:@^/@:>@*$", "")
if string.find(path, prefix) then
local depth = string.len(string.gsub(path, "@<:@^/@:>@", ""))
if depth < mindepth then
minpath = path
mindepth = depth
end
end
end)
print(minpath)'`]
])
dnl =========================================================================
dnl AX_LUA_HEADERS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl =========================================================================
AC_DEFUN([AX_LUA_HEADERS],
[
dnl Check for LUA_VERSION.
AC_MSG_CHECKING([if LUA_VERSION is defined])
AS_IF([test "x$LUA_VERSION" != 'x'],
[AC_MSG_RESULT([yes])],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([cannot check Lua headers without knowing LUA_VERSION])
])
dnl Make LUA_INCLUDE a precious variable.
AC_ARG_VAR([LUA_INCLUDE], [The Lua includes, e.g. -I/usr/include/lua5.1])
dnl Some default directories to search.
LUA_SHORT_VERSION=`echo "$LUA_VERSION" | $SED 's|\.||'`
m4_define_default([_AX_LUA_INCLUDE_LIST],
[ /usr/include/lua$LUA_VERSION \
/usr/include/lua-$LUA_VERSION \
/usr/include/lua/$LUA_VERSION \
/usr/include/lua$LUA_SHORT_VERSION \
/usr/local/include/lua$LUA_VERSION \
/usr/local/include/lua-$LUA_VERSION \
/usr/local/include/lua/$LUA_VERSION \
/usr/local/include/lua$LUA_SHORT_VERSION \
])
dnl Try to find the headers.
_ax_lua_saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h])
CPPFLAGS=$_ax_lua_saved_cppflags
dnl Try some other directories if LUA_INCLUDE was not set.
AS_IF([test "x$LUA_INCLUDE" = 'x' &&
test "x$ac_cv_header_lua_h" != 'xyes'],
[ dnl Try some common include paths.
for _ax_include_path in _AX_LUA_INCLUDE_LIST; do
test ! -d "$_ax_include_path" && continue
AC_MSG_CHECKING([for Lua headers in])
AC_MSG_RESULT([$_ax_include_path])
AS_UNSET([ac_cv_header_lua_h])
AS_UNSET([ac_cv_header_lualib_h])
AS_UNSET([ac_cv_header_lauxlib_h])
AS_UNSET([ac_cv_header_luaconf_h])
_ax_lua_saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS -I$_ax_include_path"
AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h])
CPPFLAGS=$_ax_lua_saved_cppflags
AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'],
[ LUA_INCLUDE="-I$_ax_include_path"
break
])
done
])
AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'],
[ dnl Make a program to print LUA_VERSION defined in the header.
dnl TODO It would be really nice if we could do this without compiling a
dnl program, then it would work when cross compiling. But I'm not sure how
dnl to do this reliably. For now, assume versions match when cross compiling.
AS_IF([test "x$cross_compiling" != 'xyes'],
[ AC_CACHE_CHECK([for Lua header version],
[ax_cv_lua_header_version],
[ _ax_lua_saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
AC_COMPUTE_INT(ax_cv_lua_header_version_major,[LUA_VERSION_NUM/100],[AC_INCLUDES_DEFAULT
#include <lua.h>
],[ax_cv_lua_header_version_major=unknown])
AC_COMPUTE_INT(ax_cv_lua_header_version_minor,[LUA_VERSION_NUM%100],[AC_INCLUDES_DEFAULT
#include <lua.h>
],[ax_cv_lua_header_version_minor=unknown])
AS_IF([test "x$ax_cv_lua_header_version_major" = xunknown || test "x$ax_cv_lua_header_version_minor" = xunknown],[
ax_cv_lua_header_version=unknown
],[
ax_cv_lua_header_version="$ax_cv_lua_header_version_major.$ax_cv_lua_header_version_minor"
])
CPPFLAGS=$_ax_lua_saved_cppflags
])
dnl Compare this to the previously found LUA_VERSION.
AC_MSG_CHECKING([if Lua header version matches $LUA_VERSION])
AS_IF([test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"],
[ AC_MSG_RESULT([yes])
ax_header_version_match='yes'
],
[ AC_MSG_RESULT([no])
ax_header_version_match='no'
])
],
[ AC_MSG_WARN([cross compiling so assuming header version number matches])
ax_header_version_match='yes'
])
])
dnl Was LUA_INCLUDE specified?
AS_IF([test "x$ax_header_version_match" != 'xyes' &&
test "x$LUA_INCLUDE" != 'x'],
[AC_MSG_ERROR([cannot find headers for specified LUA_INCLUDE])])
dnl Test the final result and run user code.
AS_IF([test "x$ax_header_version_match" = 'xyes'], [$1],
[m4_default([$2], [AC_MSG_ERROR([cannot find Lua includes])])])
])
dnl AX_LUA_HEADERS_VERSION no longer exists, use AX_LUA_HEADERS.
AC_DEFUN([AX_LUA_HEADERS_VERSION],
[
AC_MSG_WARN([[$0 is deprecated, please use AX_LUA_HEADERS instead]])
])
dnl =========================================================================
dnl AX_LUA_LIBS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl =========================================================================
AC_DEFUN([AX_LUA_LIBS],
[
dnl TODO Should this macro also check various -L flags?
dnl Check for LUA_VERSION.
AC_MSG_CHECKING([if LUA_VERSION is defined])
AS_IF([test "x$LUA_VERSION" != 'x'],
[AC_MSG_RESULT([yes])],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([cannot check Lua libs without knowing LUA_VERSION])
])
dnl Make LUA_LIB a precious variable.
AC_ARG_VAR([LUA_LIB], [The Lua library, e.g. -llua5.1])
AS_IF([test "x$LUA_LIB" != 'x'],
[ dnl Check that LUA_LIBS works.
_ax_lua_saved_libs=$LIBS
LIBS="$LIBS $LUA_LIB"
AC_SEARCH_LIBS([lua_load], [],
[_ax_found_lua_libs='yes'],
[_ax_found_lua_libs='no'])
LIBS=$_ax_lua_saved_libs
dnl Check the result.
AS_IF([test "x$_ax_found_lua_libs" != 'xyes'],
[AC_MSG_ERROR([cannot find libs for specified LUA_LIB])])
],
[ dnl First search for extra libs.
_ax_lua_extra_libs=''
_ax_lua_saved_libs=$LIBS
LIBS="$LIBS $LUA_LIB"
AC_SEARCH_LIBS([exp], [m])
AC_SEARCH_LIBS([dlopen], [dl])
LIBS=$_ax_lua_saved_libs
AS_IF([test "x$ac_cv_search_exp" != 'xno' &&
test "x$ac_cv_search_exp" != 'xnone required'],
[_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_exp"])
AS_IF([test "x$ac_cv_search_dlopen" != 'xno' &&
test "x$ac_cv_search_dlopen" != 'xnone required'],
[_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_dlopen"])
dnl Try to find the Lua libs.
_ax_lua_saved_libs=$LIBS
LIBS="$LIBS $LUA_LIB"
AC_SEARCH_LIBS([lua_load],
[ lua$LUA_VERSION \
lua$LUA_SHORT_VERSION \
lua-$LUA_VERSION \
lua-$LUA_SHORT_VERSION \
:liblua-$LUA_VERSION.so.0 \
:liblua-$LUA_SHORT_VERSION.so.0 \
lua \
],
[_ax_found_lua_libs='yes'],
[_ax_found_lua_libs='no'],
[$_ax_lua_extra_libs])
LIBS=$_ax_lua_saved_libs
AS_IF([test "x$ac_cv_search_lua_load" != 'xno' &&
test "x$ac_cv_search_lua_load" != 'xnone required'],
[LUA_LIB="$ac_cv_search_lua_load $_ax_lua_extra_libs"])
])
dnl Test the result and run user code.
AS_IF([test "x$_ax_found_lua_libs" = 'xyes'], [$1],
[m4_default([$2], [AC_MSG_ERROR([cannot find Lua libs])])])
])
dnl =========================================================================
dnl AX_LUA_READLINE([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl =========================================================================
AC_DEFUN([AX_LUA_READLINE],
[
AX_LIB_READLINE
AS_IF([test "x$ac_cv_header_readline_readline_h" != 'x' &&
test "x$ac_cv_header_readline_history_h" != 'x'],
[ LUA_LIBS_CFLAGS="-DLUA_USE_READLINE $LUA_LIBS_CFLAGS"
$1
],
[$2])
])
Executable → Regular
View File
+37
View File
@@ -0,0 +1,37 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_require_defined.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_REQUIRE_DEFINED(MACRO)
#
# DESCRIPTION
#
# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
# been defined and thus are available for use. This avoids random issues
# where a macro isn't expanded. Instead the configure script emits a
# non-fatal:
#
# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
#
# It's like AC_REQUIRE except it doesn't expand the required macro.
#
# Here's an example:
#
# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
#
# LICENSE
#
# Copyright (c) 2014 Mike Frysinger <vapier@gentoo.org>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 2
AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
])dnl AX_REQUIRE_DEFINED
Executable → Regular
View File
+32 -1
View File
@@ -400,7 +400,7 @@ AC_DEFUN([TORRENT_WITH_XMLRPC_C], [
else
xmlrpc_cc_prg="$withval"
fi
if eval $xmlrpc_cc_prg --version 2>/dev/null >/dev/null; then
CXXFLAGS="$CXXFLAGS `$xmlrpc_cc_prg --cflags server-util`"
LIBS="$LIBS `$xmlrpc_cc_prg server-util --libs`"
@@ -426,6 +426,37 @@ AC_DEFUN([TORRENT_WITH_XMLRPC_C], [
])
])
AC_DEFUN([TORRENT_WITH_TINYXML2], [
AC_MSG_CHECKING(for tinyxml2)
AC_ARG_WITH(xmlrpc-tinyxml2,
AS_HELP_STRING([--with-xmlrpc-tinyxml2],[enable XMLRPC support via tinyxml2]),
[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_XMLRPC_TINYXML2, 1, Support for XMLRPC via tinyxml2.)
],[
AC_MSG_RESULT(ignored)
])
])
AC_DEFUN([TORRENT_WITH_LUA], [
AC_ARG_WITH(lua,
AS_HELP_STRING([--with-lua],[enable LUA support]),
[
if test "$withval" = "no"; then
AC_MSG_RESULT(no)
else
AX_PROG_LUA
AX_LUA_LIBS
AX_LUA_HEADERS
AC_DEFINE(HAVE_LUA, 1, Use LUA.)
LIBS="$LIBS $LUA_LIB"
CXXFLAGS="$CXXFLAGS $LUA_INCLUDE"
fi
],[
AC_MSG_RESULT(ignored)
])
])
AC_DEFUN([TORRENT_WITH_INOTIFY], [
AC_LANG_PUSH(C++)
+14 -1
View File
@@ -13,7 +13,7 @@ AC_DEFUN([TORRENT_WITH_SYSROOT], [
AC_MSG_ERROR(The sysroot option must point to a directory, like f.ex "/Developer/SDKs/MacOSX10.4u.sdk".)
else
AC_MSG_RESULT($withval)
CXXFLAGS="$CXXFLAGS -isysroot $withval"
LDFLAGS="$LDFLAGS -Wl,-syslibroot,$withval"
fi
@@ -21,6 +21,19 @@ AC_DEFUN([TORRENT_WITH_SYSROOT], [
])
AC_DEFUN([TORRENT_REMOVE_UNWANTED],
[
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'/ }
fi
])
AC_DEFUN([TORRENT_ENABLE_ARCH], [
AC_ARG_ENABLE(arch,
AS_HELP_STRING([--enable-arch=ARCH],
+16
View File
@@ -37,6 +37,7 @@ libsub_root_a_SOURCES = \
display/attributes.h \
display/canvas.cc \
display/canvas.h \
display/color_map.h \
display/frame.cc \
display/frame.h \
display/manager.cc \
@@ -107,6 +108,12 @@ libsub_root_a_SOURCES = \
rpc/exec_file.h \
rpc/fixed_key.h \
rpc/ip_table_list.h \
rpc/lua.h \
rpc/lua.cc \
rpc/jsonrpc.cc \
rpc/jsonrpc.h \
rpc/rpc_manager.cc \
rpc/rpc_manager.h \
rpc/object_storage.cc \
rpc/object_storage.h \
rpc/parse.cc \
@@ -121,6 +128,11 @@ libsub_root_a_SOURCES = \
rpc/scgi_task.h \
rpc/xmlrpc.h \
rpc/xmlrpc.cc \
rpc/xmlrpc_c.cc \
rpc/xmlrpc_tinyxml2.cc \
rpc/tinyxml2/tinyxml2.h \
rpc/tinyxml2/tinyxml2.cc \
rpc/nlohmann/json.h \
\
ui/download.cc \
ui/download.h \
@@ -151,10 +163,13 @@ libsub_root_a_SOURCES = \
ui/root.cc \
ui/root.h \
\
utils/base64.cc \
utils/base64.h \
utils/directory.cc \
utils/directory.h \
utils/file_status_cache.cc \
utils/file_status_cache.h \
utils/functional.h \
utils/list_focus.h \
utils/lockfile.cc \
utils/lockfile.h \
@@ -190,4 +205,5 @@ libsub_root_a_SOURCES = \
thread_worker.cc \
thread_worker.h
AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir)
+30 -70
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
#include "config.h"
#include <functional>
#include <unistd.h>
#include <cstdio>
#include <functional>
#include <netdb.h>
#include <unistd.h>
#include <rak/file_stat.h>
#include <rak/error_number.h>
#include <rak/path.h>
@@ -47,14 +12,16 @@
#include <rak/regex.h>
#include <torrent/rate.h>
#include <torrent/throttle.h>
#include <torrent/tracker.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>
#include <torrent/data/file.h>
#include <torrent/data/file_list.h>
#include <torrent/download/resource_manager.h>
#include <torrent/net/resolver.h>
#include <torrent/net/types.h>
#include <torrent/peer/connection_list.h>
#include <torrent/peer/peer_list.h>
#include <torrent/utils/log.h>
@@ -104,7 +71,7 @@ apply_d_change_link(core::Download* download, const torrent::Object::list_type&
const std::string& type = (itr++)->as_string();
const std::string& prefix = (itr++)->as_string();
const std::string& postfix = (itr++)->as_string();
if (type.empty())
throw torrent::input_error("Invalid arguments.");
@@ -319,21 +286,6 @@ retrieve_d_bitfield(core::Download* download) {
return torrent::Object(rak::transform_hex(bitField->begin(), bitField->end()));
}
struct call_add_d_peer_t {
call_add_d_peer_t(core::Download* d, int port) : m_download(d), m_port(port) { }
void operator() (const sockaddr* sa, int err) {
if (sa == NULL) {
lt_log_print(torrent::LOG_TORRENT_WARN, "could not resolve hostname for added peer");
} else {
m_download->download()->add_peer(sa, m_port);
}
}
core::Download* m_download;
int m_port;
};
void
apply_d_add_peer(core::Download* download, const std::string& arg) {
int port, ret;
@@ -356,7 +308,15 @@ apply_d_add_peer(core::Download* download, const std::string& arg) {
if (port < 1 || port > 65535)
throw torrent::input_error("Invalid port number.");
torrent::connection_manager()->resolver()(host, (int)rak::socket_address::pf_unspec, SOCK_STREAM, call_add_d_peer_t(download, port));
// 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) {
if (sa == nullptr) {
lt_log_print(torrent::LOG_TORRENT_WARN, "could not resolve hostname for added peer: %s", gai_strerror(err));
return;
}
download->download()->add_peer(sa.get(), port);
});
}
torrent::Object
@@ -410,7 +370,7 @@ f_multicall(core::Download* download, const torrent::Object::list_type& args) {
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(itr->get()), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
@@ -435,9 +395,9 @@ t_multicall(core::Download* download, const torrent::Object::list_type& args) {
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string();
torrent::Tracker* t = download->tracker_list()->at(itr);
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(&t), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
@@ -593,8 +553,7 @@ d_list_push_back_unique(core::Download* download, const torrent::Object& rawArgs
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();
if (std::find_if(list.begin(), list.end(),
rak::bind1st(std::ptr_fun(&torrent::object_equal), args)) == list.end())
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);
return torrent::Object();
@@ -605,8 +564,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(),
rak::bind1st(std::ptr_fun(&torrent::object_equal), args)) != list.end());
return (int64_t)(std::find_if(list.begin(), list.end(), [args](const torrent::Object& obj) { return torrent::object_equal(obj, args); }) != list.end());
}
torrent::Object
@@ -614,7 +572,7 @@ d_list_remove(core::Download* download, const torrent::Object& rawArgs, const ch
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();
list.erase(std::remove_if(list.begin(), list.end(), rak::bind1st(std::ptr_fun(&torrent::object_equal), args)), list.end());
list.erase(std::remove_if(list.begin(), list.end(), [args](const torrent::Object& obj) { return torrent::object_equal(obj, args); }), list.end());
return torrent::Object();
}
@@ -629,7 +587,6 @@ d_list_remove(core::Download* download, const torrent::Object& rawArgs, const ch
#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)
@@ -873,8 +830,8 @@ initialize_command_download() {
CMD2_DL ("d.wanted_chunks", CMD2_ON_DATA(wanted_chunks));
// Do not exposre d.tracker_announce.force to regular users.
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_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));
@@ -882,8 +839,11 @@ initialize_command_download() {
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_LIST ("d.tracker.insert", std::bind(&download_tracker_insert, std::placeholders::_1, std::placeholders::_2));
CMD2_DL_VALUE_V ("d.tracker.send_scrape", std::bind(&torrent::TrackerController::scrape_request, CMD2_BIND_TC, std::placeholders::_2));
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_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); });
CMD2_DL ("d.directory", CMD2_ON_FL(root_dir));
CMD2_DL_STRING_V("d.directory.set", std::bind(&apply_d_directory, std::placeholders::_1, std::placeholders::_2));
@@ -905,7 +865,7 @@ initialize_command_download() {
// CG_GROUP_INDEX()));
CMD2_DL ("d.group", std::bind(&cg_d_group, std::placeholders::_1));
CMD2_DL ("d.group.name", std::bind(&cg_d_group, std::placeholders::_1));
CMD2_DL ("d.group.name", std::bind(&cg_d_group_name, std::placeholders::_1));
CMD2_DL_V ("d.group.set", std::bind(&cg_d_group_set, std::placeholders::_1, std::placeholders::_2));
CMD2_DL_LIST ("f.multicall", std::bind(&f_multicall, std::placeholders::_1, std::placeholders::_2));
+105 -85
View File
@@ -5,12 +5,12 @@
// 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
@@ -40,25 +40,24 @@
#include <torrent/utils/log.h>
#include <torrent/utils/option_strings.h>
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
#include "control.h"
#include "globals.h"
#include "rpc/parse.h"
#include "rpc/parse_options.h"
static std::vector<std::pair<const char*, int>> object_storage_flags = {
{ "multi", rpc::object_storage::flag_multi_type },
{ "simple", rpc::object_storage::flag_function_type },
{ "value", rpc::object_storage::flag_value_type },
{ "bool", rpc::object_storage::flag_bool_type },
{ "string", rpc::object_storage::flag_string_type },
{ "list", rpc::object_storage::flag_list_type },
{"multi", rpc::object_storage::flag_multi_type},
{"simple", rpc::object_storage::flag_function_type},
{"value", rpc::object_storage::flag_value_type},
{"bool", rpc::object_storage::flag_bool_type},
{"string", rpc::object_storage::flag_string_type},
{"list", rpc::object_storage::flag_list_type},
{ "static", rpc::object_storage::flag_static },
{ "private", rpc::object_storage::flag_private },
{ "const", rpc::object_storage::flag_constant },
{ "rlookup", rpc::object_storage::flag_rlookup }
};
{"static", rpc::object_storage::flag_static},
{"private", rpc::object_storage::flag_private},
{"const", rpc::object_storage::flag_constant},
{"rlookup", rpc::object_storage::flag_rlookup}};
static int
object_storage_parse_flag(const std::string& flag) {
@@ -109,7 +108,7 @@ system_method_generate_command2(torrent::Object* object, torrent::Object::list_c
if (first + 1 == last) {
if (!first->is_dict_key())
throw torrent::input_error("New command of wrong type.");
*object = *first;
uint32_t flags = object->flags() & torrent::Object::mask_function;
@@ -122,9 +121,9 @@ system_method_generate_command2(torrent::Object* object, torrent::Object::list_c
while (first != last) {
if (!first->is_dict_key())
throw torrent::input_error("New command of wrong type.");
object->as_list().push_back(*first++);
uint32_t flags = object->as_list().back().flags() & torrent::Object::mask_function;
object->as_list().back().unset_flags(torrent::Object::mask_function);
object->as_list().back().set_flags((flags >> 1) & torrent::Object::mask_function);
@@ -134,20 +133,32 @@ system_method_generate_command2(torrent::Object* object, torrent::Object::list_c
// torrent::Object
// system_method_insert_function(const torrent::Object::list_type& args, int flags) {
// }
// This is only used by tinyxml2, xmlrpc-c intercepts the call internally
torrent::Object
system_listMethods() {
torrent::Object resultRaw = torrent::Object::create_list();
torrent::Object::list_type& result = resultRaw.as_list();
result.push_back("system.multicall"); // Handled directly by the XMLRPC code
for (auto itr : rpc::commands) {
result.push_back(itr.first);
}
return resultRaw;
}
torrent::Object
system_method_insert_object(const torrent::Object::list_type& args, int flags) {
if (args.empty())
throw torrent::input_error("Invalid argument count.");
torrent::Object::list_const_iterator itrArgs = args.begin();
const std::string& rawKey = (itrArgs++)->as_string();
const std::string& raw_key = (itrArgs++)->as_string();
if (rawKey.empty() ||
control->object_storage()->find_raw_string(torrent::raw_string::from_string(rawKey)) != control->object_storage()->end() ||
rpc::commands.has(rawKey) || rpc::commands.has(rawKey + ".set"))
if (raw_key.empty() ||
control->object_storage()->find_raw_string(torrent::raw_string::from_string(raw_key)) != control->object_storage()->end() ||
rpc::commands.has(raw_key) || rpc::commands.has(raw_key + ".set"))
throw torrent::input_error("Invalid key.");
torrent::Object value;
@@ -171,90 +182,101 @@ system_method_insert_object(const torrent::Object::list_type& args, int flags) {
throw torrent::input_error("Invalid type.");
}
// We must initialize this varriable to prevent a critical memory leak
int cmd_flags = rpc::CommandMap::flag_delete_key;
int cmd_flags = 0;
if (!(flags & rpc::object_storage::flag_static))
cmd_flags |= rpc::CommandMap::flag_modifiable;
if (!(flags & rpc::object_storage::flag_private))
cmd_flags |= rpc::CommandMap::flag_public_xmlrpc;
cmd_flags |= rpc::CommandMap::flag_public_rpc;
if ((flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_list_type) {
torrent::Object valueList = torrent::Object::create_list();
torrent::Object valueList = torrent::Object::create_list();
torrent::Object::list_type& valueListType = valueList.as_list();
if ((itrArgs)->is_list())
valueListType = (itrArgs)->as_list();
control->object_storage()->insert_str(rawKey, valueList, flags);
control->object_storage()->insert_str(raw_key, valueList, flags);
} else {
control->object_storage()->insert_str(rawKey, value, flags);
control->object_storage()->insert_str(raw_key, value, flags);
}
if ((flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_function_type ||
(flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_multi_type) {
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call<rpc::target_type> >::type>
(create_new_key(rawKey),
std::bind(&rpc::object_storage::call_function_str, control->object_storage(),
rawKey, std::placeholders::_1, std::placeholders::_2),
&rpc::command_base_call<rpc::target_type>,
cmd_flags, NULL, NULL);
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call<rpc::target_type>>::type>(
raw_key,
std::bind(&rpc::object_storage::call_function_str, control->object_storage(), raw_key, std::placeholders::_1, std::placeholders::_2),
&rpc::command_base_call<rpc::target_type>,
cmd_flags,
NULL,
NULL);
} else {
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call<rpc::target_type> >::type>
(create_new_key(rawKey),
std::bind(&rpc::object_storage::get_str, control->object_storage(), rawKey),
&rpc::command_base_call<rpc::target_type>,
cmd_flags, NULL, NULL);
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call<rpc::target_type>>::type>(
raw_key,
std::bind(&rpc::object_storage::get_str, control->object_storage(), raw_key),
&rpc::command_base_call<rpc::target_type>,
cmd_flags,
NULL,
NULL);
}
// Not the right argument.
// if (flags & rpc::object_storage::flag_rlookup) {
// rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_string<rpc::target_type> >::type>
// (create_new_key<9>(rawKey, ".rlookup"),
// std::bind(&rpc::object_storage::rlookup_obj_list, control->object_storage(), rawKey),
// (create_new_key<9>(raw_key, ".rlookup"),
// std::bind(&rpc::object_storage::rlookup_obj_list, control->object_storage(), raw_key),
// &rpc::command_base_call_string<rpc::target_type>,
// cmd_flags, NULL, NULL);
// }
// TODO: Next... Make test class for this.
// // Ehm... no proper handling if these throw.
// // Ehm... no proper handling if these throw.
if (!(flags & rpc::object_storage::flag_constant)) {
switch (flags & rpc::object_storage::mask_type) {
case rpc::object_storage::flag_bool_type:
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_value<rpc::target_type> >::type>
(create_new_key<5>(rawKey, ".set"),
std::bind(&rpc::object_storage::set_str_bool, control->object_storage(), rawKey, std::placeholders::_2),
&rpc::command_base_call_value<rpc::target_type>,
cmd_flags, NULL, NULL);
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_value<rpc::target_type>>::type>(
raw_key + ".set",
std::bind(&rpc::object_storage::set_str_bool, control->object_storage(), raw_key, std::placeholders::_2),
&rpc::command_base_call_value<rpc::target_type>,
cmd_flags,
NULL,
NULL);
break;
case rpc::object_storage::flag_value_type:
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_value<rpc::target_type> >::type>
(create_new_key<5>(rawKey, ".set"),
std::bind(&rpc::object_storage::set_str_value, control->object_storage(), rawKey, std::placeholders::_2),
&rpc::command_base_call_value<rpc::target_type>,
cmd_flags, NULL, NULL);
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_value<rpc::target_type>>::type>(
raw_key + ".set",
std::bind(&rpc::object_storage::set_str_value, control->object_storage(), raw_key, std::placeholders::_2),
&rpc::command_base_call_value<rpc::target_type>,
cmd_flags,
NULL,
NULL);
break;
case rpc::object_storage::flag_string_type:
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_string<rpc::target_type> >::type>
(create_new_key<5>(rawKey, ".set"),
std::bind(&rpc::object_storage::set_str_string, control->object_storage(), rawKey, std::placeholders::_2),
&rpc::command_base_call_string<rpc::target_type>,
cmd_flags, NULL, NULL);
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_string<rpc::target_type>>::type>(
raw_key + ".set",
std::bind(&rpc::object_storage::set_str_string, control->object_storage(), raw_key, std::placeholders::_2),
&rpc::command_base_call_string<rpc::target_type>,
cmd_flags,
NULL,
NULL);
break;
case rpc::object_storage::flag_list_type:
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_list<rpc::target_type> >::type>
(create_new_key<5>(rawKey, ".set"),
std::bind(&rpc::object_storage::set_str_list, control->object_storage(), rawKey, std::placeholders::_2),
&rpc::command_base_call_list<rpc::target_type>,
cmd_flags, NULL, NULL);
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_list<rpc::target_type>>::type>(
raw_key + ".set",
std::bind(&rpc::object_storage::set_str_list, control->object_storage(), raw_key, std::placeholders::_2),
&rpc::command_base_call_list<rpc::target_type>,
cmd_flags,
NULL,
NULL);
break;
case rpc::object_storage::flag_function_type:
case rpc::object_storage::flag_multi_type:
default: break;
default:
break;
}
}
@@ -282,22 +304,15 @@ system_method_insert(const torrent::Object::list_type& args) {
throw torrent::input_error("Invalid argument count.");
torrent::Object::list_const_iterator itrArgs = args.begin();
const std::string& rawKey = (itrArgs++)->as_string();
const std::string& raw_key = (itrArgs++)->as_string();
if (rawKey.empty() || rpc::commands.has(rawKey))
if (raw_key.empty() || rpc::commands.has(raw_key))
throw torrent::input_error("Invalid key.");
int flags = rpc::CommandMap::flag_delete_key | rpc::CommandMap::flag_modifiable | rpc::CommandMap::flag_public_xmlrpc;
int new_flags = rpc::parse_option_flags(itrArgs->as_string(), std::bind(&object_storage_parse_flag, std::placeholders::_1));
if ((new_flags & rpc::object_storage::flag_private))
flags &= ~rpc::CommandMap::flag_public_xmlrpc;
if ((new_flags & rpc::object_storage::flag_constant))
flags &= ~rpc::CommandMap::flag_modifiable;
torrent::Object::list_type new_args;
new_args.push_back(rawKey);
new_args.push_back(raw_key);
if ((new_flags & rpc::object_storage::flag_function_type) ||
(new_flags & rpc::object_storage::flag_multi_type)) {
@@ -345,8 +360,7 @@ system_method_redirect(const torrent::Object::list_type& args) {
std::string new_key = torrent::object_create_string(args.front());
std::string dest_key = torrent::object_create_string(args.back());
rpc::commands.create_redirect(create_new_key(new_key), create_new_key(dest_key),
rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_delete_key | rpc::CommandMap::flag_modifiable);
rpc::commands.create_redirect(new_key, dest_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_modifiable);
return torrent::Object();
}
@@ -372,9 +386,9 @@ system_method_has_key(const torrent::Object::list_type& args) {
throw torrent::input_error("Invalid argument count.");
torrent::Object::list_const_iterator itrArgs = args.begin();
const std::string& key = (itrArgs++)->as_string();
const std::string& cmd_key = (itrArgs++)->as_string();
const std::string& key = (itrArgs++)->as_string();
const std::string& cmd_key = (itrArgs++)->as_string();
return control->object_storage()->has_str_multi_key(key, cmd_key);
}
@@ -384,9 +398,9 @@ system_method_set_key(const torrent::Object::list_type& args) {
throw torrent::input_error("Invalid argument count.");
torrent::Object::list_const_iterator itrArgs = args.begin();
const std::string& key = (itrArgs++)->as_string();
const std::string& cmd_key = (itrArgs++)->as_string();
const std::string& key = (itrArgs++)->as_string();
const std::string& cmd_key = (itrArgs++)->as_string();
if (itrArgs == args.end()) {
control->object_storage()->erase_str_multi_key(key, cmd_key);
return torrent::Object();
@@ -403,9 +417,9 @@ 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();
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);
@@ -428,6 +442,11 @@ cmd_catch(rpc::target_type target, const torrent::Object& args) {
void
initialize_command_dynamic() {
// clang-format off
#ifdef HAVE_XMLRPC_TINYXML2
CMD2_ANY ("system.listMethods", std::bind(&system_listMethods)); // only used by tinyxml2
#endif
CMD2_VAR_BOOL ("method.use_deprecated", true);
CMD2_VAR_VALUE ("method.use_intermediate", 1);
@@ -472,4 +491,5 @@ initialize_command_dynamic() {
CMD2_ANY ("strings.log_group", std::bind(&torrent::option_list_strings, torrent::OPTION_LOG_GROUP));
CMD2_ANY ("strings.tracker_event", std::bind(&torrent::option_list_strings, torrent::OPTION_TRACKER_EVENT));
CMD2_ANY ("strings.tracker_mode", std::bind(&torrent::option_list_strings, torrent::OPTION_TRACKER_MODE));
// clang-format on
}
+18 -54
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 <functional>
@@ -66,14 +30,14 @@ apply_on_ratio(const torrent::Object& rawArgs) {
const std::string& groupName = rawArgs.as_string();
char buffer[32 + groupName.size()];
sprintf(buffer, "group2.%s.view", groupName.c_str());
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())
throw torrent::input_error("Could not find view.");
char* bufferStart = buffer + sprintf(buffer, "group2.%s.ratio.", groupName.c_str());
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]
@@ -103,7 +67,7 @@ apply_on_ratio(const torrent::Object& rawArgs) {
downloads.push_back(*itr);
}
sprintf(buffer, "group.%s.ratio.command", groupName.c_str());
snprintf(buffer, sizeof(buffer), "group.%s.ratio.command", groupName.c_str());
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.");
@@ -216,28 +180,27 @@ void apply_import(const std::string& path) { if (!rpc::parse_command_file(pa
void apply_try_import(const std::string& path) { if (!rpc::parse_command_file(path)) control->core()->push_log_std("Could not read resource file: " + path); }
torrent::Object
apply_close_low_diskspace(int64_t arg) {
core::DownloadList* downloadList = control->core()->download_list();
apply_close_low_diskspace(int64_t arg, uint32_t skip_priority) {
bool closed = false;
core::Manager::DListItr itr = downloadList->begin();
while ((itr = std::find_if(itr, downloadList->end(), std::mem_fun(&core::Download::is_downloading)))
!= downloadList->end()) {
if ((*itr)->file_list()->free_diskspace() < (uint64_t)arg) {
downloadList->close(*itr);
for (auto download : *control->core()->download_list()) {
if (!download->is_downloading())
continue;
if (download->priority() >= skip_priority)
continue;
if (download->file_list()->free_diskspace() >= (uint64_t)arg)
continue;
(*itr)->set_hash_failed(true);
(*itr)->set_message(std::string("Low diskspace."));
control->core()->download_list()->close(download);
closed = true;
}
download->set_hash_failed(true);
download->set_message(std::string("Low diskspace."));
++itr;
closed = true;
}
if (closed)
lt_log_print(torrent::LOG_TORRENT_ERROR, "Closed torrents due to low diskspace.");
lt_log_print(torrent::LOG_TORRENT_ERROR, "Closed torrents due to low diskspace.");
return torrent::Object();
}
@@ -391,7 +354,8 @@ initialize_command_events() {
core::Manager::create_quiet | core::Manager::create_start | core::Manager::create_raw_data));
CMD2_ANY_LIST ("load.raw_start_verbose", std::bind(&apply_load, std::placeholders::_2, core::Manager::create_start | core::Manager::create_raw_data));
CMD2_ANY_VALUE ("close_low_diskspace", std::bind(&apply_close_low_diskspace, std::placeholders::_2));
CMD2_ANY_VALUE ("close_low_diskspace", std::bind(&apply_close_low_diskspace, std::placeholders::_2, 99));
CMD2_ANY_VALUE ("close_low_diskspace.normal", std::bind(&apply_close_low_diskspace, std::placeholders::_2, 3));
CMD2_ANY_LIST ("download_list", std::bind(&apply_download_list, std::placeholders::_2));
CMD2_ANY_LIST ("d.multicall2", std::bind(&d_multicall, std::placeholders::_2));
+11 -11
View File
@@ -69,7 +69,7 @@ cg_d_group_set(core::Download* download, const torrent::Object& arg) {
torrent::Object
apply_cg_list() {
torrent::Object::list_type result;
for (torrent::ResourceManager::group_iterator
itr = torrent::resource_manager()->group_begin(),
last = torrent::resource_manager()->group_end(); itr != last; itr++)
@@ -121,8 +121,7 @@ cg_get_index(const torrent::Object& raw_args) {
if (arg.is_string()) {
if (!rpc::parse_whole_value_nothrow(arg.as_string().c_str(), &index)) {
std::vector<torrent::choke_group*>::iterator itr = std::find_if(cg_list_hack.begin(), cg_list_hack.end(),
rak::equal(arg.as_string(), std::mem_fun(&torrent::choke_group::name)));
auto itr = std::find_if(cg_list_hack.begin(), cg_list_hack.end(), [&arg](torrent::choke_group* cg) { return arg.as_string() == cg->name(); });
if (itr == cg_list_hack.end())
throw torrent::input_error("Choke group not found.");
@@ -154,14 +153,17 @@ cg_get_group(const torrent::Object& raw_args) {
}
int64_t cg_d_group(core::Download* download) { return download->group(); }
const std::string& cg_d_group_name(core::Download* download) {
return cg_list_hack.at(download->group())->name();
}
void cg_d_group_set(core::Download* download, const torrent::Object& arg) { download->set_group(cg_get_index(arg)); }
torrent::Object
apply_cg_list() {
torrent::Object::list_type result;
for (std::vector<torrent::choke_group*>::iterator itr = cg_list_hack.begin(), last = cg_list_hack.end(); itr != last; itr++)
result.push_back((*itr)->name());
for (auto itr : cg_list_hack)
result.push_back(itr->name());
return torrent::Object::from_list(result);
}
@@ -179,8 +181,7 @@ apply_cg_insert(const std::string& arg) {
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(),
rak::equal(arg, std::mem_fun(&torrent::choke_group::name))) != cg_list_hack.end())
std::find_if(cg_list_hack.begin(), cg_list_hack.end(), [&arg](torrent::choke_group* cg) { return arg == cg->name(); }) != cg_list_hack.end())
throw torrent::input_error("Duplicate name for choke group.");
cg_list_hack.push_back(new torrent::choke_group());
@@ -194,8 +195,7 @@ apply_cg_insert(const std::string& arg) {
torrent::Object
apply_cg_index_of(const std::string& arg) {
std::vector<torrent::choke_group*>::iterator itr =
std::find_if(cg_list_hack.begin(), cg_list_hack.end(), rak::equal(arg, std::mem_fun(&torrent::choke_group::name)));
auto itr = std::find_if(cg_list_hack.begin(), cg_list_hack.end(), [&arg](torrent::choke_group* cg) { return arg == cg->name(); });
if (itr == cg_list_hack.end())
throw torrent::input_error("Choke group not found.");
@@ -340,7 +340,7 @@ void
initialize_command_groups() {
CMD2_ANY ("choke_group.list", std::bind(&apply_cg_list));
CMD2_ANY_STRING ("choke_group.insert", std::bind(&apply_cg_insert, std::placeholders::_2));
#if USE_CHOKE_GROUP
CMD2_ANY ("choke_group.size", std::bind(&torrent::ResourceManager::group_size, torrent::resource_manager()));
CMD2_ANY_STRING ("choke_group.index_of", std::bind(&torrent::ResourceManager::group_index_of, torrent::resource_manager(), std::placeholders::_2));
+12 -68
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_UTILS_COMMAND_HELPERS_H
#define RTORRENT_UTILS_COMMAND_HELPERS_H
@@ -49,7 +13,7 @@ void initialize_commands();
#define CMD2_A_FUNCTION(key, function, slot, parm, doc) \
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::function>::type>(key, slot, &rpc::function, \
rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, NULL, NULL);
rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_rpc, NULL, NULL);
#define CMD2_A_FUNCTION_PRIVATE(key, function, slot, parm, doc) \
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::function>::type>(key, slot, &rpc::function, \
@@ -92,9 +56,9 @@ void initialize_commands();
#define CMD2_PEER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Peer*>, object_convert_void(slot), "i:", "")
#define CMD2_PEER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::Peer*>, object_convert_void(slot), "i:i", "")
#define CMD2_TRACKER(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Tracker*>, slot, "i:", "")
#define CMD2_TRACKER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Tracker*>, object_convert_void(slot), "i:", "")
#define CMD2_TRACKER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::Tracker*>, object_convert_void(slot), "i:i", "")
#define CMD2_TRACKER(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::tracker::Tracker*>, slot, "i:", "")
#define CMD2_TRACKER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::tracker::Tracker*>, object_convert_void(slot), "i:", "")
#define CMD2_TRACKER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::tracker::Tracker*>, object_convert_void(slot), "i:i", "")
#define CMD2_VAR_BOOL(key, value) \
control->object_storage()->insert_c_str(key, int64_t(value), rpc::object_storage::flag_bool_type); \
@@ -137,23 +101,23 @@ void initialize_commands();
std::placeholders::_1, std::placeholders::_2));
#define CMD2_REDIRECT(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_dont_delete);
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_xmlrpc | rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
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_FILE(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_file_target | rpc::CommandMap::flag_dont_delete);
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_xmlrpc | rpc::CommandMap::flag_tracker_target | rpc::CommandMap::flag_dont_delete);
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(create_new_key(from_key), create_new_key(to_key), \
rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_delete_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(create_new_key(from_key), create_new_key(to_key), \
rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_delete_key);
rpc::commands.create_redirect(from_key, to_key, \
rpc::CommandMap::flag_no_target);
//
// Conversion of return types:
@@ -188,24 +152,4 @@ template <typename T>
object_convert_type<T, void>
object_convert_void(T f) { return f; }
//
// Key creation:
//
template <int postfix_size>
inline const char*
create_new_key(const std::string& key, const char postfix[postfix_size]) {
char *buffer = new char[key.size() + std::max(postfix_size, 1)];
std::memcpy(buffer, key.c_str(), key.size() + 1);
std::memcpy(buffer + key.size(), postfix, postfix_size);
return buffer;
}
inline const char*
create_new_key(const std::string& key) {
char *buffer = new char[key.size() + 1];
std::memcpy(buffer, key.c_str(), key.size() + 1);
return buffer;
}
#endif
+13 -36
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 <fcntl.h>
@@ -60,6 +24,7 @@
#include "utils/file_status_cache.h"
#include "globals.h"
#include "rpc/lua.h"
#include "control.h"
#include "command_helpers.h"
@@ -241,6 +206,7 @@ initialize_command_local() {
CMD2_VAR_C_STRING("system.api_version", (int64_t)API_VERSION);
CMD2_VAR_C_STRING("system.client_version", PACKAGE_VERSION);
CMD2_VAR_C_STRING("system.library_version", torrent::version());
CMD2_VAR_VALUE ("system.file.allocate", 0);
CMD2_VAR_VALUE ("system.file.max_size", (int64_t)512 << 30);
CMD2_VAR_VALUE ("system.file.split_size", -1);
@@ -254,6 +220,10 @@ 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.opened_counter", std::bind(&FM_t::files_opened_counter, fileManager));
CMD2_ANY ("system.files.closed_counter", std::bind(&FM_t::files_closed_counter, fileManager));
CMD2_ANY ("system.files.failed_counter", std::bind(&FM_t::files_failed_counter, fileManager));
@@ -315,6 +285,13 @@ initialize_command_local() {
CMD2_ANY_V ("session.save", std::bind(&core::DownloadList::session_save, dList));
#ifdef HAVE_LUA
rpc::LuaEngine* lua_engine = control->lua_engine();
CMD2_ANY ("lua.execute", std::bind(&rpc::execute_lua, lua_engine, std::placeholders::_1, std::placeholders::_2, 0));
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) \
CMD2_ANY(key, std::bind(&rpc::ExecFile::execute_object, &rpc::execFile, std::placeholders::_2, flags));
+3 -2
View File
@@ -32,7 +32,7 @@ torrent::Object
apply_log_open(int output_flags, const torrent::Object::list_type& args) {
if (args.size() < 2)
throw torrent::input_error("Invalid number of arguments.");
torrent::Object::list_const_iterator itr = args.begin();
std::string output_id = (itr++)->as_string();
@@ -142,5 +142,6 @@ initialize_command_logging() {
CMD2_ANY_STRING ("log.execute", std::bind(&apply_log, std::placeholders::_2, 0));
CMD2_ANY_STRING ("log.vmmap.dump", std::bind(&log_vmmap_dump, std::placeholders::_2));
CMD2_ANY_STRING_V("log.xmlrpc", std::bind(&ThreadWorker::set_xmlrpc_log, worker_thread, std::placeholders::_2));
CMD2_ANY_STRING_V("log.rpc", std::bind(&ThreadWorker::set_rpc_log, worker_thread, std::placeholders::_2));
CMD2_REDIRECT ("log.xmlrpc", "log.rpc"); // For backwards compatibility
}
+38 -79
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 <functional>
@@ -42,8 +6,8 @@
#include <rak/address_info.h>
#include <rak/path.h>
#include <torrent/connection_manager.h>
#include <torrent/tracker.h>
#include <torrent/tracker_list.h>
#include <torrent/tracker/tracker.h>
#include <torrent/torrent.h>
#include <torrent/rate.h>
#include <torrent/data/file_manager.h>
@@ -94,51 +58,44 @@ 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(); }
torrent::File*
xmlrpc_find_file(core::Download* download, uint32_t index) {
if (index >= download->file_list()->size_files())
return NULL;
return (*download->file_list())[index];
}
// Ergh... time to update the Tracker API to allow proper ptrs.
torrent::Tracker*
xmlrpc_find_tracker(core::Download* download, uint32_t index) {
if (index >= download->tracker_list()->size())
return NULL;
return download->tracker_list()->at(index);
}
torrent::Peer*
xmlrpc_find_peer(core::Download* download, const torrent::HashString& hash) {
torrent::ConnectionList::iterator itr = download->connection_list()->find(hash.c_str());
if (itr == download->connection_list()->end())
return NULL;
return *itr;
}
void
initialize_xmlrpc() {
rpc::xmlrpc.initialize();
rpc::xmlrpc.slot_find_download() = std::bind(&core::DownloadList::find_hex_ptr, control->core()->download_list(), std::placeholders::_1);
rpc::xmlrpc.slot_find_file() = std::bind(&xmlrpc_find_file, std::placeholders::_1, std::placeholders::_2);
rpc::xmlrpc.slot_find_tracker() = std::bind(&xmlrpc_find_tracker, std::placeholders::_1, std::placeholders::_2);
rpc::xmlrpc.slot_find_peer() = std::bind(&xmlrpc_find_peer, std::placeholders::_1, std::placeholders::_2);
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;
};
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_xmlrpc))
if (!(itr->second.m_flags & rpc::CommandMap::flag_public_rpc))
continue;
rpc::xmlrpc.insert_command(itr->first, itr->second.m_parm, itr->second.m_doc);
rpc::rpc.insert_command(itr->first.c_str(), itr->second.m_parm, itr->second.m_doc);
}
lt_log_print(torrent::LOG_RPC_EVENTS, "XMLRPC initialized with %u functions.", count);
lt_log_print(torrent::LOG_RPC_EVENTS, "RPC initialized with %u functions.", count);
}
torrent::Object
@@ -146,8 +103,7 @@ apply_scgi(const std::string& arg, int type) {
if (worker_thread->scgi() != NULL)
throw torrent::input_error("SCGI already enabled.");
if (!rpc::xmlrpc.is_valid())
initialize_xmlrpc();
initialize_rpc();
rpc::SCgi* scgi = new rpc::SCgi;
@@ -225,7 +181,7 @@ apply_xmlrpc_dialect(const std::string& arg) {
else
value = -1;
rpc::xmlrpc.set_dialect(value);
rpc::rpc.set_dialect(value);
return torrent::Object();
}
@@ -298,9 +254,12 @@ initialize_command_network() {
CMD2_ANY_STRING ("network.scgi.open_local", std::bind(&apply_scgi, std::placeholders::_2, 2));
CMD2_VAR_BOOL ("network.scgi.dont_route", false);
CMD2_ANY_STRING ("network.xmlrpc.dialect.set", std::bind(&apply_xmlrpc_dialect, std::placeholders::_2));
CMD2_ANY ("network.xmlrpc.size_limit", std::bind(&rpc::XmlRpc::size_limit));
CMD2_ANY_VALUE_V ("network.xmlrpc.size_limit.set", std::bind(&rpc::XmlRpc::set_size_limit, std::placeholders::_2));
CMD2_ANY_STRING ("network.xmlrpc.dialect.set", [](const auto&, const auto& arg) { return apply_xmlrpc_dialect(arg); })
CMD2_ANY ("network.xmlrpc.size_limit", [](const auto&, const auto&){ return rpc::rpc.size_limit(); });
CMD2_ANY_VALUE_V ("network.xmlrpc.size_limit.set", [](const auto&, const auto& arg){ return rpc::rpc.set_size_limit(arg); });
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));
+51 -90
View File
@@ -1,46 +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 <cstdio>
#include <netdb.h>
#include <rak/address_info.h>
#include <rak/error_number.h>
#include <torrent/dht_manager.h>
#include <torrent/tracker.h>
#include <torrent/net/resolver.h>
#include <torrent/tracker/dht_controller.h>
#include <torrent/tracker/tracker.h>
#include <torrent/utils/log.h>
#include "core/download.h"
@@ -52,30 +18,16 @@
#include "core/dht_manager.h"
void
tracker_set_enabled(torrent::Tracker* tracker, bool state) {
tracker_set_enabled(torrent::tracker::Tracker* tracker, bool state) {
if (state)
tracker->enable();
else
tracker->disable();
}
struct call_add_node_t {
call_add_node_t(int port) : m_port(port) { }
void operator() (const sockaddr* sa, int err) {
if (sa == NULL) {
lt_log_print(torrent::LOG_DHT_WARN, "Could not resolve host.");
} else {
torrent::dht_manager()->add_node(sa, m_port);
}
}
int m_port;
};
torrent::Object
apply_dht_add_node(const std::string& arg) {
if (!torrent::dht_manager()->is_valid())
if (!torrent::dht_controller()->is_valid())
throw torrent::input_error("DHT not enabled.");
int port, ret;
@@ -92,68 +44,77 @@ apply_dht_add_node(const std::string& arg) {
if (port < 1 || port > 65535)
throw torrent::input_error("Invalid port number.");
torrent::connection_manager()->resolver()(host, (int)rak::socket_address::pf_inet, SOCK_DGRAM, call_add_node_t(port));
// Currently discarding SOCK_STREAM.
torrent::main_thread()->resolver()->resolve_specific(nullptr, host, PF_INET, [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));
return;
}
torrent::dht_controller()->add_node(sa.get(), port);
});
return torrent::Object();
}
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(),
arg ? std::mem_fun(&torrent::Tracker::enable) : std::mem_fun(&torrent::Tracker::disable));
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 && !rpc::call_command_value("trackers.use_udp"))
(*itr)->enable_udp_trackers(false);
}
}
return torrent::Object();
}
void
initialize_command_tracker() {
CMD2_TRACKER ("t.is_open", std::bind(&torrent::Tracker::is_busy, std::placeholders::_1));
CMD2_TRACKER ("t.is_enabled", std::bind(&torrent::Tracker::is_enabled, std::placeholders::_1));
CMD2_TRACKER ("t.is_usable", std::bind(&torrent::Tracker::is_usable, std::placeholders::_1));
CMD2_TRACKER ("t.is_busy", std::bind(&torrent::Tracker::is_busy, std::placeholders::_1));
CMD2_TRACKER ("t.is_extra_tracker", std::bind(&torrent::Tracker::is_extra_tracker, std::placeholders::_1));
CMD2_TRACKER ("t.can_scrape", std::bind(&torrent::Tracker::can_scrape, std::placeholders::_1));
CMD2_TRACKER ("t.is_busy", std::bind(&torrent::tracker::Tracker::is_busy, std::placeholders::_1));
CMD2_TRACKER ("t.is_enabled", std::bind(&torrent::tracker::Tracker::is_enabled, std::placeholders::_1));
CMD2_TRACKER ("t.is_extra_tracker", std::bind(&torrent::tracker::Tracker::is_extra_tracker, std::placeholders::_1));
CMD2_TRACKER ("t.is_open", std::bind(&torrent::tracker::Tracker::is_busy, std::placeholders::_1));
CMD2_TRACKER ("t.is_scrapable", std::bind(&torrent::tracker::Tracker::is_scrapable, std::placeholders::_1));
CMD2_TRACKER ("t.is_usable", std::bind(&torrent::tracker::Tracker::is_usable, std::placeholders::_1));
CMD2_TRACKER_V ("t.enable", std::bind(&torrent::Tracker::enable, std::placeholders::_1));
CMD2_TRACKER_V ("t.disable", std::bind(&torrent::Tracker::disable, std::placeholders::_1));
// TODO: Deprecate.
CMD2_TRACKER ("t.can_scrape", std::bind(&torrent::tracker::Tracker::is_scrapable, std::placeholders::_1));
CMD2_TRACKER_V ("t.enable", std::bind(&torrent::tracker::Tracker::enable, std::placeholders::_1));
CMD2_TRACKER_V ("t.disable", std::bind(&torrent::tracker::Tracker::disable, std::placeholders::_1));
CMD2_TRACKER_VALUE_V("t.is_enabled.set", std::bind(&tracker_set_enabled, std::placeholders::_1, std::placeholders::_2));
CMD2_TRACKER ("t.url", std::bind(&torrent::Tracker::url, std::placeholders::_1));
CMD2_TRACKER ("t.group", std::bind(&torrent::Tracker::group, std::placeholders::_1));
CMD2_TRACKER ("t.type", std::bind(&torrent::Tracker::type, std::placeholders::_1));
CMD2_TRACKER ("t.id", std::bind(&torrent::Tracker::tracker_id, std::placeholders::_1));
CMD2_TRACKER ("t.url", std::bind(&torrent::tracker::Tracker::url, std::placeholders::_1));
CMD2_TRACKER ("t.group", std::bind(&torrent::tracker::Tracker::group, std::placeholders::_1));
CMD2_TRACKER ("t.type", std::bind(&torrent::tracker::Tracker::type, std::placeholders::_1));
CMD2_TRACKER ("t.id", std::bind(&torrent::tracker::Tracker::tracker_id, std::placeholders::_1));
CMD2_TRACKER ("t.latest_event", std::bind(&torrent::Tracker::latest_event, std::placeholders::_1));
CMD2_TRACKER ("t.latest_new_peers", std::bind(&torrent::Tracker::latest_new_peers, std::placeholders::_1));
CMD2_TRACKER ("t.latest_sum_peers", std::bind(&torrent::Tracker::latest_sum_peers, std::placeholders::_1));
CMD2_TRACKER ("t.latest_event", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().latest_event(); });
CMD2_TRACKER ("t.latest_new_peers", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().latest_new_peers(); });
CMD2_TRACKER ("t.latest_sum_peers", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().latest_sum_peers(); });
// Time since last connection, connection attempt.
CMD2_TRACKER ("t.normal_interval", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().normal_interval(); });
CMD2_TRACKER ("t.min_interval", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().min_interval(); });
CMD2_TRACKER ("t.normal_interval", std::bind(&torrent::Tracker::normal_interval, std::placeholders::_1));
CMD2_TRACKER ("t.min_interval", std::bind(&torrent::Tracker::min_interval, std::placeholders::_1));
CMD2_TRACKER ("t.activity_time_next", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().activity_time_next(); });
CMD2_TRACKER ("t.activity_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().activity_time_last(); });
CMD2_TRACKER ("t.activity_time_next", std::bind(&torrent::Tracker::activity_time_next, std::placeholders::_1));
CMD2_TRACKER ("t.activity_time_last", std::bind(&torrent::Tracker::activity_time_last, std::placeholders::_1));
CMD2_TRACKER ("t.success_time_next", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().success_time_next(); });
CMD2_TRACKER ("t.success_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().success_time_last(); });
CMD2_TRACKER ("t.success_counter", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().success_counter(); });
CMD2_TRACKER ("t.success_time_next", std::bind(&torrent::Tracker::success_time_next, std::placeholders::_1));
CMD2_TRACKER ("t.success_time_last", std::bind(&torrent::Tracker::success_time_last, std::placeholders::_1));
CMD2_TRACKER ("t.success_counter", std::bind(&torrent::Tracker::success_counter, std::placeholders::_1));
CMD2_TRACKER ("t.failed_time_next", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().failed_time_next(); });
CMD2_TRACKER ("t.failed_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().failed_time_last(); });
CMD2_TRACKER ("t.failed_counter", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().failed_counter(); });
CMD2_TRACKER ("t.failed_time_next", std::bind(&torrent::Tracker::failed_time_next, std::placeholders::_1));
CMD2_TRACKER ("t.failed_time_last", std::bind(&torrent::Tracker::failed_time_last, std::placeholders::_1));
CMD2_TRACKER ("t.failed_counter", std::bind(&torrent::Tracker::failed_counter, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_time_last(); });
CMD2_TRACKER ("t.scrape_counter", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_counter(); });
CMD2_TRACKER ("t.scrape_time_last", std::bind(&torrent::Tracker::scrape_time_last, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_counter", std::bind(&torrent::Tracker::scrape_counter, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_complete", std::bind(&torrent::Tracker::scrape_complete, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_incomplete", std::bind(&torrent::Tracker::scrape_incomplete, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_downloaded", std::bind(&torrent::Tracker::scrape_downloaded, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_complete", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_complete(); });
CMD2_TRACKER ("t.scrape_incomplete", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_incomplete(); });
CMD2_TRACKER ("t.scrape_downloaded", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_downloaded(); });
CMD2_ANY_VALUE ("trackers.enable", std::bind(&apply_enable_trackers, int64_t(1)));
CMD2_ANY_VALUE ("trackers.disable", std::bind(&apply_enable_trackers, int64_t(0)));
+36 -52
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>
@@ -42,14 +6,14 @@
#include <regex>
#include <rak/algorithm.h>
#include <rak/functional.h>
#include <rak/functional_fun.h>
#include <torrent/utils/log.h>
#include "core/manager.h"
#include "core/view_manager.h"
#include "display/canvas.h"
#include "ui/root.h"
#include "ui/download_list.h"
#include "display/color_map.h"
#include "rpc/parse.h"
#include "globals.h"
@@ -64,7 +28,7 @@ apply_view_filter_on(const torrent::Object::list_type& args) {
throw torrent::input_error("Too few arguments.");
const std::string& name = args.front().as_string();
if (name.empty())
throw torrent::input_error("First argument must be a string.");
@@ -135,7 +99,7 @@ apply_view_set(const torrent::Object::list_type& args) {
}
torrent::Object
apply_print(rpc::target_type target, const torrent::Object& rawArgs) {
apply_print([[maybe_unused]] rpc::target_type target, const torrent::Object& rawArgs) {
char buffer[1024];
rpc::print_object(buffer, buffer + 1024, &rawArgs, 0);
@@ -144,7 +108,7 @@ apply_print(rpc::target_type target, const torrent::Object& rawArgs) {
}
torrent::Object
apply_cat(rpc::target_type target, const torrent::Object& rawArgs) {
apply_cat([[maybe_unused]] rpc::target_type target, const torrent::Object& rawArgs) {
std::string result;
rpc::print_object_std(&result, &rawArgs, 0);
@@ -152,7 +116,7 @@ apply_cat(rpc::target_type target, const torrent::Object& rawArgs) {
}
torrent::Object
apply_value(rpc::target_type target, const torrent::Object::list_type& args) {
apply_value([[maybe_unused]] rpc::target_type target, const torrent::Object::list_type& args) {
if (args.size() < 1)
throw torrent::input_error("'value' takes at least a number argument!");
if (args.size() > 2)
@@ -220,7 +184,7 @@ apply_not(rpc::target_type target, const torrent::Object& rawArgs) {
}
torrent::Object
apply_false(rpc::target_type target, const torrent::Object& rawArgs) {
apply_false([[maybe_unused]] rpc::target_type target, [[maybe_unused]] const torrent::Object& rawArgs) {
return (int64_t)0;
}
@@ -235,10 +199,10 @@ apply_and(rpc::target_type target, const torrent::Object& rawArgs) {
return (int64_t)false;
} else if (itr->is_value()) {
if (!itr->as_value())
if (!itr->as_value())
return (int64_t)false;
} else {
} else {
// TODO: Switch to new versions that only accept the new command syntax.
if (!as_boolean(rpc::parse_command_single(target, itr->as_string())))
return (int64_t)false;
@@ -258,10 +222,10 @@ apply_or(rpc::target_type target, const torrent::Object& rawArgs) {
return (int64_t)true;
} else if (itr->is_value()) {
if (itr->as_value())
if (itr->as_value())
return (int64_t)true;
} else {
} else {
if (as_boolean(rpc::parse_command_single(target, itr->as_string())))
return (int64_t)true;
}
@@ -298,7 +262,7 @@ apply_cmp(rpc::target_type target, const torrent::Object::list_type& args) {
if (result1.type() != result2.type())
throw torrent::input_error("Type mismatch.");
switch (result1.type()) {
case torrent::Object::TYPE_VALUE: return result1.as_value() - result2.as_value();
case torrent::Object::TYPE_STRING: return result1.as_string().compare(result2.as_string());
@@ -427,7 +391,7 @@ apply_to_time(const torrent::Object& rawArgs, int flags) {
u = std::localtime(&t);
else
u = std::gmtime(&t);
if (u == NULL)
return torrent::Object();
@@ -470,7 +434,7 @@ apply_to_mb(const torrent::Object& rawArgs) {
torrent::Object
apply_to_xb(const torrent::Object& rawArgs) {
char buffer[48];
int64_t arg = rawArgs.as_value();
int64_t arg = rawArgs.as_value();
if (arg < (int64_t(1000) << 10))
snprintf(buffer, 48, "%5.1f KB", (double)arg / (int64_t(1) << 10));
@@ -486,7 +450,7 @@ apply_to_xb(const torrent::Object& rawArgs) {
torrent::Object
apply_to_throttle(const torrent::Object& rawArgs) {
int64_t arg = rawArgs.as_value();
int64_t arg = rawArgs.as_value();
if (arg < 0)
return "---";
else if (arg == 0)
@@ -584,7 +548,7 @@ cmd_view_size_not_visible(const torrent::Object::string_type& args) {
torrent::Object
cmd_view_persistent(const torrent::Object::string_type& args) {
core::View* view = *control->view_manager()->find_throw(args);
if (!view->get_filter().is_empty() || !view->event_added().is_empty() || !view->event_removed().is_empty())
throw torrent::input_error("Cannot set modified views as persitent.");
@@ -797,6 +761,13 @@ cmd_status_throttle_names(bool up, const torrent::Object::list_type& args) {
return torrent::Object();
}
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();
}
void
initialize_command_ui() {
CMD2_VAR_STRING("keys.layout", "qwerty");
@@ -844,6 +815,8 @@ initialize_command_ui() {
CMD2_VAR_VALUE ("ui.throttle.global.step.medium", 50);
CMD2_VAR_VALUE ("ui.throttle.global.step.large", 500);
CMD2_VAR_VALUE ("ui.focus.page_size", 0);
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));
@@ -894,4 +867,15 @@ initialize_command_ui() {
CMD2_ANY_LIST ("elapsed.less", std::bind(&apply_elapsed_less, std::placeholders::_2));
CMD2_ANY_LIST ("elapsed.greater", std::bind(&apply_elapsed_greater, std::placeholders::_2));
// 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]);
});
}
}
+12 -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 <unistd.h>
@@ -49,10 +13,15 @@
#include "display/canvas.h"
#include "display/window.h"
#include "display/window_http_queue.h"
#include "display/window_input.h"
#include "display/window_statusbar.h"
#include "display/window_title.h"
#include "display/manager.h"
#include "input/manager.h"
#include "input/input_event.h"
#include "rpc/command_scheduler.h"
#include "rpc/lua.h"
#include "rpc/parse_commands.h"
#include "rpc/scgi.h"
#include "rpc/object_storage.h"
@@ -68,6 +37,7 @@ Control::Control() :
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_tick(0),
@@ -82,7 +52,7 @@ Control::Control() :
m_taskShutdown.slot() = std::bind(&Control::handle_shutdown, this);
m_commandScheduler->set_slot_error_message(rak::mem_fn(m_core, &core::Manager::push_log_std));
m_commandScheduler->set_slot_error_message([this](const std::string& msg) { m_core->push_log_std(msg); });
}
Control::~Control() {
@@ -99,14 +69,15 @@ Control::~Control() {
delete m_directory_events;
delete m_commandScheduler;
delete m_objectStorage;
delete m_lua_engine;
}
void
Control::initialize() {
display::Canvas::initialize();
display::Window::slot_schedule(rak::make_mem_fun(m_display, &display::Manager::schedule));
display::Window::slot_unschedule(rak::make_mem_fun(m_display, &display::Manager::unschedule));
display::Window::slot_adjust(rak::make_mem_fun(m_display, &display::Manager::adjust_layout));
display::Window::slot_schedule([this](display::Window* w, rak::timer 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);
@@ -126,7 +97,7 @@ Control::initialize() {
void
Control::cleanup() {
// delete m_scgi; m_scgi = NULL;
rpc::xmlrpc.cleanup();
rpc::rpc.cleanup();
priority_queue_erase(&taskScheduler, &m_taskShutdown);
+8 -4
View File
@@ -37,6 +37,7 @@
#ifndef RTORRENT_CONTROL_H
#define RTORRENT_CONTROL_H
#include <atomic>
#include <cinttypes>
#include <sys/types.h>
#include <rak/timer.h>
@@ -66,6 +67,7 @@ namespace rpc {
class CommandScheduler;
class XmlRpc;
class object_storage;
class LuaEngine;
}
namespace torrent {
@@ -87,8 +89,8 @@ public:
void handle_shutdown();
void receive_normal_shutdown() { m_shutdownReceived = true; __sync_synchronize(); }
void receive_quick_shutdown() { m_shutdownReceived = true; m_shutdownQuick = true; __sync_synchronize(); }
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; }
@@ -101,6 +103,7 @@ public:
rpc::CommandScheduler* command_scheduler() { return m_commandScheduler; }
rpc::object_storage* object_storage() { return m_objectStorage; }
rpc::LuaEngine* lua_engine() { return m_lua_engine; }
torrent::directory_events* directory_events() { return m_directory_events; }
@@ -125,6 +128,7 @@ private:
rpc::CommandScheduler* m_commandScheduler;
rpc::object_storage* m_objectStorage;
rpc::LuaEngine* m_lua_engine;
torrent::directory_events* m_directory_events;
uint64_t m_tick;
@@ -134,8 +138,8 @@ private:
rak::priority_item m_taskShutdown;
bool m_shutdownReceived lt_cacheline_aligned;
bool m_shutdownQuick lt_cacheline_aligned;
std::atomic<bool> m_shutdownReceived;
std::atomic<bool> m_shutdownQuick;
};
#endif
+4 -2
View File
@@ -67,6 +67,9 @@ CurlGet::start() {
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)
@@ -83,8 +86,7 @@ CurlGet::start() {
// 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_erase(&taskScheduler, &m_taskTimeout);
priority_queue_insert(&taskScheduler, &m_taskTimeout, cachedTime + rak::timer::from_seconds(m_timeout + 5));
priority_queue_update(&taskScheduler, &m_taskTimeout, cachedTime + rak::timer::from_seconds(m_timeout + 5));
}
curl_easy_setopt(m_handle, CURLOPT_FORBID_REUSE, (long)1);
+9 -41
View File
@@ -1,47 +1,13 @@
// 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
#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_base.h>
#include <torrent/utils/thread.h>
#include "control.h"
@@ -51,10 +17,13 @@
namespace core {
int
CurlSocket::receive_socket(void* easy_handle, curl_socket_t fd, int what, void* userp, void* socketp) {
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.
@@ -75,7 +44,7 @@ CurlSocket::receive_socket(void* easy_handle, curl_socket_t fd, int what, void*
// 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);
@@ -91,8 +60,7 @@ CurlSocket::receive_socket(void* easy_handle, curl_socket_t fd, int what, void*
}
CurlSocket::~CurlSocket() {
if (m_fileDesc != -1)
throw torrent::internal_error("CurlSocket::~CurlSocket() m_fileDesc != -1.");
assert(m_fileDesc == -1 && "CurlSocket::~CurlSocket() m_fileDesc != -1.");
}
void
+39 -70
View File
@@ -1,61 +1,18 @@
// 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>
#include <curl/multi.h>
#include <torrent/exceptions.h>
#include "rak/functional.h"
#include "curl_get.h"
#include "curl_socket.h"
#include "curl_stack.h"
namespace core {
CurlStack::CurlStack() :
m_handle((void*)curl_multi_init()),
m_active(0),
m_maxActive(32),
m_ssl_verify_host(true),
m_ssl_verify_peer(true),
m_dns_timeout(60) {
m_taskTimeout.slot() = std::bind(&CurlStack::receive_timeout, this);
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);
@@ -66,11 +23,21 @@ CurlStack::CurlStack() :
}
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_taskTimeout);
priority_queue_erase(&taskScheduler, &m_task_timeout);
}
CurlGet*
@@ -80,6 +47,9 @@ CurlStack::new_object() {
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;
@@ -115,7 +85,7 @@ CurlStack::receive_action(CurlSocket* socket, int events) {
; // Do nothing.
if (empty())
priority_queue_erase(&taskScheduler, &m_taskTimeout);
priority_queue_erase(&taskScheduler, &m_task_timeout);
}
} while (code == CURLM_CALL_MULTI_PERFORM);
@@ -133,11 +103,11 @@ CurlStack::process_done_handle() {
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(), rak::equal(msg->easy_handle, std::mem_fun(&CurlGet::handle)));
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();
@@ -155,7 +125,7 @@ CurlStack::process_done_handle() {
void
CurlStack::transfer_done(void* handle, const char* msg) {
iterator itr = std::find_if(begin(), end(), rak::equal(handle, std::mem_fun(&CurlGet::handle)));
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.");
@@ -171,30 +141,30 @@ 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_taskTimeout.is_queued()) {
if (!empty() && !m_task_timeout.is_queued()) {
long timeout;
curl_multi_timeout((CURLM*)m_handle, &timeout);
priority_queue_insert(&taskScheduler, &m_taskTimeout,
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_userAgent.empty())
curl_easy_setopt(get->handle(), CURLOPT_USERAGENT, m_userAgent.c_str());
if (!m_user_agent.empty())
curl_easy_setopt(get->handle(), CURLOPT_USERAGENT, m_user_agent.c_str());
if (!m_httpProxy.empty())
curl_easy_setopt(get->handle(), CURLOPT_PROXY, m_httpProxy.c_str());
if (!m_http_proxy.empty())
curl_easy_setopt(get->handle(), CURLOPT_PROXY, m_http_proxy.c_str());
if (!m_bindAddress.empty())
curl_easy_setopt(get->handle(), CURLOPT_INTERFACE, m_bindAddress.c_str());
if (!m_bind_address.empty())
curl_easy_setopt(get->handle(), CURLOPT_INTERFACE, m_bind_address.c_str());
if (!m_httpCaPath.empty())
curl_easy_setopt(get->handle(), CURLOPT_CAPATH, m_httpCaPath.c_str());
if (!m_http_ca_path.empty())
curl_easy_setopt(get->handle(), CURLOPT_CAPATH, m_http_ca_path.c_str());
if (!m_httpCaCert.empty())
curl_easy_setopt(get->handle(), CURLOPT_CAINFO, m_httpCaCert.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));
@@ -202,12 +172,12 @@ CurlStack::add_get(CurlGet* get) {
base_type::push_back(get);
if (m_active >= m_maxActive)
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.");
@@ -234,8 +204,8 @@ CurlStack::remove_get(CurlGet* get) {
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_maxActive &&
(itr = std::find_if(begin(), end(), std::not1(std::mem_fun(&CurlGet::is_active)))) != end()) {
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)
@@ -262,8 +232,7 @@ int
CurlStack::set_timeout(void* handle, long timeout_ms, void* userp) {
CurlStack* stack = (CurlStack*)userp;
priority_queue_erase(&taskScheduler, &stack->m_taskTimeout);
priority_queue_insert(&taskScheduler, &stack->m_taskTimeout, cachedTime + rak::timer::from_milliseconds(timeout_ms));
priority_queue_update(&taskScheduler, &stack->m_task_timeout, cachedTime + rak::timer::from_milliseconds(timeout_ms));
return 0;
}
+28 -59
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_CURL_STACK_H
#define RTORRENT_CORE_CURL_STACK_H
@@ -81,24 +45,27 @@ class CurlStack : std::deque<CurlGet*> {
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_maxActive; }
void set_max_active(unsigned int a) { m_maxActive = a; }
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_userAgent; }
const std::string& http_proxy() const { return m_httpProxy; }
const std::string& bind_address() const { return m_bindAddress; }
const std::string& http_capath() const { return m_httpCaPath; }
const std::string& http_cacert() const { return m_httpCaCert; }
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_userAgent = s; }
void set_http_proxy(const std::string& s) { m_httpProxy = s; }
void set_bind_address(const std::string& s) { m_bindAddress = s; }
void set_http_capath(const std::string& s) { m_httpCaPath = s; }
void set_http_cacert(const std::string& s) { m_httpCaCert = s; }
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; }
@@ -131,20 +98,22 @@ class CurlStack : std::deque<CurlGet*> {
void* m_handle;
unsigned int m_active;
unsigned int m_maxActive;
bool m_running{true};
rak::priority_item m_taskTimeout;
unsigned int m_active{0};
unsigned int m_max_active{32};
std::string m_userAgent;
std::string m_httpProxy;
std::string m_bindAddress;
std::string m_httpCaPath;
std::string m_httpCaCert;
rak::priority_item m_task_timeout;
bool m_ssl_verify_host;
bool m_ssl_verify_peer;
long m_dns_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};
};
}
+23 -59
View File
@@ -1,47 +1,11 @@
// 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 <fstream>
#include <sstream>
#include <torrent/object.h>
#include <torrent/dht_manager.h>
#include <torrent/object_stream.h>
#include <torrent/rate.h>
#include <torrent/tracker/dht_controller.h>
#include <torrent/utils/log.h>
#include "rpc/parse_commands.h"
@@ -94,7 +58,7 @@ DhtManager::load_dht_cache() {
LT_LOG_THIS("could not open cache file (path:%s)", cache_filename.c_str());
}
torrent::dht_manager()->initialize(cache);
torrent::dht_controller()->initialize(cache);
if (m_start == dht_on)
start_dht();
@@ -104,31 +68,31 @@ void
DhtManager::start_dht() {
priority_queue_erase(&taskScheduler, &m_stopTimeout);
if (!torrent::dht_manager()->is_valid()) {
if (!torrent::dht_controller()->is_valid()) {
LT_LOG_THIS("server start skipped, manager is uninitialized", 0);
return;
}
if (torrent::dht_manager()->is_active()) {
if (torrent::dht_controller()->is_active()) {
LT_LOG_THIS("server start skipped, already active", 0);
return;
}
torrent::ThrottlePair throttles = control->core()->get_throttle(m_throttleName);
torrent::dht_manager()->set_upload_throttle(throttles.first);
torrent::dht_manager()->set_download_throttle(throttles.second);
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_manager()->start(port)) {
if (!torrent::dht_controller()->start(port)) {
m_start = dht_off;
return;
}
torrent::dht_manager()->reset_statistics();
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());
@@ -146,17 +110,17 @@ DhtManager::stop_dht() {
priority_queue_erase(&taskScheduler, &m_updateTimeout);
priority_queue_erase(&taskScheduler, &m_stopTimeout);
if (torrent::dht_manager()->is_active()) {
if (torrent::dht_controller()->is_active()) {
LT_LOG_THIS("stopping server", 0);
log_statistics(true);
torrent::dht_manager()->stop();
torrent::dht_controller()->stop();
}
}
void
DhtManager::save_dht_cache() {
if (!control->core()->download_store()->is_enabled() || !torrent::dht_manager()->is_valid())
if (!control->core()->download_store()->is_enabled() || !torrent::dht_controller()->is_valid())
return;
std::string filename = control->core()->download_store()->path() + "rtorrent.dht_cache";
@@ -167,7 +131,7 @@ DhtManager::save_dht_cache() {
return;
torrent::Object cache = torrent::Object::create_map();
cache_file << *torrent::dht_manager()->store_cache(&cache);
cache_file << *torrent::dht_controller()->store_cache(&cache);
if (!cache_file.good())
return;
@@ -198,7 +162,7 @@ DhtManager::set_mode(const std::string& arg) {
void
DhtManager::update() {
if (!torrent::dht_manager()->is_active())
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()) {
@@ -207,7 +171,7 @@ DhtManager::update() {
for (itr = control->core()->download_list()->begin(), end = control->core()->download_list()->end(); itr != end; ++itr)
if ((*itr)->download()->info()->is_active() && !(*itr)->download()->info()->is_private())
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());
@@ -223,17 +187,17 @@ DhtManager::update() {
bool
DhtManager::log_statistics(bool force) {
torrent::DhtManager::statistics_type stats = torrent::dht_manager()->get_statistics();
auto stats = torrent::dht_controller()->get_statistics();
// Check for firewall problems.
if (stats.cycle > 2 && stats.queries_sent - m_dhtPrevQueriesSent > 100 && stats.queries_received == m_dhtPrevQueriesReceived) {
// We should have had clients ping us at least but have received
// nothing, that means the UDP port is probably unreachable.
if (torrent::dht_manager()->can_receive_queries())
if (torrent::dht_controller()->is_receiving_requests())
LT_LOG_THIS("listening port appears to be unreachable, no queries received", 0);
torrent::dht_manager()->set_can_receive(false);
torrent::dht_controller()->set_receive_requests(false);
}
if (stats.queries_sent - m_dhtPrevQueriesSent > stats.num_nodes * 2 + 20 && stats.replies_received == m_dhtPrevRepliesReceived) {
@@ -248,7 +212,7 @@ DhtManager::log_statistics(bool force) {
m_warned = false;
if (stats.queries_received > m_dhtPrevQueriesReceived)
torrent::dht_manager()->set_can_receive(true);
torrent::dht_controller()->set_receive_requests(true);
// Nothing to log while bootstrapping, but check again every minute.
if (stats.cycle <= 1) {
@@ -269,7 +233,7 @@ DhtManager::log_statistics(bool force) {
// afterwards (i.e. every 2 hours), or when forced.
if ((force && stats.cycle != m_dhtPrevCycle) || stats.cycle == 3 || stats.cycle > m_dhtPrevCycle + 7) {
char buffer[256];
snprintf(buffer, sizeof(buffer),
snprintf(buffer, sizeof(buffer),
"DHT statistics: %d queries in, %d queries out, %d replies received, %lld bytes read, %lld bytes sent, "
"%d known nodes in %d buckets, %d peers (highest: %d) tracked in %d torrents.",
stats.queries_received - m_dhtPrevQueriesReceived,
@@ -301,11 +265,11 @@ DhtManager::dht_statistics() {
torrent::Object dhtStats = torrent::Object::create_map();
dhtStats.insert_key("dht", dht_settings[m_start]);
dhtStats.insert_key("active", torrent::dht_manager()->is_active());
dhtStats.insert_key("active", torrent::dht_controller()->is_active());
dhtStats.insert_key("throttle", m_throttleName);
if (torrent::dht_manager()->is_active()) {
torrent::DhtManager::statistics_type stats = torrent::dht_manager()->get_statistics();
if (torrent::dht_controller()->is_active()) {
auto stats = torrent::dht_controller()->get_statistics();
dhtStats.insert_key("cycle", stats.cycle);
dhtStats.insert_key("queries_received", stats.queries_received);
@@ -327,7 +291,7 @@ DhtManager::dht_statistics() {
void
DhtManager::set_throttle_name(const std::string& throttleName) {
if (torrent::dht_manager()->is_active())
if (torrent::dht_controller()->is_active())
throw torrent::input_error("Cannot set DHT throttle while active.");
m_throttleName = throttleName;
-36
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_DHT_MANAGER_H
#define RTORRENT_CORE_DHT_MANAGER_H
+4 -41
View File
@@ -1,50 +1,13 @@
// 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 <list>
#include <rak/file_stat.h>
#include <rak/functional.h>
#include <rak/path.h>
#include <torrent/exceptions.h>
#include <torrent/rate.h>
#include <torrent/torrent.h>
#include <torrent/tracker.h>
#include <torrent/tracker_list.h>
#include <torrent/tracker/tracker.h>
#include <torrent/data/file_list.h>
#include "rpc/parse_commands.h"
@@ -76,11 +39,11 @@ 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::TRACKER_UDP) {
if (itr->type() == torrent::TRACKER_UDP) {
if (state)
(*itr)->enable();
itr->enable();
else
(*itr)->disable();
itr->disable();
}
}
+7 -49
View File
@@ -1,42 +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_CORE_DOWNLOAD_H
#define RTORRENT_CORE_DOWNLOAD_H
#include <torrent/common.h>
#include <torrent/download.h>
#include <torrent/download_info.h>
#include <torrent/hash_string.h>
@@ -46,11 +11,6 @@
#include "globals.h"
namespace torrent {
class PeerList;
class TrackerList;
}
namespace core {
class Download {
@@ -59,7 +19,6 @@ public:
typedef torrent::FileList file_list_type;
typedef torrent::PeerList peer_list_type;
typedef torrent::TrackerList tracker_list_type;
typedef torrent::TrackerController tracker_controller_type;
typedef torrent::ConnectionList connection_list_type;
typedef download_type::ConnectionType connection_type;
@@ -71,10 +30,10 @@ public:
Download(download_type d);
~Download();
const torrent::DownloadInfo* info() const { return m_download.info(); }
const torrent::download_data* data() const { return m_download.data(); }
auto info() const { return m_download.info(); }
auto data() const { return m_download.data(); }
torrent::DownloadMain* main() { return m_download.main(); }
auto main() { return m_download.main(); }
bool is_open() const { return m_download.info()->is_open(); }
bool is_active() const { return m_download.info()->is_active(); }
@@ -102,13 +61,12 @@ 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(); }
tracker_controller_type* tracker_controller() { return m_download.tracker_controller(); }
connection_list_type* connection_list() { return m_download.connection_list(); }
uint32_t connection_list_size() const;
auto connection_list() { return m_download.connection_list(); }
uint32_t connection_list_size() const;
const std::string& message() const { return m_message; }
void set_message(const std::string& msg) { m_message = msg; }
+34 -63
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 <cstdlib>
@@ -73,21 +37,20 @@ is_network_uri(const std::string& uri) {
std::strncmp(uri.c_str(), "ftp://", 6) == 0;
}
static bool
download_factory_add_stream(torrent::Object* root, const char* key, const char* filename) {
static std::unique_ptr<torrent::Object>
download_factory_load_stream(const char* filename) {
std::fstream stream(filename, std::ios::in | std::ios::binary);
if (!stream.is_open())
return false;
torrent::Object obj;
stream >> obj;
if (!stream.is_open())
return std::unique_ptr<torrent::Object>();
auto obj = std::make_unique<torrent::Object>();
stream >> *obj;
if (!stream.good())
return false;
return std::unique_ptr<torrent::Object>();
root->insert_key_move(key, obj);
return true;
return obj;
}
bool
@@ -209,9 +172,19 @@ DownloadFactory::receive_commit() {
void
DownloadFactory::receive_success() {
auto rtorrent_object = download_factory_load_stream((rak::path_expand(m_uri) + ".rtorrent").c_str());
auto libtorrent_resume_object = download_factory_load_stream((rak::path_expand(m_uri) + ".libtorrent_resume").c_str());
uint32_t tracker_key;
if (rtorrent_object && rtorrent_object->has_key_value("key"))
tracker_key = rtorrent_object->get_key_value("key");
else
tracker_key = random() % (std::numeric_limits<uint32_t>::max() - 1) + 1;
Download* download = m_stream != NULL ?
m_manager->download_list()->create(m_stream, m_printLog) :
m_manager->download_list()->create(m_object, m_printLog);
m_manager->download_list()->create(m_stream, tracker_key, m_printLog) :
m_manager->download_list()->create(m_object, tracker_key, m_printLog);
m_object = NULL;
@@ -228,7 +201,7 @@ DownloadFactory::receive_success() {
torrent::Object& meta = root->insert_key("rtorrent_meta_download", torrent::Object::create_map());
meta.insert_key("start", m_start);
meta.insert_key("print_log", m_printLog);
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)
@@ -236,9 +209,12 @@ DownloadFactory::receive_success() {
}
if (m_session) {
download_factory_add_stream(root, "rtorrent", (rak::path_expand(m_uri) + ".rtorrent").c_str());
download_factory_add_stream(root, "libtorrent_resume", (rak::path_expand(m_uri) + ".libtorrent_resume").c_str());
if (rtorrent_object)
root->insert_key_move("rtorrent", *rtorrent_object);
if (libtorrent_resume_object)
root->insert_key_move("libtorrent_resume", *libtorrent_resume_object);
} else {
// We only allow session torrents to keep their
// 'rtorrent/libtorrent' sections. The "fast_resume" section
@@ -249,6 +225,8 @@ 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());
initialize_rtorrent(download, rtorrent);
if (!rtorrent->has_key_string("custom1")) rtorrent->insert_key("custom1", std::string());
@@ -321,8 +299,9 @@ 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(),
rak::bind2nd(std::ptr_fun(&rpc::parse_command_multiple_std), rpc::make_target(download)));
std::for_each(m_commands.begin(), m_commands.end(), [&download](const std::string& cmd) {
rpc::parse_command_multiple_std(cmd, 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.");
@@ -338,7 +317,7 @@ DownloadFactory::receive_success() {
if (m_printLog)
m_manager->push_log_std(msg);
if (m_manager->download_list()->find(infohash) != m_manager->download_list()->end()) {
// Should stop it, mark it bad. Perhaps even delete it?
download->set_hash_failed(true);
@@ -413,14 +392,6 @@ DownloadFactory::initialize_rtorrent(Download* download, torrent::Object* rtorre
else
rpc::call_command("d.priority.set", (int64_t)2, rpc::make_target(download));
if (rtorrent->has_key_value("key")) {
download->tracker_list()->set_key(rtorrent->get_key_value("key"));
} else {
download->tracker_list()->set_key(random() % (std::numeric_limits<uint32_t>::max() - 1) + 1);
rtorrent->insert_key("key", download->tracker_list()->key());
}
if (rtorrent->has_key_value("total_uploaded"))
download->info()->mutable_up_rate()->set_total(rtorrent->get_key_value("total_uploaded"));
+16 -53
View File
@@ -1,45 +1,8 @@
// 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>
#include <fstream>
#include <iostream>
#include <rak/functional.h>
#include <rak/string_manip.h>
#include <torrent/data/file.h>
#include <torrent/utils/resume.h>
@@ -71,7 +34,7 @@
namespace core {
inline void
DownloadList::check_contains(Download* d) {
DownloadList::check_contains([[maybe_unused]] Download* d) {
#ifdef USE_EXTRA_DEBUG
if (std::find(begin(), end(), d) == end())
throw torrent::internal_error("DownloadList::check_contains(...) failed.");
@@ -80,15 +43,15 @@ DownloadList::check_contains(Download* d) {
void
DownloadList::clear() {
std::for_each(begin(), end(), std::bind1st(std::mem_fun(&DownloadList::close), this));
std::for_each(begin(), end(), rak::call_delete<Download>());
std::for_each(begin(), end(), [&](Download* d) { close(d); });
std::for_each(begin(), end(), [](Download* d) { delete d; });
base_type::clear();
}
void
DownloadList::session_save() {
unsigned int c = std::count_if(begin(), end(), std::bind1st(std::mem_fun(&DownloadStore::save_resume), control->core()->download_store()));
unsigned int c = std::count_if(begin(), end(), [&](Download* d) { return control->core()->download_store()->save_resume(d); });
if (c != size())
lt_log_print(torrent::LOG_ERROR, "Failed to save session torrents.");
@@ -99,7 +62,7 @@ DownloadList::session_save() {
DownloadList::iterator
DownloadList::find(const torrent::HashString& hash) {
return std::find_if(begin(), end(), rak::equal(hash, rak::on(std::mem_fun(&Download::info), std::mem_fun(&torrent::DownloadInfo::hash))));
return std::find_if(begin(), end(), [hash](Download* d) { return hash == d->info()->hash(); });
}
DownloadList::iterator
@@ -109,7 +72,7 @@ DownloadList::find_hex(const char* hash) {
for (torrent::HashString::iterator itr = key.begin(), last = key.end(); itr != last; itr++, hash += 2)
*itr = (rak::hexchar_to_value(*hash) << 4) + rak::hexchar_to_value(*(hash + 1));
return std::find_if(begin(), end(), rak::equal(key, rak::on(std::mem_fun(&Download::info), std::mem_fun(&torrent::DownloadInfo::hash))));
return std::find_if(begin(), end(), [key](Download* d) { return key == d->info()->hash(); });
}
Download*
@@ -120,11 +83,11 @@ DownloadList::find_hex_ptr(const char* hash) {
}
Download*
DownloadList::create(torrent::Object* obj, bool printLog) {
DownloadList::create(torrent::Object* obj, uint32_t tracker_key, bool printLog) {
torrent::Download download;
try {
download = torrent::download_add(obj);
download = torrent::download_add(obj, tracker_key);
} catch (torrent::local_error& e) {
delete obj;
@@ -141,13 +104,13 @@ DownloadList::create(torrent::Object* obj, bool printLog) {
}
Download*
DownloadList::create(std::istream* str, bool printLog) {
DownloadList::create(std::istream* str, uint32_t tracker_key, bool printLog) {
torrent::Object* object = new torrent::Object;
torrent::Download download;
try {
*str >> *object;
// Don't throw input_error from here as gcc-3.3.5 produces bad
// code.
if (str->fail()) {
@@ -159,7 +122,7 @@ DownloadList::create(std::istream* str, bool printLog) {
return NULL;
}
download = torrent::download_add(object);
download = torrent::download_add(object, tracker_key);
} catch (torrent::local_error& e) {
delete object;
@@ -187,8 +150,8 @@ 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(), std::bind2nd(std::mem_fun(&View::insert), download));
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::filter_download), download));
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); });
DL_TRIGGER_EVENT(*itr, "event.download.inserted");
@@ -221,7 +184,7 @@ 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(), std::bind2nd(std::mem_fun(&View::erase), *itr));
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), [itr](View* v) { v->erase(*itr); });
torrent::download_remove(*(*itr)->download());
delete *itr;
@@ -550,8 +513,8 @@ DownloadList::hash_done(Download* download) {
if (download->is_done()) {
confirm_finished(download);
} else {
download->set_message("Hash check on download completion found bad chunks, consider using \"safe_sync\".");
lt_log_print(torrent::LOG_TORRENT_ERROR, "Hash check on download completion found bad chunks, consider using \"safe_sync\".");
download->set_message("Hash check on download completion found bad chunks.");
lt_log_print(torrent::LOG_TORRENT_ERROR, "Hash check on download completion found bad chunks.");
DL_TRIGGER_EVENT(download, "event.download.hash_final_failed");
}
+3 -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_CORE_DOWNLOAD_LIST_H
#define RTORRENT_CORE_DOWNLOAD_LIST_H
@@ -43,6 +7,7 @@
namespace torrent {
class HashString;
class Object;
}
namespace core {
@@ -86,8 +51,8 @@ public:
Download* find_hex_ptr(const char* hash);
// Might move this to DownloadFactory.
Download* create(std::istream* str, bool printLog);
Download* create(torrent::Object* obj, bool printLog);
Download* create(std::istream* str, uint32_t tracker_key, bool printLog);
Download* create(torrent::Object* obj, uint32_t tracker_key, bool printLog);
iterator insert(Download* d);
+11 -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
// DownloadStore handles the saving and listing of session torrents.
#include "config.h"
@@ -56,6 +20,7 @@
#include "download.h"
#include "download_store.h"
#include "rpc/parse_commands.h"
namespace core {
@@ -129,8 +94,14 @@ DownloadStore::write_bencode(const std::string& filename, const torrent::Object&
if (fd < 0)
goto download_store_save_error;
fdatasync(fd);
::close(fd);
if (rpc::call_command_value("system.files.session.fdatasync")) {
#ifdef __APPLE__
fsync(fd);
#else
fdatasync(fd);
#endif
::close(fd);
}
return true;
@@ -173,7 +144,7 @@ DownloadStore::save(Download* d, int flags) {
::rename((base_filename + ".libtorrent_resume.new").c_str(), (base_filename + ".libtorrent_resume").c_str());
::rename((base_filename + ".rtorrent.new").c_str(), (base_filename + ".rtorrent").c_str());
if (!(flags & flag_skip_static) &&
write_bencode(base_filename + ".new", *d->bencode(), torrent::Object::flag_session_data))
::rename((base_filename + ".new").c_str(), base_filename.c_str());
@@ -207,7 +178,7 @@ DownloadStore::get_formated_entries() {
if (!d.update(utils::Directory::update_hide_dot))
throw torrent::storage_error("core::DownloadStore::update() could not open directory \"" + m_path + "\"");
d.erase(std::remove_if(d.begin(), d.end(), std::ptr_fun(&not_correct_format)), d.end());
d.erase(std::remove_if(d.begin(), d.end(), [&](const utils::directory_entry& entry) { return not_correct_format(entry); }), d.end());
return d;
}
-36
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_DOWNLOAD_STORE_H
#define RTORRENT_CORE_DOWNLOAD_STORE_H
+1 -2
View File
@@ -40,7 +40,6 @@
#include <sstream>
#include <torrent/http.h>
#include "rak/functional.h"
#include "http_queue.h"
#include "curl_get.h"
@@ -48,7 +47,7 @@ namespace core {
HttpQueue::iterator
HttpQueue::insert(const std::string& url, std::iostream* s) {
std::auto_ptr<CurlGet> h(m_slot_factory());
std::unique_ptr<CurlGet> h(m_slot_factory());
h->set_url(url);
h->set_stream(s);
+41 -51
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 <cstdio>
@@ -59,6 +23,7 @@
#include "rpc/parse_commands.h"
#include "utils/directory.h"
#include "utils/base64.h"
#include "utils/file_status_cache.h"
#include "globals.h"
@@ -186,6 +151,8 @@ Manager::initialize_second() {
void
Manager::cleanup() {
m_httpStack->shutdown();
// Need to disconnect log signals? Not really since we won't receive
// any more.
@@ -198,15 +165,14 @@ Manager::cleanup() {
delete m_httpStack;
CurlStack::global_cleanup();
}
void
Manager::shutdown(bool force) {
if (!force)
std::for_each(m_downloadList->begin(), m_downloadList->end(), std::bind1st(std::mem_fun(&DownloadList::pause_default), m_downloadList));
std::for_each(m_downloadList->begin(), m_downloadList->end(), [this](Download* d) { m_downloadList->pause_default(d); });
else
std::for_each(m_downloadList->begin(), m_downloadList->end(), std::bind1st(std::mem_fun(&DownloadList::close_quick), m_downloadList));
std::for_each(m_downloadList->begin(), m_downloadList->end(), [this](Download* d) { m_downloadList->close_quick(d); });
}
void
@@ -222,7 +188,7 @@ Manager::listen_open() {
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.");
// } else if (portRange.is_list()) {
} else {
@@ -329,12 +295,12 @@ Manager::set_proxy_address(const std::string& addr) {
if ((err = rak::address_info::get_address_info(buf, 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());
rak::address_info::free_address_info(ai);
} catch (torrent::input_error& e) {
@@ -348,6 +314,21 @@ Manager::receive_http_failed(std::string msg) {
push_log_std("Http download error: \"" + msg + "\"");
}
bool
is_data_uri(const std::string& uri) {
return std::strncmp(uri.c_str(), "data:", 5) == 0;
}
std::string
decode_data_uri(const std::string& uri) {
const auto start = uri.find("base64,", 5) + 7;
if (start == std::string::npos)
throw torrent::input_error("Invalid data uri: not base64 encoded.");
if (start >= uri.size())
throw torrent::input_error("Empty base64.");
return utils::decode_base64(uri.substr(start));
}
void
Manager::try_create_download(const std::string& uri, int flags, const command_list_type& commands) {
// If the path was attempted loaded before, skip it.
@@ -355,6 +336,7 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li
!(flags & create_raw_data) &&
!is_network_uri(uri) &&
!is_magnet_uri(uri) &&
!is_data_uri(uri) &&
!file_status_cache()->insert(uri, 0))
return;
@@ -366,12 +348,18 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li
f->set_start(flags & create_start);
f->set_print_log(!(flags & create_quiet));
f->slot_finished(std::bind(&rak::call_delete_func<core::DownloadFactory>, f));
f->slot_finished([f]() { delete f; });
if (flags & create_raw_data)
if (is_data_uri(uri)) {
// Allow the use of data URIs, primarily for JSON-RPC which
// doesn't have a defined mechanism for binary data
f->load_raw_data(decode_data_uri(uri));
f->variables()["tied_to_file"] = (int64_t)false;
} else if (flags & create_raw_data) {
f->load_raw_data(uri);
else
} else {
f->load(uri);
}
f->commit();
}
@@ -390,7 +378,7 @@ Manager::try_create_download_from_meta_download(torrent::Object* bencode, const
f->set_start(meta.get_key_value("start"));
f->set_print_log(meta.get_key_value("print_log"));
f->slot_finished(std::bind(&rak::call_delete_func<core::DownloadFactory>, f));
f->slot_finished([f]() { delete f; });
// Bit of a waste to create the bencode repesentation here
// only to have the DownloadFactory decode it.
@@ -414,7 +402,7 @@ path_expand(std::vector<std::string>* paths, const std::string& pattern) {
rak::split_iterator_t<std::string> first = rak::split_iterator(pattern, '/');
rak::split_iterator_t<std::string> last = rak::split_iterator(pattern);
if (first == last)
return;
@@ -443,16 +431,18 @@ path_expand(std::vector<std::string>* paths, const std::string& pattern) {
// 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(), rak::on(rak::mem_ref(&utils::directory_entry::s_name), std::not1(r))), itr->end());
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), rak::bind1st(std::ptr_fun(&path_expand_transform), itr->path() + (itr->path() == "/" ? "" : "/")));
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);
});
}
currentCache.clear();
currentCache.swap(nextCache);
}
std::transform(currentCache.begin(), currentCache.end(), std::back_inserter(*paths), std::mem_fun_ref(&utils::Directory::path));
std::transform(currentCache.begin(), currentCache.end(), std::back_inserter(*paths), std::mem_fn(&utils::Directory::path));
}
bool
@@ -486,7 +476,7 @@ Manager::try_create_download_expand(const std::string& uri, int flags, command_l
void
Manager::receive_hashing_changed() {
bool foundHashing = std::find_if(m_hashingView->begin_visible(), m_hashingView->end_visible(),
std::mem_fun(&Download::is_hash_checking)) != m_hashingView->end_visible();
std::mem_fn(&Download::is_hash_checking)) != m_hashingView->end_visible();
// Try quick hashing all those with hashing == initial, set them to
// something else when failed.
+4 -2
View File
@@ -49,10 +49,12 @@ namespace core {
template<typename Key, typename T, typename Compare = std::less<Key>,
typename Alloc = std::allocator<std::pair<const Key, T> > >
class RangeMap : private std::map<Key, std::pair<Key, T>, Compare,
typename Alloc::template rebind<std::pair<const Key, std::pair<Key, T> > >::other> {
typename std::allocator_traits<Alloc>::template rebind_alloc<std::pair<const Key, std::pair<Key, T>>>> {
typedef std::map<Key, std::pair<Key, T>, Compare,
typename Alloc::template rebind<std::pair<const Key, std::pair<Key, T> > >::other> base_type;
typename std::allocator_traits<Alloc>::template rebind_alloc<std::pair<const Key, std::pair<Key, T>>>> base_type;
//std::allocator_traits<Alloc>::template rebind_alloc<std::pair<const Key, std::pair<Key, T>>>
public:
RangeMap() {}
+63 -73
View File
@@ -1,63 +1,26 @@
// 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>
#include <functional>
#include <rak/functional.h>
#include <rak/functional_fun.h>
#include <torrent/download.h>
#include <torrent/exceptions.h>
#include "rpc/parse_commands.h"
#include "rpc/object_storage.h"
#include "control.h"
#include "download.h"
#include "download_list.h"
#include "manager.h"
#include "rpc/object_storage.h"
#include "rpc/parse_commands.h"
#include "view.h"
namespace core {
// Also add focus thingie here?
struct view_downloads_compare : std::binary_function<Download*, Download*, bool> {
view_downloads_compare(const torrent::Object& cmd) : m_command(cmd) {}
struct view_downloads_compare : std::function<bool (Download*, Download*)> {
view_downloads_compare(const torrent::Object& cmd) :
m_command(cmd) {}
bool operator () (Download* d1, Download* d2) const {
bool operator()(Download* d1, Download* d2) const {
try {
if (m_command.is_empty())
return false;
@@ -75,8 +38,7 @@ struct view_downloads_compare : std::binary_function<Download*, Download*, bool>
// return rpc::commands.call_command(tmp_command.as_dict_key().c_str(), tmp_command.as_dict_obj(),
// rpc::make_target_pair(d1, d2)).as_value();
return rpc::commands.call_command(m_command.as_dict_key().c_str(), m_command.as_dict_obj(),
rpc::make_target_pair(d1, d2)).as_value();
return rpc::commands.call_command(m_command.as_dict_key().c_str(), m_command.as_dict_obj(), rpc::make_target_pair(d1, d2)).as_value();
} catch (torrent::input_error& e) {
control->core()->push_log(e.what());
@@ -88,10 +50,11 @@ struct view_downloads_compare : std::binary_function<Download*, Download*, bool>
const torrent::Object& m_command;
};
struct view_downloads_filter : std::unary_function<Download*, bool> {
view_downloads_filter(const torrent::Object& cmd, const torrent::Object& cmd2) : m_command(cmd), m_command2(cmd2) {}
struct view_downloads_filter : std::function<bool (Download*)> {
view_downloads_filter(const torrent::Object& cmd, const torrent::Object& cmd2) :
m_command(cmd), m_command2(cmd2) {}
bool operator () (Download* d1) const {
bool operator()(Download* d1) const {
return this->evalCmd(m_command, d1) && this->evalCmd(m_command2, d1);
}
@@ -121,11 +84,16 @@ struct view_downloads_filter : std::unary_function<Download*, bool> {
switch (result.type()) {
// case torrent::Object::TYPE_RAW_BENCODE: return !result.as_raw_bencode().empty();
case torrent::Object::TYPE_VALUE: return result.as_value();
case torrent::Object::TYPE_STRING: return !result.as_string().empty();
case torrent::Object::TYPE_LIST: return !result.as_list().empty();
case torrent::Object::TYPE_MAP: return !result.as_map().empty();
default: return false;
case torrent::Object::TYPE_VALUE:
return result.as_value();
case torrent::Object::TYPE_STRING:
return !result.as_string().empty();
case torrent::Object::TYPE_LIST:
return !result.as_list().empty();
case torrent::Object::TYPE_MAP:
return !result.as_map().empty();
default:
return false;
}
// The default filter action is to return true, to not filter
@@ -139,14 +107,13 @@ struct view_downloads_filter : std::unary_function<Download*, bool> {
}
}
const torrent::Object& m_command;
const torrent::Object& m_command2;
const torrent::Object& m_command;
const torrent::Object& m_command2;
};
void
View::emit_changed() {
priority_queue_erase(&taskScheduler, &m_delayChanged);
priority_queue_insert(&taskScheduler, &m_delayChanged, cachedTime);
priority_queue_update(&taskScheduler, &m_delayChanged, cachedTime);
}
void
@@ -176,9 +143,9 @@ View::initialize(const std::string& name) {
m_name = name;
// Urgh, wrong. No filtering being done.
std::for_each(dlist->begin(), dlist->end(), rak::bind1st(std::mem_fun(&View::push_back), this));
std::for_each(dlist->begin(), dlist->end(), [&](Download* d) { push_back(d); });
m_size = base_type::size();
m_size = base_type::size();
m_focus = 0;
set_last_changed(rak::timer());
@@ -232,20 +199,45 @@ View::set_not_visible(Download* download) {
}
void
View::next_focus() {
View::next_focus(unsigned int i) {
if (empty())
return;
m_focus = (m_focus + 1) % (size() + 1);
// If at the boundary, roll over
if (m_focus == size() - 1) {
m_focus = size();
emit_changed();
return;
}
// Move forward, stop at the boundary
if (m_focus == size()) // Needs special handling to ensure it's not off by one
m_focus = i - 1;
else
m_focus += i;
if (m_focus > size() - 1)
m_focus = size() - 1;
emit_changed();
}
void
View::prev_focus() {
View::prev_focus(unsigned int i) {
if (empty())
return;
m_focus = (m_focus - 1 + size() + 1) % (size() + 1);
// If at the boundary, roll over
if (m_focus == size()) {
m_focus = size() - 1;
emit_changed();
return;
}
// Move backward, stop at the boundary
m_focus -= i;
if (m_focus < 0 || m_focus > size())
m_focus = size();
emit_changed();
}
@@ -267,12 +259,12 @@ View::filter() {
return;
// Parition the list in two steps so we know which elements changed.
iterator splitVisible = std::stable_partition(begin_visible(), end_visible(), view_downloads_filter(m_filter, m_temp_filter));
iterator splitFiltered = std::stable_partition(begin_filtered(), end_filtered(), view_downloads_filter(m_filter, m_temp_filter));
iterator splitVisible = std::stable_partition(begin_visible(), end_visible(), view_downloads_filter(m_filter, m_temp_filter));
iterator splitFiltered = std::stable_partition(begin_filtered(), end_filtered(), view_downloads_filter(m_filter, m_temp_filter));
base_type changed(splitVisible, splitFiltered);
iterator splitChanged = changed.begin() + std::distance(splitVisible, end_visible());
iterator splitChanged = changed.begin() + std::distance(splitVisible, end_visible());
m_size = std::distance(begin(), std::copy(splitChanged, changed.end(), splitVisible));
std::copy(changed.begin(), splitChanged, begin_filtered());
@@ -290,12 +282,10 @@ View::filter() {
// set the elements to NULL as we trigger commands on them. Or
// perhaps always clear them, thus not throwing anything.
if (!m_event_removed.is_empty())
std::for_each(changed.begin(), splitChanged,
std::bind(&rpc::call_object_d_nothrow, m_event_removed, std::placeholders::_1));
std::for_each(changed.begin(), splitChanged, std::bind(&rpc::call_object_d_nothrow, m_event_removed, std::placeholders::_1));
if (!m_event_added.is_empty())
std::for_each(changed.begin(), splitChanged,
std::bind(&rpc::call_object_d_nothrow, m_event_added, std::placeholders::_1));
std::for_each(changed.begin(), splitChanged, std::bind(&rpc::call_object_d_nothrow, m_event_added, std::placeholders::_1));
emit_changed();
}
@@ -358,7 +348,7 @@ View::clear_filter_on() {
inline void
View::insert_visible(Download* d) {
iterator itr = std::find_if(begin_visible(), end_visible(), std::bind1st(view_downloads_compare(m_sortNew), d));
iterator itr = std::find_if(begin_visible(), end_visible(), [&d, this](Download* d2) { return view_downloads_compare(m_sortNew)(d, d2); });
m_size++;
m_focus += (m_focus >= position(itr));
@@ -377,4 +367,4 @@ View::erase_internal(iterator itr) {
base_type::erase(itr);
}
}
} // namespace core
+71 -101
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
// Provides a filtered and sorted list of downloads that can be
// updated auto-magically.
//
@@ -64,77 +28,83 @@ class Download;
class View : private std::vector<Download*> {
public:
typedef std::vector<Download*> base_type;
typedef std::function<void ()> slot_void;
typedef std::list<slot_void> signal_void;
typedef std::vector<Download*> base_type;
typedef std::function<void()> slot_void;
typedef std::list<slot_void> signal_void;
using base_type::iterator;
using base_type::const_iterator;
using base_type::reverse_iterator;
using base_type::const_reverse_iterator;
using base_type::iterator;
using base_type::reverse_iterator;
using base_type::size_type;
View() {}
~View();
void initialize(const std::string& name);
void initialize(const std::string& name);
const std::string& name() const { return m_name; }
const std::string& name() const { return m_name; }
bool empty_visible() const { return m_size == 0; }
bool empty_visible() const { return m_size == 0; }
size_type size() const { return m_size; }
size_type size_visible() const { return m_size; }
size_type size_not_visible() const { return base_type::size() - m_size; }
size_type size() const { return m_size; }
size_type size_visible() const { return m_size; }
size_type size_not_visible() const { return base_type::size() - m_size; }
// Perhaps this should be renamed?
iterator begin_visible() { return begin(); }
const_iterator begin_visible() const { return begin(); }
iterator begin_visible() { return begin(); }
const_iterator begin_visible() const { return begin(); }
iterator end_visible() { return begin() + m_size; }
const_iterator end_visible() const { return begin() + m_size; }
iterator end_visible() { return begin() + m_size; }
const_iterator end_visible() const { return begin() + m_size; }
iterator begin_filtered() { return begin() + m_size; }
const_iterator begin_filtered() const { return begin() + m_size; }
iterator begin_filtered() { return begin() + m_size; }
const_iterator begin_filtered() const { return begin() + m_size; }
iterator end_filtered() { return base_type::end(); }
const_iterator end_filtered() const { return base_type::end(); }
iterator end_filtered() { return base_type::end(); }
const_iterator end_filtered() const { return base_type::end(); }
iterator focus() { return begin() + m_focus; }
const_iterator focus() const { return begin() + m_focus; }
void set_focus(iterator itr) { m_focus = position(itr); emit_changed(); }
iterator focus() { return begin() + m_focus; }
const_iterator focus() const { return begin() + m_focus; }
void set_focus(iterator itr) {
m_focus = position(itr);
emit_changed();
}
void insert(Download* download) { base_type::push_back(download); }
void erase(Download* download);
void insert(Download* download) { base_type::push_back(download); }
void erase(Download* download);
void set_visible(Download* download);
void set_not_visible(Download* download);
void set_visible(Download* download);
void set_not_visible(Download* download);
void next_focus();
void prev_focus();
void next_focus(unsigned int i);
void prev_focus(unsigned int i);
void sort();
void next_focus() { next_focus(1); }
void prev_focus() { prev_focus(1); }
void set_sort_new(const torrent::Object& s) { m_sortNew = s; }
void set_sort_current(const torrent::Object& s) { m_sortCurrent = s; }
void sort();
void set_sort_new(const torrent::Object& s) { m_sortNew = s; }
void set_sort_current(const torrent::Object& s) { m_sortCurrent = s; }
// Need to explicity trigger filtering.
void filter();
void filter_by(const torrent::Object& condition, base_type& result);
void filter_download(core::Download* download);
void filter();
void filter_by(const torrent::Object& condition, base_type& result);
void filter_download(core::Download* download);
const torrent::Object& get_filter() const { return m_filter; }
void set_filter(const torrent::Object& s) { m_filter = s; }
void set_filter(const torrent::Object& s) { m_filter = s; }
const torrent::Object& get_filter_temp() const { return m_temp_filter; }
void set_filter_temp(const torrent::Object& s) { m_temp_filter = s; }
void set_filter_on_event(const std::string& event);
void set_filter_temp(const torrent::Object& s) { m_temp_filter = s; }
void set_filter_on_event(const std::string& event);
void clear_filter_on();
void clear_filter_on();
const torrent::Object& event_added() const { return m_event_added; }
const torrent::Object& event_removed() const { return m_event_removed; }
void set_event_added(const torrent::Object& cmd) { m_event_added = cmd; }
const torrent::Object& event_added() const { return m_event_added; }
const torrent::Object& event_removed() const { return m_event_removed; }
void set_event_added(const torrent::Object& cmd) { m_event_added = cmd; }
void set_event_removed(const torrent::Object& cmd) { m_event_removed = cmd; }
// The time of the last change to the view, semantics of this is
@@ -143,50 +113,50 @@ 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; }
rak::timer last_changed() const { return m_lastChanged; }
void set_last_changed(const rak::timer& t = ::cachedTime) { m_lastChanged = t; }
// Don't connect any slots until after initialize else it get's
// triggered when adding the Download's in DownloadList.
signal_void& signal_changed() { return m_signal_changed; }
signal_void& signal_changed() { return m_signal_changed; }
private:
View(const View&);
void operator = (const View&);
void operator=(const View&);
void push_back(Download* d) { base_type::push_back(d); }
void push_back(Download* d) { base_type::push_back(d); }
inline void insert_visible(Download* d);
inline void erase_internal(iterator itr);
inline void insert_visible(Download* d);
inline void erase_internal(iterator itr);
void emit_changed();
void emit_changed_now();
void emit_changed();
void emit_changed_now();
size_type position(const_iterator itr) const { return itr - begin(); }
size_type position(const_iterator itr) const { return itr - begin(); }
// An received thing for changed status so we can sort and filter.
std::string m_name;
std::string m_name;
size_type m_size;
size_type m_focus;
size_type m_size;
size_type m_focus;
// These should be replaced by a faster non-string command type.
torrent::Object m_sortNew;
torrent::Object m_sortCurrent;
torrent::Object m_sortNew;
torrent::Object m_sortCurrent;
torrent::Object m_filter;
torrent::Object m_temp_filter; // Temporary view filter (eg: name based filter)
torrent::Object m_filter;
torrent::Object m_temp_filter; // Temporary view filter (eg: name based filter)
torrent::Object m_event_added;
torrent::Object m_event_removed;
torrent::Object m_event_added;
torrent::Object m_event_removed;
rak::timer m_lastChanged;
rak::timer m_lastChanged;
signal_void m_signal_changed;
rak::priority_item m_delayChanged;
signal_void m_signal_changed;
rak::priority_item m_delayChanged;
};
}
} // namespace core
#endif
+3 -4
View File
@@ -37,7 +37,6 @@
#include "config.h"
#include <algorithm>
#include <rak/functional.h>
#include <torrent/exceptions.h>
#include <torrent/object.h>
@@ -55,7 +54,7 @@ namespace core {
void
ViewManager::clear() {
std::for_each(begin(), end(), rak::call_delete<View>());
std::for_each(begin(), end(), [](View* v) { delete v; });
base_type::clear();
}
@@ -76,12 +75,12 @@ ViewManager::insert(const std::string& name) {
ViewManager::iterator
ViewManager::find(const std::string& name) {
return std::find_if(begin(), end(), rak::equal(name, std::mem_fun(&View::name)));
return std::find_if(begin(), end(), [name](View* v){ return name == v->name(); });
}
ViewManager::iterator
ViewManager::find_throw(const std::string& name) {
iterator itr = std::find_if(begin(), end(), rak::equal(name, std::mem_fun(&View::name)));
iterator itr = std::find_if(begin(), end(), [name](View* v){ return name == v->name(); });
if (itr == end())
throw torrent::input_error("Could not find view: " + name);
+120 -43
View File
@@ -1,45 +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 <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <torrent/exceptions.h>
#include <unistd.h>
#include "rpc/parse_commands.h"
@@ -48,14 +12,16 @@
namespace display {
bool Canvas::m_isInitialized = false;
bool Canvas::m_isDaemon = false;
bool Canvas::m_isDaemon = false;
// Maps ncurses color IDs to a ncurses attribute int
std::unordered_map<int, int> Canvas::m_attr_map = {};
Canvas::Canvas(int x, int y, int width, int height) {
if (!m_isDaemon) {
m_window = newwin(height, width, y, x);
m_window = newwin(height, width, y, x);
if (m_window == NULL)
throw torrent::internal_error("Could not allocate ncurses canvas.");
if (m_window == NULL)
throw torrent::internal_error("Could not allocate ncurses canvas.");
}
}
@@ -73,7 +39,7 @@ Canvas::print_attributes(unsigned int x, unsigned int y, const char* first, cons
move(x, y);
attr_t org_attr;
short org_pair;
short org_pair;
wattr_get(m_window, &org_attr, &org_pair, NULL);
attributes_list::const_iterator attrItr = attributes->begin();
@@ -111,6 +77,9 @@ Canvas::initialize() {
if (!m_isDaemon) {
initscr();
start_color();
use_default_colors();
Canvas::build_colors();
raw();
noecho();
nodelay(stdscr, TRUE);
@@ -119,6 +88,114 @@ Canvas::initialize() {
}
}
// Function wrapper for what possibly is a macro
int
get_colors() {
return COLORS;
}
// Turns the string color definitions from the "ui.color.*" RPC
// commands into valid ncurses color pairs
void
Canvas::build_colors() {
// This may get called early in the start process by the config
// file, so we need to delay building until initscr() has a chance
// to run
if (!m_isInitialized || m_isDaemon)
return;
// basic color names, index maps to ncurses COLOR_*
static const char* color_names[] = {
"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"};
// Those hold the background colors of "odd" and "even"
int bg_odd = -1;
int bg_even = -1;
for (int k = 1; k < RCOLOR_MAX; k++) {
init_pair(k, -1, -1);
std::string color_def = rpc::call_command_string(color_vars[k]);
if (color_def.empty())
continue; // Use terminal default if definition is empty
short color[2] = {-1, -1}; // fg, bg
short color_idx = 0; // 0 = fg; 1 = bg
short bright = 0;
unsigned long attr = A_NORMAL;
// Process string as space-separated words
size_t start = 0, end = 0;
while (true) {
end = color_def.find(' ', start);
std::string word = color_def.substr(start, end - start);
if (word == "bold")
attr |= A_BOLD;
else if (word == "standout")
attr |= A_STANDOUT;
else if (word == "underline")
attr |= A_UNDERLINE;
else if (word == "reverse")
attr |= A_REVERSE;
else if (word == "blink")
attr |= A_BLINK;
else if (word == "dim")
attr |= A_DIM;
else if (word == "on") {
color_idx = 1;
bright = 0;
} // Switch to background color
else if (word == "gray" || word == "grey")
color[color_idx] = bright ? 7 : 8; // Bright gray is white
else if (word == "bright")
bright = 8;
else if (word.find_first_not_of("0123456789") == std::string::npos) {
// Handle numeric index
short c = -1;
sscanf(word.c_str(), "%hd", &c);
color[color_idx] = c;
} else
for (short c = 0; c < 8; c++) { // Check for basic color names
if (word == color_names[c]) {
color[color_idx] = bright + c;
break;
}
}
if (end == std::string::npos)
break;
start = end + 1;
}
// 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());
Canvas::cleanup();
throw torrent::input_error(color_def + ": your terminal only supports " + buf + " colors.");
}
m_attr_map[k] = attr; // overwrite or insert the value
init_pair(k, color[0], color[1]);
if (k == RCOLOR_EVEN)
bg_even = color[1];
if (k == RCOLOR_ODD)
bg_odd = color[1];
}
// Now make copies of the basic colors with the "odd" and "even" definitions mixed in
for (int k = 1; k < RCOLOR_MAX; k++) {
short fg, bg;
pair_content(k, &fg, &bg);
// Replace the background color, and mix in the attributes
m_attr_map[k + 1 * RCOLOR_MAX] = m_attr_map[k] | m_attr_map[RCOLOR_EVEN];
m_attr_map[k + 2 * RCOLOR_MAX] = m_attr_map[k] | m_attr_map[RCOLOR_ODD];
init_pair(k + 1 * RCOLOR_MAX, fg, bg == -1 ? bg_even : bg);
init_pair(k + 2 * RCOLOR_MAX, fg, bg == -1 ? bg_odd : bg);
}
}
void
Canvas::cleanup() {
if (!m_isInitialized)
@@ -143,4 +220,4 @@ Canvas::term_size() {
return std::pair<int, int>(80, 24);
}
}
} // namespace display
+227 -84
View File
@@ -1,125 +1,204 @@
// 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_CANVAS_H
#define RTORRENT_DISPLAY_CANVAS_H
#include <string>
#include <unordered_map>
#include <vector>
#include "attributes.h"
#include "color_map.h"
namespace display {
class Canvas {
public:
typedef std::vector<Attributes> attributes_list;
typedef std::vector<Attributes> attributes_list;
typedef std::unordered_map<int, int> attributes_map;
Canvas(int x = 0, int y = 0, int width = 0, int height = 0);
~Canvas() { if (!m_isDaemon) { delwin(m_window); } }
~Canvas();
void refresh() { if (!m_isDaemon) { wnoutrefresh(m_window); } }
static void refresh_std() { if (!m_isDaemon) { wnoutrefresh(stdscr); } }
void redraw() { if (!m_isDaemon) { redrawwin(m_window); } }
static void redraw_std() { if (!m_isDaemon) { redrawwin(stdscr); } }
void refresh();
void redraw();
void resize(int w, int h);
void resize(int x, int y, int w, int h);
void resize(int w, int h) { if (!m_isDaemon) { wresize(m_window, h, w); } }
void resize(int x, int y, int w, int h);
static void refresh_std();
static void redraw_std();
static void resize_term(int x, int y);
static void resize_term(std::pair<int, int> dim);
static void resize_term(int x, int y) { if (!m_isDaemon) { resizeterm(y, x); } }
static void resize_term(std::pair<int, int> dim) { if (!m_isDaemon) { resizeterm(dim.second, dim.first); } }
unsigned int get_x();
unsigned int get_y();
unsigned int width();
unsigned int height();
unsigned int get_x() { int x, __UNUSED y; if (!m_isDaemon) { getyx(m_window, y, x); } else { x=1; } return x; }
unsigned int get_y() { int x, y; if (!m_isDaemon) { getyx(m_window, y, x); } else { y=1; } return y; }
unsigned int width() { int x, __UNUSED y; if (!m_isDaemon) { getmaxyx(m_window, y, x); } else { x=80; } return x; }
unsigned int height() { int x, y; if (!m_isDaemon) { getmaxyx(m_window, y, x); } else { y=24; } return y; }
void move(unsigned int x, unsigned int y) { if (!m_isDaemon) { wmove(m_window, y, x); } }
chtype get_background() { chtype bg=0; if (!m_isDaemon) { bg=getbkgd(m_window); } return bg; }
void set_background(chtype c) { if (!m_isDaemon) { return wbkgdset(m_window, c); } }
void erase() { if (!m_isDaemon) { werase(m_window); } }
static void erase_std() { if (!m_isDaemon) { werase(stdscr); } }
void print_border(chtype ls, chtype rs,
chtype ts, chtype bs,
chtype tl, chtype tr,
chtype bl, chtype br) { if (!m_isDaemon) { wborder(m_window, ls, rs, ts, bs, tl, tr, bl, br); } }
void move(unsigned int x, unsigned int y);
void erase();
static void erase_std();
// The format string is non-const, but that will not be a problem
// since the string shall always be a C string choosen at
// compiletime. Might cause extra copying of the string?
void print(const char* str, ...);
void print(unsigned int x, unsigned int y, const char* str, ...);
void print(const char* str, ...);
void print(unsigned int x, unsigned int y, const char* str, ...);
void print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes);
void print_char(const chtype ch);
void print_char(unsigned int x, unsigned int y, const chtype ch);
void print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes);
void print_char(const chtype ch) { if (!m_isDaemon) { waddch(m_window, ch); } }
void print_char(unsigned int x, unsigned int y, const chtype ch) { if (!m_isDaemon) { mvwaddch(m_window, y, x, ch); } }
void set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color) { if (!m_isDaemon) { mvwchgat(m_window, y, x, n, attr, color, NULL); } }
void set_default_attributes(int attr) { if (!m_isDaemon) { (void)wattrset(m_window, attr); } }
void set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color);
void set_attr(unsigned int x, unsigned int y, unsigned int n, ColorKind k);
void set_default_attributes(int attr);
// Initialize stdscr.
static void initialize();
static void cleanup();
static void initialize();
static void build_colors();
static void cleanup();
static int get_screen_width() { int x, __UNUSED y; if (!m_isDaemon) { getmaxyx(stdscr, y, x); } else { x=80; } return x; }
static int get_screen_height() { int x, y; if (!m_isDaemon) { getmaxyx(stdscr, y, x); } else { y=24;} return y; }
static int get_screen_width();
static int get_screen_height();
static std::pair<int, int> term_size();
static void do_update() { if (!m_isDaemon) { doupdate(); } }
static void do_update();
static bool daemon() { return m_isDaemon; }
static bool daemon() { return m_isDaemon; }
static const attributes_map& attr_map() { return m_attr_map; }
private:
Canvas(const Canvas&);
void operator = (const Canvas&);
void operator=(const Canvas&);
static bool m_isInitialized;
static bool m_isDaemon;
static bool m_isInitialized;
static bool m_isDaemon;
WINDOW* m_window;
// Maps ncurses color IDs to a ncurses attribute int
static std::unordered_map<int, int> m_attr_map;
WINDOW* m_window;
};
inline Canvas::~Canvas() {
if (!m_isDaemon) {
delwin(m_window);
}
}
inline void
Canvas::refresh() {
if (!m_isDaemon) {
wnoutrefresh(m_window);
}
}
inline void
Canvas::refresh_std() {
if (!m_isDaemon) {
wnoutrefresh(stdscr);
}
}
inline void
Canvas::redraw() {
if (!m_isDaemon) {
redrawwin(m_window);
}
}
inline void
Canvas::redraw_std() {
if (!m_isDaemon) {
redrawwin(stdscr);
}
}
inline void
Canvas::resize(int w, int h) {
if (!m_isDaemon) {
wresize(m_window, h, w);
}
}
inline void
Canvas::resize_term(int x, int y) {
if (!m_isDaemon) {
resizeterm(y, x);
}
}
inline void
Canvas::resize_term(std::pair<int, int> dim) {
if (!m_isDaemon) {
resizeterm(dim.second, dim.first);
}
}
inline unsigned int
Canvas::get_x() {
int x, __UNUSED y;
if (!m_isDaemon) {
getyx(m_window, y, x);
} else {
x = 1;
}
return x;
}
inline unsigned int
Canvas::get_y() {
int x, y;
if (!m_isDaemon) {
getyx(m_window, y, x);
} else {
y = 1;
}
return y;
}
inline unsigned int
Canvas::width() {
int x, __UNUSED y;
if (!m_isDaemon) {
getmaxyx(m_window, y, x);
} else {
x = 80;
}
return x;
}
inline unsigned int
Canvas::height() {
int x, y;
if (!m_isDaemon) {
getmaxyx(m_window, y, x);
} else {
y = 24;
}
return y;
}
inline void
Canvas::move(unsigned int x, unsigned int y) {
if (!m_isDaemon) {
wmove(m_window, y, x);
}
}
inline void
Canvas::erase() {
if (!m_isDaemon) {
werase(m_window);
}
}
inline void
Canvas::erase_std() {
if (!m_isDaemon) {
werase(stdscr);
}
}
inline void
Canvas::print(const char* str, ...) {
va_list arglist;
@@ -143,6 +222,70 @@ Canvas::print(unsigned int x, unsigned int y, const char* str, ...) {
}
}
inline void
Canvas::print_char(const chtype ch) {
if (!m_isDaemon) {
waddch(m_window, ch);
}
}
inline void
Canvas::print_char(unsigned int x, unsigned int y, const chtype ch) {
if (!m_isDaemon) {
mvwaddch(m_window, y, x, ch);
}
}
inline void
Canvas::set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color) {
if (!m_isDaemon) {
mvwchgat(m_window, y, x, n, attr, color, NULL);
}
}
inline void
Canvas::set_attr(unsigned int x, unsigned int y, unsigned int n, ColorKind k) {
if (!m_isDaemon) {
mvwchgat(m_window, y, x, n, m_attr_map[k], k, NULL);
}
}
inline void
Canvas::set_default_attributes(int attr) {
if (!m_isDaemon) {
(void)wattrset(m_window, attr);
}
}
inline int
Canvas::get_screen_width() {
int x, __UNUSED y;
if (!m_isDaemon) {
getmaxyx(stdscr, y, x);
} else {
x = 80;
}
return x;
}
inline int
Canvas::get_screen_height() {
int x, y;
if (!m_isDaemon) {
getmaxyx(stdscr, y, x);
} else {
y = 24;
}
return y;
}
inline void
Canvas::do_update() {
if (!m_isDaemon) {
doupdate();
}
}
} // namespace display
#endif
+48
View File
@@ -0,0 +1,48 @@
#ifndef RTORRENT_DISPLAY_COLOR_MAP_H
#define RTORRENT_DISPLAY_COLOR_MAP_H
#include <map>
#include <curses.h>
namespace display {
enum ColorKind {
RCOLOR_NCURSES_DEFAULT, // Color 0 is reserved by ncurses and cannot be changed
RCOLOR_TITLE,
RCOLOR_FOOTER,
RCOLOR_FOCUS,
RCOLOR_LABEL,
RCOLOR_INFO,
RCOLOR_ALARM,
RCOLOR_COMPLETE,
RCOLOR_SEEDING,
RCOLOR_STOPPED,
RCOLOR_QUEUED,
RCOLOR_INCOMPLETE,
RCOLOR_LEECHING,
RCOLOR_ODD,
RCOLOR_EVEN,
RCOLOR_MAX,
};
static const char* color_vars[RCOLOR_MAX] = {
0,
"ui.color.title",
"ui.color.footer",
"ui.color.focus",
"ui.color.label",
"ui.color.info",
"ui.color.alarm",
"ui.color.complete",
"ui.color.seeding",
"ui.color.stopped",
"ui.color.queued",
"ui.color.incomplete",
"ui.color.leeching",
"ui.color.odd",
"ui.color.even",
};
} // namespace display
#endif
+2 -5
View File
@@ -38,7 +38,6 @@
#include <stdexcept>
#include <algorithm>
#include <rak/functional.h>
#include "canvas.h"
#include "globals.h"
@@ -64,8 +63,7 @@ Manager::force_redraw() {
void
Manager::schedule(Window* w, rak::timer t) {
rak::priority_queue_erase(&m_scheduler, w->task_update());
rak::priority_queue_insert(&m_scheduler, w->task_update(), t);
rak::priority_queue_update(&m_scheduler, w->task_update(), t);
schedule_update(50000);
}
@@ -114,8 +112,7 @@ Manager::schedule_update(uint32_t minInterval) {
}
if (!m_taskUpdate.is_queued() || m_taskUpdate.time() > m_scheduler.top()->time()) {
rak::priority_queue_erase(&taskScheduler, &m_taskUpdate);
rak::priority_queue_insert(&taskScheduler, &m_taskUpdate, std::max(m_scheduler.top()->time(), m_timeLastUpdate + minInterval));
rak::priority_queue_update(&taskScheduler, &m_taskUpdate, std::max(m_scheduler.top()->time(), m_timeLastUpdate + minInterval));
}
}
+1 -2
View File
@@ -37,7 +37,6 @@
#include "config.h"
#include <algorithm>
#include <rak/functional.h>
#include <torrent/exceptions.h>
#include "text_element_list.h"
@@ -46,7 +45,7 @@ namespace display {
void
TextElementList::clear() {
std::for_each(begin(), end(), rak::call_delete<TextElement>());
std::for_each(begin(), end(), [](TextElement* t) { delete t; });
base_type::clear();
}
+6 -43
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 <cstring>
@@ -47,8 +11,8 @@
#include <torrent/rate.h>
#include <torrent/throttle.h>
#include <torrent/torrent.h>
#include <torrent/tracker.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>
@@ -88,7 +52,7 @@ print_hhmmss(char* first, char* last, time_t t) {
char*
print_hhmmss_local(char* first, char* last, time_t t) {
std::tm *u = std::localtime(&t);
if (u == NULL)
//return "inv_time";
throw torrent::internal_error("print_hhmmss_local(...) failed.");
@@ -107,7 +71,7 @@ print_ddhhmm(char* first, char* last, time_t t) {
char*
print_ddmmyyyy(char* first, char* last, time_t t) {
std::tm *u = std::gmtime(&t);
if (u == NULL)
//return "inv_time";
throw torrent::internal_error("print_ddmmyyyy(...) failed.");
@@ -199,12 +163,11 @@ print_download_status(char* first, char* last, core::Download* d) {
} 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_fun(&torrent::Tracker::is_busy_not_scrape));
char status[128];
std::mem_fn(&torrent::tracker::Tracker::is_busy_not_scrape));
auto status = itr->status();
(*itr)->get_status(status, sizeof(status));
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);
itr->group(), std::distance(d->tracker_list()->begin(), itr), itr->url().c_str(), status.c_str());
} else if (!d->message().empty()) {
first = print_buffer(first, last, "%s", d->message().c_str());
+4 -5
View File
@@ -38,7 +38,7 @@
#define RTORRENT_WINDOW_BASE_H
#include <rak/timer.h>
#include <rak/functional.h>
#include <functional>
#include "canvas.h"
#include "globals.h"
@@ -46,15 +46,14 @@
namespace display {
class Canvas;
class Manager;
class Window {
public:
typedef uint32_t extent_type;
typedef rak::mem_fun0<Manager, void> Slot;
typedef rak::mem_fun1<Manager, void, Window*> SlotWindow;
typedef rak::mem_fun2<Manager, void, Window*, rak::timer> SlotTimer;
typedef std::function<void()> Slot;
typedef std::function<void(Window*)> SlotWindow;
typedef std::function<void(Window*, rak::timer)> SlotTimer;
static const int flag_active = (1 << 0);
static const int flag_offscreen = (1 << 1);
+2 -3
View File
@@ -38,7 +38,6 @@
#include <cmath>
#include <stdexcept>
#include <rak/functional.h>
#include <rak/string_manip.h>
#include <torrent/bitfield.h>
#include <torrent/data/block.h>
@@ -95,7 +94,7 @@ WindowDownloadChunksSeen::redraw() {
std::vector<torrent::BlockList*> transferChunks(transfers->size(), 0);
std::copy(transfers->begin(), transfers->end(), transferChunks.begin());
std::sort(transferChunks.begin(), transferChunks.end(), rak::less2(std::mem_fun(&torrent::BlockList::index), std::mem_fun(&torrent::BlockList::index)));
std::sort(transferChunks.begin(), transferChunks.end());
std::vector<torrent::BlockList*>::const_iterator itrTransfer = transferChunks.begin();
@@ -111,7 +110,7 @@ WindowDownloadChunksSeen::redraw() {
if (bitfield->get(chunk - seen)) {
attr = A_NORMAL;
} else if (itrTransfer != transferChunks.end() && (uint32_t)(chunk - seen) == (*itrTransfer)->index()) {
if (std::find_if((*itrTransfer)->begin(), (*itrTransfer)->end(), std::mem_fun_ref(&torrent::Block::is_transfering)) != (*itrTransfer)->end())
if (std::any_of((*itrTransfer)->begin(), (*itrTransfer)->end(), std::mem_fn(&torrent::Block::is_transfering)))
attr = A_REVERSE;
else
attr = A_BOLD | A_UNDERLINE;
+65 -56
View File
@@ -1,41 +1,6 @@
// 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/color_map.h"
#include <rak/algorithm.h>
#include "core/download.h"
@@ -57,7 +22,7 @@ WindowDownloadList::WindowDownloadList() :
WindowDownloadList::~WindowDownloadList() {
if (m_view != NULL)
m_view->signal_changed().erase(m_changed_itr);
m_view = NULL;
}
@@ -72,8 +37,47 @@ WindowDownloadList::set_view(core::View* l) {
m_changed_itr = m_view->signal_changed().insert(m_view->signal_changed().begin(), std::bind(&Window::mark_dirty, this));
}
// Return a pair of ints, representing a) the ncurses attributes and b) the ncurses color pair ID to use
std::pair<int, int>
WindowDownloadList::get_attr_color(core::View::iterator selected) {
core::Download* item = *selected;
unsigned long focus_attr = selected == m_view->focus() ? m_canvas->attr_map().at(RCOLOR_FOCUS) : 0;
int offset = (((selected - m_view->begin_visible()) & 1) + 1) * RCOLOR_MAX; // Determine the even/odd offset for the color pair
bool active = item->is_open() && item->is_active();
int title_color;
if (item->is_done())
title_color = (active ? item->info()->up_rate()->rate() ? RCOLOR_SEEDING : RCOLOR_COMPLETE : RCOLOR_STOPPED) + offset;
else
title_color = (active ? item->info()->down_rate()->rate() ? RCOLOR_LEECHING : RCOLOR_INCOMPLETE : RCOLOR_QUEUED) + offset;
return std::make_pair(m_canvas->attr_map().at(title_color) | focus_attr, title_color);
}
int
WindowDownloadList::page_size(const std::string layout_name) {
// Calculate the page size for torrents. This is a public method
// because it's also used to determine the default size for page
// up/down actions.
int layout_height;
if (layout_name == "full") {
layout_height = 3;
} else if (layout_name == "compact") {
layout_height = 1;
} else {
return 0;
}
return m_canvas->height() / layout_height;
}
int
WindowDownloadList::page_size() {
return page_size(rpc::call_command_string("ui.torrent_list.layout"));
}
void
WindowDownloadList::redraw() {
if (m_canvas->daemon())
return;
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
m_canvas->erase();
@@ -95,24 +99,16 @@ WindowDownloadList::redraw() {
m_canvas->print(m_canvas->width() - 16, 0, "[%5d of %-5d]", item_idx + 1, m_view->size());
}
int layout_height;
const std::string layout_name = rpc::call_command_string("ui.torrent_list.layout");
m_canvas->set_attr(0, 0, -1, RCOLOR_TITLE);
if (layout_name == "full") {
layout_height = 3;
} else if (layout_name == "compact") {
layout_height = 1;
} else {
m_canvas->print(0, 0, "INVALID ui.torrent_list.layout '%s'", layout_name.c_str());
return;
}
const std::string layout_name = rpc::call_command_string("ui.torrent_list.layout");
typedef std::pair<core::View::iterator, core::View::iterator> Range;
Range range = rak::advance_bidirectional(m_view->begin_visible(),
m_view->focus() != m_view->end_visible() ? m_view->focus() : m_view->begin_visible(),
m_view->end_visible(),
m_canvas->height() / layout_height);
page_size(layout_name));
// Make sure we properly fill out the last lines so it looks like
// there are more torrents, yet don't hide it if we got the last one
@@ -120,8 +116,8 @@ WindowDownloadList::redraw() {
if (range.second != m_view->end_visible())
++range.second;
int pos = 1;
char buffer[m_canvas->width() + 1];
int pos = 1;
char buffer[m_canvas->width() + 1];
char* last = buffer + m_canvas->width() - 2 + 1;
// Add a proper 'column info' method.
@@ -134,25 +130,38 @@ WindowDownloadList::redraw() {
if (layout_name == "full") {
while (range.first != range.second) {
bool is_focused = range.first == m_view->focus();
char focus_char = is_focused ? '*' : ' ';
ColorKind focus_color = is_focused ? RCOLOR_FOCUS : RCOLOR_LABEL;
auto attr_color = get_attr_color(range.first);
print_download_title(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
m_canvas->set_attr(2, pos++, -1, attr_color.first, attr_color.second);
print_download_info_full(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
m_canvas->set_attr(2, pos++, -1, focus_color);
print_download_status(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
m_canvas->set_attr(2, pos++, -1, focus_color);
range.first++;
}
} else {
while (range.first != range.second) {
char focus_char = range.first == m_view->focus() ? '*' : ' ';
auto attr_color = get_attr_color(range.first);
print_download_info_compact(buffer, last, *range.first);
m_canvas->set_default_attributes(range.first == m_view->focus() ? A_REVERSE : A_NORMAL);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
m_canvas->set_attr(2, pos++, -1, attr_color.first, attr_color.second);
range.first++;
}
}
}
}
} // namespace display
+5 -36
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_WINDOW_DOWNLOAD_LIST_H
#define RTORRENT_DISPLAY_WINDOW_DOWNLOAD_LIST_H
@@ -47,6 +11,7 @@ namespace display {
class WindowDownloadList : public Window {
public:
typedef core::View::signal_void::iterator signal_void_itr;
typedef std::pair<core::View::iterator, core::View::iterator> ViewRange;
WindowDownloadList();
~WindowDownloadList();
@@ -55,9 +20,13 @@ public:
void set_view(core::View* l);
int page_size(const std::string layout_name);
int page_size();
private:
core::View* m_view;
std::pair<int, int> get_attr_color(core::View::iterator selected);
signal_void_itr m_changed_itr;
};
+4 -37
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 <torrent/rate.h>
@@ -59,6 +23,9 @@ WindowDownloadStatusbar::WindowDownloadStatusbar(core::Download* d) :
void
WindowDownloadStatusbar::redraw() {
if (m_canvas->daemon())
return;
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
m_canvas->erase();
@@ -91,7 +58,7 @@ WindowDownloadStatusbar::redraw() {
print_download_status(buffer, last, m_download);
m_canvas->print(0, 2, "[%c:%i] %s",
m_download->tracker_list()->has_active() ? 'C' : ' ',
(int)(m_download->download()->tracker_controller()->seconds_to_next_timeout()),
(int)(m_download->download()->tracker_controller().seconds_to_next_timeout()),
buffer);
}
+4 -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 <locale>
@@ -83,7 +47,7 @@ wstring_width(const std::string& i_str, int width) {
// Limit to width if it's too wide already.
if (swidth == -1 || swidth > width) {
length = swidth = 0;
while (result[length]) {
int next = ::wcwidth(result[length]);
@@ -172,13 +136,13 @@ WindowFileList::redraw() {
} else if (itr.is_entering()) {
m_canvas->print(0, pos, "%*c %ls", 16 + itr.depth(), '\\',
itr.depth() < (*itr)->path()->size() ? wstring_width((*itr)->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
itr.depth() < itr.file()->path()->size() ? wstring_width(itr.file()->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
} else if (itr.is_leaving()) {
m_canvas->print(0, pos, "%*c %-*s", 16 + (itr.depth() - 1), '/', filenameWidth - (itr.depth() - 1), "");
} else if (itr.is_file()) {
torrent::File* e = *itr;
torrent::File* e = itr.file();
const char* priority;
@@ -203,7 +167,7 @@ WindowFileList::redraw() {
m_canvas->print(8, pos, "%5.1f T", (double)val / (int64_t(1) << 40));
m_canvas->print(15, pos, "%*c %ls", 1 + itr.depth(), '|',
itr.depth() < (*itr)->path()->size() ? wstring_width((*itr)->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
itr.depth() < itr.file()->path()->size() ? wstring_width(itr.file()->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
} else {
m_canvas->print(0, pos, "BORK BORK");
+1 -2
View File
@@ -42,7 +42,6 @@
#include "core/http_queue.h"
#include "canvas.h"
#include "rak/functional.h"
#include "window_http_queue.h"
namespace display {
@@ -145,7 +144,7 @@ WindowHttpQueue::receive_insert(core::CurlGet* h) {
void
WindowHttpQueue::receive_erase(core::CurlGet* h) {
Container::iterator itr = std::find_if(m_container.begin(), m_container.end(), rak::equal(h, std::mem_fun_ref(&Node::get_http)));
Container::iterator itr = std::find_if(m_container.begin(), m_container.end(), [h](Node n) { return h == n.get_http(); });
if (itr == m_container.end())
throw std::logic_error("WindowHttpQueue::receive_erase(...) tried to remove an object we don't have");
+4 -38
View File
@@ -1,44 +1,8 @@
// 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 <ctime>
#include <torrent/torrent.h>
#include <torrent/utils/thread_base.h>
#include <torrent/utils/thread.h>
#include "canvas.h"
#include "utils.h"
@@ -54,7 +18,9 @@ WindowLog::WindowLog(torrent::log_buffer* l) :
unsigned int signal_index = torrent::main_thread()->signal_bitfield()->add_signal(std::bind(&WindowLog::receive_update, this));
m_log->lock_and_set_update_slot(std::bind(&torrent::thread_base::send_event_signal, torrent::main_thread(), signal_index, false));
m_log->lock_and_set_update_slot([signal_index]() {
torrent::main_thread()->send_event_signal(signal_index, false);
});
}
WindowLog::~WindowLog() {
+2 -36
View File
@@ -1,41 +1,6 @@
// 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/color_map.h"
#include <torrent/rate.h>
#include <torrent/torrent.h>
@@ -66,6 +31,7 @@ WindowStatusbar::redraw() {
position = print_status_extra(buffer, last);
m_canvas->print(m_canvas->width() - (position - buffer), 0, "%s", buffer);
}
m_canvas->set_attr(0, 0, -1, RCOLOR_FOOTER);
m_lastTick = control->tick();
}
+1 -37
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 "canvas.h"
@@ -64,7 +28,7 @@ WindowStringList::redraw() {
if (ypos == (size_t)m_canvas->height()) {
ypos = 0;
xpos += width + 2;
if (xpos + 20 >= (size_t)m_canvas->width())
break;
+1 -2
View File
@@ -37,7 +37,6 @@
#include "config.h"
#include <algorithm>
#include <rak/functional.h>
#include "canvas.h"
#include "utils.h"
@@ -55,7 +54,7 @@ WindowText::WindowText(rpc::target_type target, extent_type margin) :
void
WindowText::clear() {
std::for_each(begin(), end(), rak::call_delete<TextElement>());
std::for_each(begin(), end(), [](TextElement* text) { delete text; });
base_type::clear();
delete m_errorHandler;
+5 -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
#include "config.h"
#include "canvas.h"
@@ -43,11 +7,13 @@ namespace display {
void
WindowTitle::redraw() {
if (m_canvas->daemon())
return;
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
m_canvas->erase();
m_canvas->print(std::max(0, ((int)m_canvas->width() - (int)m_title.size()) / 2 - 4), 0,
"*** %s ***", m_title.c_str());
m_canvas->print(std::max(0, ((int)m_canvas->width() - (int)m_title.size()) / 2 - 4), 0, "*** %s ***", m_title.c_str());
}
}
} // namespace display
+25 -59
View File
@@ -1,47 +1,11 @@
// 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/algorithm.h>
#include <rak/string_manip.h>
#include <torrent/exceptions.h>
#include <torrent/tracker.h>
#include <torrent/tracker_list.h>
#include <torrent/tracker_controller.h>
#include <torrent/tracker/tracker.h>
#include "core/download.h"
@@ -62,14 +26,14 @@ WindowTrackerList::redraw() {
m_canvas->erase();
unsigned int pos = 0;
torrent::TrackerList* tl = m_download->tracker_list();
torrent::TrackerController* tc = m_download->tracker_controller();
auto tl = m_download->tracker_list();
auto tc = m_download->tracker_controller();
m_canvas->print(2, pos, "Trackers: [Key: %08x] [%s %s %s]",
tl->key(),
tc->is_requesting() ? "req" : " ",
tc->is_promiscuous_mode() ? "prom" : " ",
tc->is_failure_mode() ? "fail" : " ");
tc.is_requesting() ? "req" : " ",
tc.is_promiscuous_mode() ? "prom" : " ",
tc.is_failure_mode() ? "fail" : " ");
++pos;
if (tl->size() == 0 || *m_focus >= tl->size())
@@ -78,39 +42,41 @@ WindowTrackerList::redraw() {
typedef std::pair<unsigned int, unsigned int> Range;
Range range = rak::advance_bidirectional<unsigned int>(0, *m_focus, tl->size(), (m_canvas->height() - 1) / 2);
unsigned int group = tl->at(range.first)->group();
unsigned int group = tl->at(range.first).group();
while (range.first != range.second) {
torrent::Tracker* tracker = tl->at(range.first);
auto tracker = tl->at(range.first);
if (tracker->group() == group)
if (tracker.group() == group)
m_canvas->print(0, pos, "%2i:", group++);
m_canvas->print(4, pos++, "%s",
tracker->url().c_str());
tracker.url().c_str());
if (pos < m_canvas->height()) {
const char* state;
if (tracker->is_busy_not_scrape())
if (tracker.is_busy_not_scrape())
state = "req ";
else if (tracker->is_busy())
else if (tracker.is_busy())
state = "scr ";
else
state = " ";
auto tracker_state = tracker.state();
m_canvas->print(0, pos++, "%s Id: %s Counters: %uf / %us (%u) %s S/L/D: %u/%u/%u (%u/%u)",
state,
rak::copy_escape_html(tracker->tracker_id()).c_str(),
tracker->failed_counter(),
tracker->success_counter(),
tracker->scrape_counter(),
tracker->is_usable() ? " on" : tracker->is_enabled() ? "err" : "off",
tracker->scrape_complete(),
tracker->scrape_incomplete(),
tracker->scrape_downloaded(),
tracker->latest_new_peers(),
tracker->latest_sum_peers());
rak::copy_escape_html(tracker.tracker_id()).c_str(),
tracker_state.failed_counter(),
tracker_state.success_counter(),
tracker_state.scrape_counter(),
tracker.is_usable() ? " on" : tracker.is_enabled() ? "err" : "off",
tracker_state.scrape_complete(),
tracker_state.scrape_incomplete(),
tracker_state.scrape_downloaded(),
tracker_state.latest_new_peers(),
tracker_state.latest_sum_peers());
}
if (range.first == *m_focus) {
@@ -118,7 +84,7 @@ WindowTrackerList::redraw() {
m_canvas->set_attr(4, pos - 1, m_canvas->width(), is_focused() ? A_REVERSE : A_BOLD, COLOR_PAIR(0));
}
if (tracker->is_busy()) {
if (tracker.is_busy()) {
m_canvas->set_attr(0, pos - 2, 4, A_REVERSE, COLOR_PAIR(0));
m_canvas->set_attr(0, pos - 1, 4, A_REVERSE, COLOR_PAIR(0));
}
+1 -1
View File
@@ -64,7 +64,7 @@ Manager::pressed(int key) {
if (m_textInput != NULL)
m_textInput->pressed(key);
else
std::find_if(rbegin(), rend(), std::bind2nd(std::mem_fun(&Bindings::pressed), key));
std::find_if(rbegin(), rend(), [&key](Bindings* bind) { return bind->pressed(key); });
}
}
+7 -4
View File
@@ -38,7 +38,6 @@
#include <functional>
#include <rak/algorithm.h>
#include <rak/functional.h>
#include <rak/path.h>
#include <dirent.h>
@@ -105,7 +104,7 @@ PathInput::receive_do_complete() {
if (r.first == r.second)
return; // Show some nice colors here.
std::string base = rak::make_base<std::string>(r.first, r.second, rak::const_mem_ref(&utils::directory_entry::s_name));
std::string base = rak::make_base<std::string>(r.first, r.second, std::mem_fn(&utils::directory_entry::s_name));
// Clear the path after the cursor to make this code cleaner. It's
// not really nessesary to add the complexity just because someone
@@ -154,8 +153,12 @@ PathInput::range_type
PathInput::find_incomplete(utils::Directory& d, const std::string& f) {
range_type r;
r.first = std::find_if(d.begin(), d.end(), rak::bind2nd(std::ptr_fun(&find_complete_not_compare), f));
r.second = std::find_if(r.first, d.end(), rak::bind2nd(std::ptr_fun(&find_complete_compare), f));
r.first = std::find_if(d.begin(), d.end(), [f](const utils::directory_entry& de) {
return find_complete_not_compare(de, f);
});
r.second = std::find_if(r.first, d.end(), [f](const utils::directory_entry& de) {
return find_complete_compare(de, f);
});
return r;
}
+9 -46
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"
#define __STDC_FORMAT_MACROS
@@ -50,7 +14,6 @@
#include <torrent/poll.h>
#include <torrent/data/chunk_utils.h>
#include <torrent/utils/log.h>
#include <rak/functional.h>
#include <rak/error_number.h>
#ifdef HAVE_BACKTRACE
@@ -136,7 +99,7 @@ load_session_torrents() {
// Replace with session torrent flag.
f->set_session(true);
f->set_init_load(true);
f->slot_finished(std::bind(&rak::call_delete_func<core::DownloadFactory>, f));
f->slot_finished([f](){ delete f; });
f->load(entries.path() + first->s_name);
f->commit();
}
@@ -151,7 +114,7 @@ load_arg_torrents(char** first, char** last) {
// Replace with session torrent flag.
f->set_start(true);
f->set_init_load(true);
f->slot_finished(std::bind(&rak::call_delete_func<core::DownloadFactory>, f));
f->slot_finished([f](){ delete f; });
f->load(*first);
f->commit();
}
@@ -195,7 +158,7 @@ main(int argc, char** argv) {
torrent::log_initialize();
control = new Control;
unsigned int random_seed = cachedTime.seconds() ^ cachedTime.usec() ^ (getpid() << 16) ^ getppid();
srandom(random_seed);
@@ -219,7 +182,7 @@ main(int argc, char** argv) {
// platforms that do not properly pass signals to the target
// threads. Use '--enable-interrupt-socket' when configuring
// LibTorrent to enable this workaround.
if (torrent::thread_base::should_handle_sigusr1())
if (torrent::utils::Thread::should_handle_sigusr1())
SignalHandler::set_handler(SIGUSR1, std::bind(&do_nothing));
torrent::log_add_group_output(torrent::LOG_NOTICE, "important");
@@ -269,7 +232,7 @@ main(int argc, char** argv) {
"method.insert = event.download.closed,multi|rlookup|static\n"
"method.insert = event.download.resumed,multi|rlookup|static\n"
"method.insert = event.download.paused,multi|rlookup|static\n"
"method.insert = event.download.finished,multi|rlookup|static\n"
"method.insert = event.download.hash_done,multi|rlookup|static\n"
"method.insert = event.download.hash_failed,multi|rlookup|static\n"
@@ -494,7 +457,7 @@ main(int argc, char** argv) {
rpc::commands.call_catch("event.system.startup_done", rpc::make_target(), "startup_done", "System startup_done event action failed: ");
torrent::thread_base::event_loop(torrent::main_thread());
torrent::utils::Thread::event_loop(torrent::main_thread());
control->core()->download_list()->session_save();
control->cleanup();
@@ -525,7 +488,7 @@ main(int argc, char** argv) {
}
void
handle_sigbus(int signum, siginfo_t* sa, void* ptr) {
handle_sigbus(int signum, siginfo_t* sa, [[maybe_unused]] void* ptr) {
if (signum != SIGBUS)
do_panic(signum);
@@ -605,7 +568,7 @@ do_panic(int signum) {
std::stringstream output;
output << "Caught " << SignalHandler::as_string(signum) << ", dumping stack:" << std::endl;
#ifdef HAVE_BACKTRACE
void* stackPtrs[20];
@@ -619,7 +582,7 @@ do_panic(int signum) {
#else
output << "Stack dump not enabled." << std::endl;
#endif
if (signum == SIGBUS)
output << "A bus error probably means you ran out of diskspace." << std::endl;
+1 -1
View File
@@ -88,7 +88,7 @@ bool
OptionParser::has_flag(char flag, int argc, char** argv) {
char options[3] = { '-', flag, '\0' };
return std::find_if(argv, argv + argc, std::not1(std::bind1st(std::ptr_fun(&std::strcmp), options))) != argv + argc;
return std::find_if(argv, argv + argc, [&options](char* c) { return std::strcmp(c, options) == 0; }) != argv + argc;
}
std::string
+1 -37
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 "core/download.h"
@@ -45,7 +9,7 @@
template const torrent::Object func_name<target_type>(command_base* rawCommand, target_type target, const torrent::Object& args); \
template const torrent::Object func_name<core::Download*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
template const torrent::Object func_name<torrent::Peer*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
template const torrent::Object func_name<torrent::Tracker*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
template const torrent::Object func_name<torrent::tracker::Tracker*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
template const torrent::Object func_name<torrent::File*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
template const torrent::Object func_name<torrent::FileListIterator*>(command_base* rawCommand, target_type target, const torrent::Object& args);
+12 -56
View File
@@ -1,46 +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_RPC_COMMAND_H
#define RTORRENT_RPC_COMMAND_H
#include <functional>
#include <limits>
#include <torrent/object.h>
#include <torrent/common.h>
#include <torrent/object.h>
#include <torrent/data/file_list_iterator.h>
@@ -49,18 +12,11 @@ namespace core {
class Download;
}
namespace torrent {
class File;
class FileListIterator;
class Peer;
class Tracker;
}
namespace rpc {
template <typename Target>
struct target_wrapper {
typedef Target target_type;
typedef Target target_type;
typedef Target cleaned_type;
};
@@ -68,7 +24,7 @@ template <>
struct target_wrapper<void> {
struct no_type {};
typedef void target_type;
typedef void target_type;
typedef no_type* cleaned_type;
};
@@ -127,7 +83,7 @@ public:
typedef const torrent::Object (*file_slot) (command_base*, torrent::File*, const torrent::Object&);
typedef const torrent::Object (*file_itr_slot) (command_base*, torrent::FileListIterator*, const torrent::Object&);
typedef const torrent::Object (*peer_slot) (command_base*, torrent::Peer*, const torrent::Object&);
typedef const torrent::Object (*tracker_slot) (command_base*, torrent::Tracker*, const torrent::Object&);
typedef const torrent::Object (*tracker_slot) (command_base*, torrent::tracker::Tracker*, const torrent::Object&);
typedef const torrent::Object (*download_pair_slot) (command_base*, core::Download*, core::Download*, const torrent::Object&);
@@ -146,10 +102,10 @@ public:
struct stack_type {
torrent::Object* begin() { return reinterpret_cast<torrent::Object*>(buffer); }
torrent::Object* end() { return reinterpret_cast<torrent::Object*>(buffer) + max_arguments; }
const torrent::Object* begin() const { return reinterpret_cast<const torrent::Object*>(buffer); }
const torrent::Object* end() const { return reinterpret_cast<const torrent::Object*>(buffer) + max_arguments; }
torrent::Object& operator [] (unsigned int idx) { return *(begin() + idx); }
const torrent::Object& operator [] (unsigned int idx) const { return *(begin() + idx); }
@@ -176,10 +132,10 @@ public:
static void pop_stack(stack_type* stack, torrent::Object* last_stack);
template <typename T>
void set_function(T s, int value = command_base_is_valid<T>::value) { _pod<T>() = s; }
void set_function(T s, [[maybe_unused]] int value = command_base_is_valid<T>::value) { _pod<T>() = s; }
template <command_base_call_type T>
void set_function_2(typename command_base_is_type<T>::type s, int value = command_base_is_valid<typename command_base_is_type<T>::type>::value) {
void set_function_2(typename command_base_is_type<T>::type s, [[maybe_unused]] int value = command_base_is_valid<typename command_base_is_type<T>::type>::value) {
_pod<typename command_base_is_type<T>::type>() = s;
}
@@ -228,7 +184,7 @@ is_target_compatible(const target_type& target) { return target.first == target_
inline bool is_target_pair(const target_type& target) { return target.first >= command_base::target_download_pair; }
template <typename T> inline T
get_target_cast(target_type target, int type = target_type_id<T>::value) { return (T)target.second; }
get_target_cast(target_type target, [[maybe_unused]] int type = target_type_id<T>::value) { return (T)target.second; }
inline target_type get_target_left(const target_type& target) { return target_type(target.first - 5, target.second); }
inline target_type get_target_right(const target_type& target) { return target_type(target.first - 5, target.third); }
@@ -251,7 +207,7 @@ command_base::_call(command_base* cmd, target_type target, Args args) {
template <> struct command_base_is_valid<func_type<target_type>::type> { static const int value = 1; }; \
template <> struct command_base_is_valid<func_type<core::Download*>::type> { static const int value = 1; }; \
template <> struct command_base_is_valid<func_type<torrent::Peer*>::type> { static const int value = 1; }; \
template <> struct command_base_is_valid<func_type<torrent::Tracker*>::type> { static const int value = 1; }; \
template <> struct command_base_is_valid<func_type<torrent::tracker::Tracker*>::type> { static const int value = 1; }; \
template <> struct command_base_is_valid<func_type<torrent::File*>::type> { static const int value = 1; }; \
template <> struct command_base_is_valid<func_type<torrent::FileListIterator*>::type> { static const int value = 1; };
@@ -268,8 +224,8 @@ COMMAND_BASE_TEMPLATE_TYPE(command_list_function, torrent::Object (T, const to
template <> struct command_base_is_type<func_name<target_type> > { static const int value = 1; typedef func_type<target_type>::type type; }; \
template <> struct command_base_is_type<func_name<core::Download*> > { static const int value = 1; typedef func_type<core::Download*>::type type; }; \
template <> struct command_base_is_type<func_name<torrent::Peer*> > { static const int value = 1; typedef func_type<torrent::Peer*>::type type; }; \
template <> struct command_base_is_type<func_name<torrent::Tracker*> > { static const int value = 1; typedef func_type<torrent::Tracker*>::type type; }; \
template <> struct command_base_is_type<func_name<torrent::File*> > { static const int value = 1; typedef func_type<torrent::File*>::type type; }; \
template <> struct command_base_is_type<func_name<torrent::tracker::Tracker*> > { static const int value = 1; typedef func_type<torrent::tracker::Tracker*>::type type; }; \
template <> struct command_base_is_type<func_name<torrent::File*> > { static const int value = 1; typedef func_type<torrent::File*>::type type; }; \
template <> struct command_base_is_type<func_name<torrent::FileListIterator*> > { static const int value = 1; typedef func_type<torrent::FileListIterator*>::type type; };
COMMAND_BASE_TEMPLATE_CALL(command_base_call, command_function);
+4 -38
View File
@@ -1,42 +1,8 @@
// 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_RPC_COMMAND_IMPL_H
#define RTORRENT_RPC_COMMAND_IMPL_H
#include "rpc/command.h"
namespace rpc {
//template <> struct target_type_id<command_base::generic_slot> { static const int value = command_base::target_generic; };
@@ -54,7 +20,7 @@ template <> struct target_type_id<> { static const in
template <> struct target_type_id<target_type> { static const int value = command_base::target_any; static const int proper_type = 1; };
template <> struct target_type_id<core::Download*> { static const int value = command_base::target_download; static const int proper_type = 1; };
template <> struct target_type_id<torrent::Peer*> { static const int value = command_base::target_peer; static const int proper_type = 1; };
template <> struct target_type_id<torrent::Tracker*> { static const int value = command_base::target_tracker; static const int proper_type = 1; };
template <> struct target_type_id<torrent::tracker::Tracker*> { static const int value = command_base::target_tracker; static const int proper_type = 1; };
template <> struct target_type_id<torrent::File*> { static const int value = command_base::target_file; static const int proper_type = 1; };
template <> struct target_type_id<torrent::FileListIterator*> { static const int value = command_base::target_file_itr; static const int proper_type = 1; };
@@ -63,7 +29,7 @@ template <> struct target_type_id<core::Download*, core::Download*> { static con
template <> inline bool
is_target_compatible<target_type>(const target_type& target) { return true; }
template <> inline bool
is_target_compatible<torrent::File*>(const target_type& target) { return target.first == command_base::target_file || command_base::target_file_itr; }
is_target_compatible<torrent::File*>(const target_type& target) { return target.first == command_base::target_file || target.first == command_base::target_file_itr; }
template <> inline target_type
get_target_cast<target_type>(target_type target, int type) { return target; }
+11 -45
View File
@@ -36,7 +36,6 @@
#include "config.h"
#include <vector>
#include <torrent/exceptions.h>
#include <torrent/object.h>
#include <torrent/data/file_list_iterator.h>
@@ -49,57 +48,27 @@
#include "command.h"
#include "command_map.h"
// For XMLRPC stuff, clean up.
#include "xmlrpc.h"
#include "rpc_manager.h"
#include "parse_commands.h"
namespace rpc {
command_base::stack_type command_base::current_stack;
CommandMap::~CommandMap() {
std::vector<const char*> keys;
for (iterator itr = base_type::begin(), last = base_type::end(); itr != last; itr++) {
// if (!(itr->second.m_flags & flag_dont_delete))
// delete itr->second.m_variable;
if (itr->second.m_flags & flag_delete_key)
keys.push_back(itr->first);
}
for (std::vector<const char*>::iterator itr = keys.begin(), last = keys.end(); itr != last; itr++)
delete [] *itr;
}
CommandMap::iterator
CommandMap::insert(key_type key, int flags, const char* parm, const char* doc) {
CommandMap::insert(const key_type& key, int flags, const char* parm, const char* doc) {
iterator itr = base_type::find(key);
if (itr != base_type::end())
throw torrent::internal_error("CommandMap::insert(...) tried to insert an already existing key.");
// TODO: This is not honoring the public_xmlrpc flags!!!
if (rpc::xmlrpc.is_valid() && (flags & flag_public_xmlrpc))
// if (rpc::xmlrpc.is_valid())
rpc::xmlrpc.insert_command(key, parm, doc);
if (rpc::rpc.is_initialized() && (flags & flag_public_rpc))
rpc::rpc.insert_command(key.c_str(), parm, doc);
return base_type::insert(itr, value_type(key, command_map_data_type(flags, parm, doc)));
}
// void
// CommandMap::insert(key_type key, const command_map_data_type src) {
// iterator itr = base_type::find(key);
// if (itr != base_type::end())
// throw torrent::internal_error("CommandMap::insert(...) tried to insert an already existing key.");
// itr = base_type::insert(itr, value_type(key, command_map_data_type(src.m_variable, src.m_flags | flag_dont_delete, src.m_parm, src.m_doc)));
// // We can assume all the slots are the same size.
// itr->second.m_anySlot = src.m_anySlot;
// }
void
CommandMap::erase(iterator itr) {
if (itr == end())
@@ -112,14 +81,11 @@ CommandMap::erase(iterator itr) {
// if (!(itr->second.m_flags & flag_dont_delete))
// delete itr->second.m_variable;
const char* key = itr->second.m_flags & flag_delete_key ? itr->first : NULL;
base_type::erase(itr);
delete [] key;
}
void
CommandMap::create_redirect(key_type key_new, key_type key_dest, int flags) {
CommandMap::create_redirect(const key_type& key_new, const key_type& key_dest, int flags) {
iterator new_itr = base_type::find(key_new);
iterator dest_itr = base_type::find(key_dest);
@@ -135,11 +101,11 @@ CommandMap::create_redirect(key_type key_new, key_type key_dest, int flags) {
dest_itr->second.m_flags |= flag_has_redirects;
flags |= dest_itr->second.m_flags & ~(flag_delete_key | flag_has_redirects | flag_public_xmlrpc);
flags |= dest_itr->second.m_flags & ~(flag_has_redirects | flag_public_rpc);
// TODO: This is not honoring the public_xmlrpc flags!!!
if (rpc::xmlrpc.is_valid() && (flags & flag_public_xmlrpc))
rpc::xmlrpc.insert_command(key_new, dest_itr->second.m_parm, dest_itr->second.m_doc);
if (rpc::rpc.is_initialized() && (flags & flag_public_rpc))
rpc::rpc.insert_command(key_new.c_str(), dest_itr->second.m_parm, dest_itr->second.m_doc);
iterator itr = base_type::insert(base_type::end(),
value_type(key_new, command_map_data_type(flags,
@@ -152,7 +118,7 @@ CommandMap::create_redirect(key_type key_new, key_type key_dest, int flags) {
}
const CommandMap::mapped_type
CommandMap::call_catch(key_type key, target_type target, const mapped_type& args, const char* err) {
CommandMap::call_catch(const key_type& key, const target_type& target, const mapped_type& args, const char* err) {
try {
return call_command(key, args, target);
} catch (torrent::input_error& e) {
@@ -162,7 +128,7 @@ CommandMap::call_catch(key_type key, target_type target, const mapped_type& args
}
const CommandMap::mapped_type
CommandMap::call_command(key_type key, const mapped_type& arg, target_type target) {
CommandMap::call_command(const key_type& key, const mapped_type& arg, const target_type& target) {
iterator itr = base_type::find(key);
if (itr == base_type::end())
@@ -172,7 +138,7 @@ CommandMap::call_command(key_type key, const mapped_type& arg, target_type targe
}
const CommandMap::mapped_type
CommandMap::call_command(iterator itr, const mapped_type& arg, target_type target) {
CommandMap::call_command(iterator itr, const mapped_type& arg, const target_type& target) {
return itr->second.m_anySlot(&itr->second.m_variable, target, arg);
}
+19 -63
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_RPC_COMMAND_MAP_H
#define RTORRENT_RPC_COMMAND_MAP_H
@@ -46,10 +10,6 @@
namespace rpc {
struct command_map_comp : public std::binary_function<const char*, const char*, bool> {
bool operator () (const char* arg1, const char* arg2) const { return std::strcmp(arg1, arg2) < 0; }
};
struct command_map_data_type {
// Some commands will need to share data, like get/set a variable. So
// instead of using a single virtual member function, each command
@@ -63,7 +23,7 @@ struct command_map_data_type {
command_map_data_type(const command_map_data_type& src) :
m_variable(src.m_variable), m_anySlot(src.m_anySlot),
m_flags(src.m_flags), m_parm(src.m_parm), m_doc(src.m_doc) {}
command_base m_variable;
command_base::any_slot m_anySlot;
@@ -73,9 +33,9 @@ struct command_map_data_type {
const char* m_doc;
};
class CommandMap : public std::map<const char*, command_map_data_type, command_map_comp> {
class CommandMap : public std::map<std::string, command_map_data_type> {
public:
typedef std::map<const char*, command_map_data_type, command_map_comp> base_type;
typedef std::map<std::string, command_map_data_type> base_type;
typedef torrent::Object mapped_type;
typedef mapped_type::value_type mapped_value_type;
@@ -90,8 +50,7 @@ public:
using base_type::find;
static const int flag_dont_delete = 0x1;
static const int flag_delete_key = 0x2;
static const int flag_public_xmlrpc = 0x4;
static const int flag_public_rpc = 0x4;
static const int flag_modifiable = 0x10;
static const int flag_is_redirect = 0x20;
static const int flag_has_redirects = 0x40;
@@ -101,39 +60,36 @@ public:
static const int flag_tracker_target = 0x400;
CommandMap() {}
~CommandMap();
bool has(const char* key) const { return base_type::find(key) != base_type::end(); }
bool has(const std::string& key) const { return has(key.c_str()); }
bool has(const std::string& key) const { return base_type::find(key) != base_type::end(); }
bool is_modifiable(const_iterator itr) { return itr != end() && (itr->second.m_flags & flag_modifiable); }
iterator insert(key_type key, int flags, const char* parm, const char* doc);
iterator insert(const key_type& key, int flags, const char* parm, const char* doc);
template <typename T, typename Slot>
void
insert_slot(key_type key, Slot variable, command_base::any_slot targetSlot, int flags, const char* parm, const char* doc) {
insert_slot(const key_type& key, Slot variable, command_base::any_slot target_slot, int flags, const char* parm, const char* doc) {
iterator itr = insert(key, flags, parm, doc);
itr->second.m_variable.set_function<T>(variable);
itr->second.m_anySlot = targetSlot;
itr->second.m_anySlot = target_slot;
}
// void insert(key_type key, const command_map_data_type src);
void erase(iterator itr);
void create_redirect(key_type key_new, key_type key_dest, int flags);
void create_redirect(const key_type& key_new, const key_type& key_dest, int flags);
const mapped_type call(key_type key, const mapped_type& args = mapped_type());
const mapped_type call(key_type key, target_type target, const mapped_type& args = mapped_type()) { return call_command(key, args, target); }
const mapped_type call_catch(key_type key, target_type target, const mapped_type& args = mapped_type(), const char* err = "Command failed: ");
const mapped_type call(const key_type& key, const mapped_type& args = mapped_type());
const mapped_type call(const key_type& key, const target_type& target, const mapped_type& args = mapped_type()) { return call_command(key, args, target); }
const mapped_type call_catch(const key_type& key, const target_type& target, const mapped_type& args = mapped_type(), const char* err = "Command failed: ");
const mapped_type call_command (key_type key, const mapped_type& arg, target_type target = target_type((int)command_base::target_generic, NULL));
const mapped_type call_command (iterator itr, const mapped_type& arg, target_type target = target_type((int)command_base::target_generic, NULL));
const mapped_type call_command (const key_type& key, const mapped_type& arg, const target_type& target = target_type((int)command_base::target_generic, NULL));
const mapped_type call_command (iterator itr, const mapped_type& arg, const target_type& target = target_type((int)command_base::target_generic, NULL));
const mapped_type call_command_d(key_type key, core::Download* download, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_download, download)); }
const mapped_type call_command_p(key_type key, torrent::Peer* peer, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_peer, peer)); }
const mapped_type call_command_t(key_type key, torrent::Tracker* tracker, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_tracker, tracker)); }
const mapped_type call_command_f(key_type key, torrent::File* file, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_file, file)); }
const mapped_type call_command_d(const key_type& key, core::Download* download, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_download, download)); }
const mapped_type call_command_p(const key_type& key, torrent::Peer* peer, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_peer, peer)); }
const mapped_type call_command_t(const key_type& key, torrent::tracker::Tracker* tracker, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_tracker, tracker)); }
const mapped_type call_command_f(const key_type& key, torrent::File* file, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_file, file)); }
private:
CommandMap(const CommandMap&);
@@ -175,7 +131,7 @@ create_object_list(const torrent::Object& o1, const torrent::Object& o2, const t
}
inline const CommandMap::mapped_type
CommandMap::call(key_type key, const mapped_type& args) {
CommandMap::call(const key_type& key, const mapped_type& args) {
return call_command(key, args, make_target());
}
+3 -4
View File
@@ -39,7 +39,6 @@
#include <algorithm>
#include <cstdlib>
#include <time.h>
#include <rak/functional.h>
#include <rak/string_manip.h>
#include <torrent/exceptions.h>
@@ -50,12 +49,12 @@
namespace rpc {
CommandScheduler::~CommandScheduler() {
std::for_each(begin(), end(), rak::call_delete<CommandSchedulerItem>());
std::for_each(begin(), end(), [](CommandSchedulerItem* item) { delete item; });
}
CommandScheduler::iterator
CommandScheduler::find(const std::string& key) {
return std::find_if(begin(), end(), rak::equal(key, std::mem_fun(&CommandSchedulerItem::key)));
return std::find_if(begin(), end(), [key](CommandSchedulerItem* item) { return key == item->key(); });
}
CommandScheduler::iterator
@@ -100,7 +99,7 @@ CommandScheduler::call_item(value_type item) {
rpc::call_object(item->command());
} catch (torrent::input_error& e) {
if (m_slotErrorMessage.is_valid())
if (m_slotErrorMessage)
m_slotErrorMessage("Scheduled command failed: " + item->key() + ": " + e.what());
}
+2 -3
View File
@@ -40,7 +40,6 @@
#include <cstdint>
#include <vector>
#include <string>
#include <rak/functional_fun.h>
namespace torrent {
class Object;
@@ -52,7 +51,7 @@ class CommandSchedulerItem;
class CommandScheduler : public std::vector<CommandSchedulerItem*> {
public:
typedef rak::function1<void, const std::string&> SlotString;
typedef std::function<void (const std::string&)> SlotString;
typedef std::pair<int, int> Time;
typedef std::vector<CommandSchedulerItem*> base_type;
@@ -63,7 +62,7 @@ public:
CommandScheduler() {}
~CommandScheduler();
void set_slot_error_message(SlotString::base_type* s) { m_slotErrorMessage.set(s); }
void set_slot_error_message(SlotString s) { m_slotErrorMessage = s; }
// slot_error_message or something.
+244
View File
@@ -0,0 +1,244 @@
#include "config.h"
#include "rpc/jsonrpc.h"
#include <cstdint>
#include <string>
#include <torrent/common.h>
#include <torrent/torrent.h>
#include "thread_base.h"
#include "rpc/rpc_manager.h"
#include "rpc/command.h"
#include "rpc/command_map.h"
#include "rpc/nlohmann/json.h"
#include "rpc/parse_commands.h"
#include "torrent/exceptions.h"
#include "torrent/object.h"
#include "utils/functional.h"
namespace rpc {
// Taken from https://www.jsonrpc.org/specification
constexpr int JSONRPC_PARSE_ERROR = -32700;
constexpr int JSONRPC_INVALID_REQUEST_ERROR = -32600;
constexpr int JSONRPC_METHOD_NOT_FOUND_ERROR = -32601;
constexpr int JSONRPC_INVALID_PARAMS_ERROR = -32602;
constexpr int JSONRPC_INTERNAL_ERROR = -32000;
using json = nlohmann::json;
torrent::Object
json_to_object(const json& value) {
switch (value.type()) {
case json::value_t::number_unsigned:
case json::value_t::number_integer:
return torrent::Object(value.get<int64_t>());
case json::value_t::boolean:
return value.get<bool>() ? torrent::Object(int64_t(1)) : torrent::Object(int64_t(0));
case json::value_t::string:
return torrent::Object(value.get<std::string>());
case json::value_t::array: {
auto array_raw = torrent::Object::create_list();
auto& array = array_raw.as_list();
for (const auto& entry : value) {
array.push_back(json_to_object(entry));
}
return array_raw;
}
case json::value_t::object: {
auto map_raw = torrent::Object::create_map();
auto& map = map_raw.as_map();
for (const auto& entry : value.items()) {
map[entry.key()] = json_to_object(entry.value());
}
return map_raw;
}
case json::value_t::number_float:
// type_name() for floats returns 'number', which is accurate for JSON but misleading
throw torrent::input_error("invalid parameters: unexpected data type float");
default:
throw torrent::input_error("invalid parameters: unexpected data type " + std::string(value.type_name()));
}
}
json
object_to_json(const torrent::Object& object) noexcept {
switch (object.type()) {
case torrent::Object::TYPE_VALUE:
return object.as_value();
case torrent::Object::TYPE_STRING:
return object.as_string();
case torrent::Object::TYPE_LIST: {
json result = json::array();
std::transform(object.as_list().cbegin(), object.as_list().cend(), std::back_inserter(result), [](const torrent::Object& element) {
return object_to_json(element);
});
return result;
}
case torrent::Object::TYPE_MAP: {
json result = json::object();
for (const auto& entry : object.as_map()) {
result.emplace(entry.first, object_to_json(entry.second));
}
return result;
}
case torrent::Object::TYPE_DICT_KEY: {
json result = json::array();
result.push_back(object_to_json(object.as_dict_key()));
const auto& dict_obj = object.as_dict_obj();
if (dict_obj.is_list()) {
std::transform(dict_obj.as_list().cbegin(), dict_obj.as_list().cend(), std::back_inserter(result), [](const torrent::Object& element) {
return object_to_json(element);
});
} else {
result.push_back(object_to_json(dict_obj));
}
return result;
}
default:
return 0;
}
}
json
jsonrpc_call_command(const std::string& method, const json& params) {
if (params.type() == json::value_t::object) {
// Named parameters is valid JSON-RPC, rtorrent just doesn't support it
throw rpc_error(JSONRPC_INVALID_PARAMS_ERROR, "invalid parameter: procedure named parameter not supported");
} else if (params.type() != json::value_t::array) {
throw rpc_error(JSONRPC_INVALID_REQUEST_ERROR, "invalid request: params field must be an array");
}
CommandMap::iterator itr = commands.find(method.c_str());
if (itr == commands.end()) {
throw rpc_error(JSONRPC_METHOD_NOT_FOUND_ERROR, "method not found: " + method);
}
torrent::Object params_object = json_to_object(params);
auto& params_object_list = params_object.as_list();
rpc::target_type target = rpc::make_target();
std::function<void()> deleter = []() {};
utils::scope_guard guard([&deleter]() { deleter(); });
if (!(itr->second.m_flags & CommandMap::flag_no_target)) {
// Provide a blank target if none was provided
if (params_object_list.empty())
params_object_list.push_back("");
if (!params_object_list.begin()->is_string())
throw torrent::input_error("invalid parameters: target must be a string");
RpcManager::object_to_target(params_object_list.begin()->as_string(), itr->second.m_flags, &target, &deleter);
params_object_list.erase(params_object_list.begin());
}
const auto& result = rpc::commands.call_command(itr, params_object, target);
return object_to_json(result);
}
json
json_error(int code, const std::string& msg, json id) {
return json{{"jsonrpc", "2.0"}, {"id", id}, {"error", {{"code", code}, {"message", msg}}}};
}
json
handle_request(const json& request) {
json response = {{"jsonrpc", "2.0"}, {"id", nullptr}};
try {
if (!request["id"].is_number() && !request["id"].is_string() && !request["id"].is_null())
return json_error(JSONRPC_INVALID_REQUEST_ERROR, "request id is invalid type " + std::string(request["id"].type_name()), response["id"]);
response["id"] = request["id"];
if (!request.contains("method") || !request["method"].is_string())
return json_error(JSONRPC_INVALID_REQUEST_ERROR, "method string not present", response["id"]);
if (request.contains("params"))
response["result"] = jsonrpc_call_command(request["method"], request["params"]);
else
response["result"] = jsonrpc_call_command(request["method"], json::array({""}));
return response;
} catch (rpc_error& e) {
return json_error(e.type(), e.what(), response["id"]);
} catch (torrent::input_error& e) {
return json_error(JSONRPC_INVALID_PARAMS_ERROR, e.what(), response["id"]);
} catch (torrent::local_error& e) {
return json_error(JSONRPC_INTERNAL_ERROR, e.what(), response["id"]);
}
}
// Notifications are basically the same as requests, except we can
// just drop the message on the floor if there are any errors
void
handle_notification(const json& request) noexcept {
if (!request.contains("method") || !request["method"].is_string())
return;
try {
if (request.contains("params"))
jsonrpc_call_command(request["method"], request["params"]);
else
jsonrpc_call_command(request["method"], json::array({""}));
} catch (std::exception& e) {
}
}
bool
JsonRpc::process(const char* in_buffer, uint32_t length, slot_write callback) {
json response;
json body;
try {
body = json::parse(in_buffer, in_buffer + length);
switch (body.type()) {
case json::value_t::object: {
if (!body.contains("id")) {
handle_notification(body);
return callback("", 0);
} else {
response = handle_request(body);
}
break;
}
case json::value_t::array: {
// Empty batch requests are invalid as per the spec
if (body.empty()) {
response = json_error(JSONRPC_INVALID_REQUEST_ERROR, "invalid request: empty batch", nullptr);
break;
}
response = json::array();
for (const auto& sub_body : body) {
if (!sub_body.contains("id"))
handle_notification(sub_body);
else
response.push_back(handle_request(sub_body));
}
// This indicates the batch was composed entirely of
// notifications, in which case nothing is returned
if (response.empty())
return callback("", 0);
break;
}
default:
response = json_error(JSONRPC_PARSE_ERROR, "message type " + std::string(body.type_name()) + " unsupported", nullptr);
}
std::string response_str = response.dump();
return callback(response_str.c_str(), response_str.size());
} catch (json::parse_error& e) {
auto err_str = json_error(JSONRPC_PARSE_ERROR, e.what(), nullptr).dump(-1, ' ', false, json::error_handler_t::replace);
return callback(err_str.c_str(), err_str.size());
} catch (json::type_error& e) {
// Type errors may be caused by invalid UTF-8 strings in exception strings, hence the ::replace
auto err_str = json_error(JSONRPC_PARSE_ERROR, e.what(), nullptr).dump(-1, ' ', false, json::error_handler_t::replace);
return callback(err_str.c_str(), err_str.size());
}
}
} // namespace rpc
+24
View File
@@ -0,0 +1,24 @@
#ifndef RTORRENT_RPC_JSONRPC_H
#define RTORRENT_RPC_JSONRPC_H
#include <functional>
#include <cstdint>
namespace rpc {
class JsonRpc {
public:
using slot_write = std::function<bool(const char*, uint32_t)>;
void initialize() {};
void cleanup() {};
bool process(const char* in_buffer, uint32_t length, slot_write callback);
void insert_command(const char* name, const char* parm, const char* doc) {};
};
} // namespace rpc
#endif
+399
View File
@@ -0,0 +1,399 @@
#include "config.h"
#include <fstream>
#include <string>
#include <sys/stat.h>
#include <unistd.h>
#include "rpc/lua.h"
#ifdef HAVE_LUA
#include <lua.hpp>
#endif
#include <rak/error_number.h>
#include <rak/path.h>
#include <rak/string_manip.h>
#include <torrent/object.h>
#include "core/download.h"
#include "rpc/command.h"
#include "rpc/command_map.h"
#include "rpc/parse_commands.h"
#include "rpc/xmlrpc.h"
namespace rpc {
const int LuaEngine::flag_string;
const std::string LuaEngine::module_name = "rtorrent";
#ifdef HAVE_LUA
LuaEngine::LuaEngine() {
m_luaState = luaL_newstate();
luaL_openlibs(m_luaState);
set_package_preload();
}
LuaEngine::~LuaEngine() { lua_close(m_luaState); }
void
LuaEngine::set_package_preload() {
auto l_state = m_luaState;
lua_getglobal(l_state, "package");
lua_getfield(l_state, -1, "preload");
lua_pushcfunction(l_state, LuaEngine::lua_init_module);
lua_setfield(l_state, -2, LuaEngine::module_name.c_str());
lua_pop(l_state, 2);
}
void
check_lua_status(lua_State* l_state, int status) {
if (status != LUA_OK) {
throw torrent::input_error(lua_tostring(l_state, -1));
}
}
std::string
LuaEngine::search_lua_path(lua_State* l_state) {
// Get package.path
lua_getglobal(l_state, "package");
lua_getfield(l_state, -1, "path");
std::string lua_path(lua_tostring(l_state, -1));
lua_pop(l_state, 2);
// Use lambda here to ensure file closes as soon as it goes out of scope
auto file_exists = [](const std::string& path) -> bool {
std::ifstream file(path);
return file.is_open();
};
// Tokenize path using ';' as delimiter
size_t pos = 0, end;
while ((end = lua_path.find(';', pos)) != std::string::npos) {
std::string file_path(lua_path.substr(pos, end - pos));
size_t ppos = 0;
while ((ppos = file_path.find('?')) != std::string::npos) {
file_path.replace(ppos, 1, LuaEngine::module_name);
}
if (file_exists(file_path)) {
return file_path;
}
}
return "";
}
int
LuaEngine::lua_rtorrent_call(lua_State* l_state) {
auto method = lua_tostring(l_state, 1);
lua_remove(l_state, 1);
torrent::Object object;
rpc::target_type target = rpc::make_target();
;
rpc::CommandMap::iterator itr = rpc::commands.find(std::string(method).c_str());
if (itr == rpc::commands.end()) {
throw torrent::input_error("method not found: " + std::string(method));
}
object = lua_callstack_to_object(l_state, itr->second.m_flags, &target);
try {
const auto& result = rpc::commands.call_command(itr, object, target);
object_to_lua(l_state, result);
return 1;
} catch (torrent::base_error& e) {
throw luaL_error(l_state, e.what());
}
}
int
LuaEngine::lua_init_module(lua_State* l_state) {
// Should this throw if it fails to find the file?
auto lua_file = search_lua_path(l_state);
if (!lua_file.empty()) {
check_lua_status(l_state, luaL_loadfile(l_state, lua_file.c_str()));
}
lua_createtable(l_state, 0, 1);
// Assign functions
lua_pushliteral(l_state, "call");
lua_pushcfunction(l_state, LuaEngine::lua_rtorrent_call);
lua_settable(l_state, -3);
if (!lua_file.empty()) {
check_lua_status(l_state, lua_pcall(l_state, 1, 1, 0));
}
return 1;
}
void
object_to_target(const torrent::Object& obj, int call_flags, rpc::target_type* target) {
if (!obj.is_string()) {
throw torrent::input_error("invalid parameters: target must be a string");
}
std::string target_string = obj.as_string();
bool require_index = (call_flags & (CommandMap::flag_tracker_target | CommandMap::flag_file_target));
if (target_string.empty() && !require_index) {
return;
}
// Length of SHA1 hash is 40
if (target_string.size() < 40) {
throw torrent::input_error("invalid parameters: invalid target");
}
char type = 'd';
std::string hash;
std::string index;
const auto& delim_pos = target_string.find_first_of(':', 40);
if (delim_pos == target_string.npos || delim_pos + 2 >= target_string.size()) {
if (require_index) {
throw torrent::input_error("invalid parameters: no index");
}
hash = target_string;
} else {
hash = target_string.substr(0, delim_pos);
type = target_string[delim_pos + 1];
index = target_string.substr(delim_pos + 2);
}
core::Download* download = rpc.slot_find_download()(hash.c_str());
if (download == nullptr)
throw torrent::input_error("invalid parameters: info-hash not found");
try {
switch (type) {
case 'd':
*target = rpc::make_target(download);
break;
case 'f':
*target = rpc::make_target(command_base::target_file, rpc.slot_find_file()(download, std::stoi(std::string(index))));
break;
case 't':
*target =
rpc::make_target(command_base::target_tracker, rpc.slot_find_tracker()(download, std::stoi(std::string(index))));
break;
case 'p': {
if (index.size() < 40) {
throw torrent::input_error("Not a hash string.");
}
torrent::HashString hash;
torrent::hash_string_from_hex_c_str(index.c_str(), hash);
*target = rpc::make_target(command_base::target_peer, rpc.slot_find_peer()(download, hash));
break;
}
default:
throw torrent::input_error("invalid parameters: unexpected target type");
}
} catch (const std::logic_error&) {
throw torrent::input_error("invalid parameters: invalid index");
}
}
void
object_to_lua(lua_State* l_state, torrent::Object const& object) {
// Converts an object to a single Lua stack object
switch (object.type()) {
case torrent::Object::TYPE_VALUE:
lua_pushnumber(l_state, static_cast<double>(object.as_value()));
break;
case torrent::Object::TYPE_NONE:
lua_pushnil(l_state);
break;
case torrent::Object::TYPE_STRING:
lua_pushstring(l_state, object.as_string().c_str());
break;
case torrent::Object::TYPE_LIST: {
int index = 1;
auto object_list = object.as_list();
lua_createtable(l_state, static_cast<int>(object_list.size()), 0);
int table_idx = lua_gettop(l_state);
for (const auto& itr : object_list) {
object_to_lua(l_state, itr);
lua_rawseti(l_state, table_idx, lua_Integer(index++));
}
break;
}
case torrent::Object::TYPE_MAP: {
auto object_map = object.as_map();
lua_createtable(l_state, 0, static_cast<int>(object_map.size()));
int table_idx = lua_gettop(l_state);
for (const auto& itr : object_map) {
object_to_lua(l_state, itr.second);
lua_pushlstring(l_state, itr.first.c_str(), itr.first.size());
lua_rawset(l_state, table_idx);
}
break;
}
default:
lua_pushnumber(l_state, lua_Number(object.type()));
break;
}
}
torrent::Object
lua_to_object(lua_State* l_state) {
switch (lua_type(l_state, -1)) {
case LUA_TNUMBER:
return torrent::Object(lua_tonumber(l_state, -1));
case LUA_TSTRING:
return torrent::Object(lua_tostring(l_state, -1));
case LUA_TBOOLEAN:
return torrent::Object(lua_toboolean(l_state, -1));
case LUA_TNIL:
return torrent::Object((torrent::Object::value_type)0);
case LUA_TTABLE: {
lua_pushnil(l_state);
int status = lua_next(l_state, -2);
if (status == 0)
return torrent::Object::create_map();
// If the table starts at 1, assume it's an array
if (lua_isnumber(l_state, -2) && (lua_tonumber(l_state, -2) == 1)) {
torrent::Object list = torrent::Object::create_list();
list.insert_back(lua_to_object(l_state));
lua_pop(l_state, 1);
while (lua_next(l_state, -2) != 0) {
list.insert_back(lua_to_object(l_state));
lua_pop(l_state, 1);
}
return list;
} else {
torrent::Object map = torrent::Object::create_map();
// Reset the stack and start from the first element
lua_pop(l_state, 2);
lua_pushnil(l_state);
while (lua_next(l_state, -2) != 0) {
std::string key;
switch (lua_type(l_state, -2)) {
case LUA_TSTRING:
key = lua_tostring(l_state, -2);
break;
default:
// Bencode dictionaries require string keys, but naively
// calling lua_tostring will auto-convert any other object
// (particularly numbers) to strings in-place, which would
// throw off lua_next, so we copy the value and only then
// get the string.
// https://www.lua.org/manual/5.3/manual.html#lua_tolstring
lua_pushvalue(l_state, -2);
key = lua_tostring(l_state, -1);
lua_pop(l_state, 1);
break;
}
map.insert_key(key, lua_to_object(l_state));
lua_pop(l_state, 1);
}
return map;
}
return torrent::Object(lua_tostring(l_state, -1));
}
default:
std::string result = lua_tostring(l_state, -1);
lua_pop(l_state, 1);
return torrent::Object(result);
}
}
torrent::Object
lua_callstack_to_object(lua_State* l_state, int command_flags, rpc::target_type* target) {
torrent::Object object;
if (lua_gettop(l_state) == 0) {
return torrent::Object();
}
if (!lua_isstring(l_state, 1)) {
throw torrent::input_error("invalid parameters: target must be a string");
}
object_to_target(torrent::Object(lua_tostring(l_state, 1)), command_flags, target);
// start from the second argument since the first is the target
lua_remove(l_state, 1);
if (lua_gettop(l_state) == 0) {
return torrent::Object();
} else {
torrent::Object result = torrent::Object::create_list();
torrent::Object::list_type& list_ref = result.as_list();
while (lua_gettop(l_state) != 0) {
list_ref.insert(list_ref.begin(), lua_to_object(l_state));
lua_remove(l_state, -1);
}
return result;
}
return object;
}
int
lua_rtorrent_call(lua_State* l_state) {
torrent::Object object;
rpc::target_type target = rpc::make_target();
auto method = lua_tostring(l_state, 1);
lua_remove(l_state, 1);
rpc::CommandMap::iterator itr = rpc::commands.find(method);
if (itr == rpc::commands.end()) {
throw torrent::input_error("method not found: " + std::string(method));
}
object = lua_callstack_to_object(l_state, itr->second.m_flags, &target);
try {
const auto& result = rpc::commands.call_command(itr, object, target);
object_to_lua(l_state, result);
return 1;
} catch (torrent::base_error& e) {
throw luaL_error(l_state, e.what());
}
}
torrent::Object
execute_lua(LuaEngine* engine, rpc::target_type target_type, torrent::Object const& raw_args, int flags) {
size_t lua_argc = 1; // Target is always present, even if empty
lua_State* l_state = engine->state();
std::string target_string;
switch (target_type.first) {
case (command_base::target_download):
core::Download* dl_target = (core::Download*)target_type.second;
torrent::HashString infohash = dl_target->info()->hash();
target_string = rak::transform_hex_str(infohash);
break;
}
switch (raw_args.type()) {
case torrent::Object::TYPE_LIST: {
const torrent::Object::list_type& args = raw_args.as_list();
if (flags & LuaEngine::flag_string) {
check_lua_status(l_state, luaL_loadstring(l_state, args.begin()->as_string().c_str()));
} else {
check_lua_status(l_state, luaL_loadfile(l_state, args.begin()->as_string().c_str()));
}
object_to_lua(l_state, target_string);
for (torrent::Object::list_const_iterator itr = std::next(args.begin()), last = args.end(); itr != last; itr++) {
object_to_lua(l_state, *itr);
}
lua_argc += args.size() - 1;
break;
}
case torrent::Object::TYPE_STRING: {
const torrent::Object::string_type& target = raw_args.as_string();
if (flags & LuaEngine::flag_string) {
check_lua_status(l_state, luaL_loadstring(l_state, target.c_str()));
} else {
check_lua_status(l_state, luaL_loadfile(l_state, target.c_str()));
}
object_to_lua(l_state, target_string);
break;
}
default:
throw torrent::input_error("execute_lua(...): cannot call lua with arg type " + std::to_string(raw_args.type()));
}
check_lua_status(l_state, lua_pcall(l_state, lua_argc, LUA_MULTRET, 0));
return lua_to_object(l_state);
}
#else
torrent::Object
execute_lua(LuaEngine* engine, torrent::Object const& rawArgs, int flags) {
throw torrent::input_error("Lua support not enabled");
return torrent::Object();
}
LuaEngine::LuaEngine() {}
LuaEngine::~LuaEngine() {}
#endif
} // namespace rpc
+45
View File
@@ -0,0 +1,45 @@
#ifndef RTORRENT_LUA_H
#define RTORRENT_LUA_H
#include "rpc/command.h"
#include <torrent/object.h>
#ifdef HAVE_LUA
#include <lua.hpp>
#endif
namespace rpc {
class LuaEngine {
public:
static const int flag_string = 0x1;
static const std::string module_name;
LuaEngine();
~LuaEngine();
#ifdef HAVE_LUA
// lua_CFunctions
static int lua_init_module(lua_State* l_state);
static int lua_rtorrent_call(lua_State* l_state);
void set_package_preload();
lua_State* state() { return m_luaState; }
private:
static std::string search_lua_path(lua_State* l_state);
lua_State* m_luaState;
#endif
};
torrent::Object execute_lua(LuaEngine* engine, rpc::target_type target, const torrent::Object& raw_args, int flags);
#ifdef HAVE_LUA
int rtorrent_call(lua_State* l_state);
void init_rtorrent_module(lua_State* l_state);
void object_to_lua(lua_State* l_state, torrent::Object const& object);
void check_lua_status(lua_State* l_state, int status);
torrent::Object lua_to_object(lua_State* l_state);
torrent::Object lua_callstack_to_object(lua_State* l_state, int command_flags, rpc::target_type* target);
#endif
} // namespace rpc
#endif
+2
View File
@@ -0,0 +1,2 @@
# third-party library, disable all checks in this folder.
Checks: '-*'
File diff suppressed because it is too large Load Diff
+3 -6
View File
@@ -38,7 +38,6 @@
#include "object_storage.h"
#include "rak/functional.h"
#include "parse.h"
#include "parse_commands.h"
@@ -223,8 +222,7 @@ object_storage::erase_multi_key(const torrent::raw_string& key, const std::strin
if (r_itr == m_rlookup.end())
return;
rlookup_mapped_iterator rm_itr = std::find_if(r_itr->second.begin(), r_itr->second.end(),
rak::equal(key, rak::mem_ptr(&value_type::first)));
rlookup_mapped_iterator rm_itr = std::find_if(r_itr->second.begin(), r_itr->second.end(), [key](value_type* type) { return key == type->first; });
if (rm_itr != r_itr->second.end())
r_itr->second.erase(rm_itr);
@@ -243,8 +241,7 @@ object_storage::set_multi_key_obj(const torrent::raw_string& key, const std::str
if (r_itr == m_rlookup.end())
r_itr = m_rlookup.insert(std::make_pair(cmd_key, rlookup_type::mapped_type())).first;
if (std::find_if(r_itr->second.begin(), r_itr->second.end(),
rak::equal(key, rak::mem_ptr(&value_type::first))) == r_itr->second.end())
if (std::find_if(r_itr->second.begin(), r_itr->second.end(), [key](value_type* type) { return key == type->first; }) == r_itr->second.end())
r_itr->second.push_back(&*itr);
}
@@ -259,7 +256,7 @@ object_storage::rlookup_list(const std::string& cmd_key) {
if (r_itr != m_rlookup.end())
std::transform(r_itr->second.begin(), r_itr->second.end(), std::back_inserter(result),
std::bind(&key_type::c_str, std::bind(rak::mem_ptr(&value_type::first), std::placeholders::_1)));
std::bind(&key_type::c_str, std::bind(std::mem_fn(&value_type::first), std::placeholders::_1)));
return result;
}
+12 -19
View File
@@ -39,30 +39,23 @@
#include <algorithm>
#include <fstream>
#include <string>
#include <rak/functional.h>
#include <functional>
#include <rak/path.h>
#include <torrent/exceptions.h>
#include "parse.h"
#include "parse_commands.h"
#include "rpc/rpc_manager.h"
namespace rpc {
CommandMap commands;
XmlRpc xmlrpc;
ExecFile execFile;
inline bool command_map_is_space(char c) {
return c == ' ' || c == '\t';
}
struct command_map_is_space : std::unary_function<char, bool> {
bool operator () (char c) const {
return c == ' ' || c == '\t';
}
};
struct command_map_is_newline : std::unary_function<char, bool> {
bool operator () (char c) const {
return c == '\n' || c == '\0' || c == ';';
}
};
inline bool command_map_is_newline(char c) {
return c == '\n' || c == '\0' || c == ';';
}
// Only escape eol on odd number of escape characters. We know that
// there can't be any characters in between, so this should work for
@@ -131,7 +124,7 @@ parse_command_name(const char* first, const char* last, char* dest_first, char*
// the code below for both cases.
parse_command_type
parse_command(target_type target, const char* first, const char* last) {
first = std::find_if(first, last, std::not1(command_map_is_space()));
first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); });
if (first == last || *first == '#')
return std::make_pair(torrent::Object(), first);
@@ -139,7 +132,7 @@ parse_command(target_type target, const char* first, const char* last) {
char key[128];
first = parse_command_name(first, last, key, key + 128);
first = std::find_if(first, last, std::not1(command_map_is_space()));
first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); });
if (first == last || *first != '=')
throw torrent::input_error("Could not find '=' in command '" + std::string(key) + "'.");
@@ -150,10 +143,10 @@ parse_command(target_type target, const char* first, const char* last) {
// Find the last character that is part of this command, skipping
// the whitespace at the end. This ensures us that the caller
// doesn't need to do this nor check for junk at the end.
first = std::find_if(first, last, std::not1(command_map_is_space()));
first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); });
if (first != last) {
if (*first != '\n' && *first != ';' && *first != '\0')
if (!command_map_is_newline(*first))
throw torrent::input_error("Junk at end of input.");
first++;
+1 -7
View File
@@ -40,9 +40,8 @@
#include <string>
#include <cstring>
#include "command_map.h"
#include "exec_file.h"
#include "xmlrpc.h"
#include "rpc_manager.h"
namespace core {
class Download;
@@ -50,11 +49,6 @@ namespace core {
namespace rpc {
// Move to another file?
extern CommandMap commands;
extern XmlRpc xmlrpc;
extern ExecFile execFile;
typedef std::pair<torrent::Object, const char*> parse_command_type;
// The generic parse command function, used by the rest. At some point
+166
View File
@@ -0,0 +1,166 @@
#include "config.h"
#include <cstring>
#include <torrent/exceptions.h>
#include "parse_commands.h"
#include "rpc/rpc_manager.h"
namespace rpc {
CommandMap commands;
RpcManager rpc;
ExecFile execFile;
void
RpcManager::object_to_target(const torrent::Object& obj, int call_flags, rpc::target_type* target, std::function<void()>* deleter) {
if (call_flags & CommandMap::flag_no_target)
return;
if (!obj.is_string()) {
throw torrent::input_error("invalid parameters: target must be a string");
}
std::string target_string = obj.as_string();
bool require_index = (call_flags & (CommandMap::flag_tracker_target | CommandMap::flag_file_target));
if (target_string.size() == 0 && !require_index) {
return;
}
// Length of SHA1 hash is 40
if (target_string.size() < 40) {
throw torrent::input_error("invalid parameters: invalid target");
}
char type = 'd';
std::string hash;
std::string index;
const auto& delim_pos = target_string.find_first_of(':', 40);
if (delim_pos == target_string.npos ||
delim_pos + 2 >= target_string.size()) {
if (require_index) {
throw torrent::input_error("invalid parameters: no index");
}
hash = target_string;
} else {
hash = target_string.substr(0, delim_pos);
type = target_string[delim_pos + 1];
index = target_string.substr(delim_pos + 2);
}
core::Download* download = rpc.slot_find_download()(hash.c_str());
if (download == nullptr)
throw torrent::input_error("invalid parameters: info-hash not found");
try {
torrent::tracker::Tracker* tracker;
switch (type) {
case 'd':
*target = rpc::make_target(download);
break;
case 'f':
*target = rpc::make_target(command_base::target_file,
rpc.slot_find_file()(download, std::stoi(std::string(index))));
break;
case 't':
tracker = new torrent::tracker::Tracker(rpc.slot_find_tracker()(download, std::stoi(std::string(index))));
*target = rpc::make_target(command_base::target_tracker, tracker);
*deleter = [tracker]() { delete tracker; };
break;
case 'p': {
if (index.size() < 40) {
throw torrent::input_error("invalid parameters: not a hash string.");
}
torrent::HashString hash;
torrent::hash_string_from_hex_c_str(index.c_str(), hash);
*target = rpc::make_target(command_base::target_peer,
rpc.slot_find_peer()(download, hash));
break;
}
default:
throw torrent::input_error("invalid parameters: unexpected target type");
}
} catch (const std::logic_error&) {
throw torrent::input_error("invalid parameters: invalid index");
}
}
bool
RpcManager::process(RPCType type, const char* in_buffer, uint32_t length, slot_response_callback callback) {
switch (type) {
case RPCType::XML: {
if (m_xmlrpc.is_valid() && rpc::call_command_value("network.rpc.use_xmlrpc")) {
return m_xmlrpc.process(in_buffer, length, callback);
} else {
const std::string response = "<?xml version=\"1.0\"?><methodResponse><fault><struct><member><name>faultCode</name><value><i8>-501</i8></value></member><member><name>faultString</name><value><string>XML-RPC not supported</string></value></member></struct></fault></methodResponse>";
return callback(response.c_str(), response.size());
}
}
case RPCType::JSON: {
if (rpc::call_command_value("network.rpc.use_jsonrpc")) {
return m_jsonrpc.process(in_buffer, length, callback);
} else {
const std::string response = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32601,\"message\":\"JSON-RPC not supported\"},\"id\":null}";
return callback(response.c_str(), response.size());
}
}
}
}
void
RpcManager::initialize() {
m_xmlrpc.initialize();
m_jsonrpc.initialize();
m_initialized = true;
}
void
RpcManager::cleanup() {
m_xmlrpc.cleanup();
m_jsonrpc.cleanup();
}
bool
RpcManager::is_type_enabled(RPCType type) const {
switch (type) {
case RPCType::XML:
return m_is_xmlrpc_enabled;
case RPCType::JSON:
return m_is_jsonrpc_enabled;
}
}
void
RpcManager::set_type_enabled(RPCType type, bool enabled) {
switch (type) {
case RPCType::XML:
m_is_xmlrpc_enabled = enabled;
case RPCType::JSON:
m_is_jsonrpc_enabled = enabled;
}
}
bool
RpcManager::is_initialized() const {
return m_initialized;
}
void
RpcManager::insert_command(const char* name, const char* parm, const char* doc) {
m_xmlrpc.insert_command(name, parm, doc);
m_jsonrpc.insert_command(name, parm, doc);
}
} // namespace rpc
+92
View File
@@ -0,0 +1,92 @@
#ifndef RTORRENT_RPC_MANAGER_H
#define RTORRENT_RPC_MANAGER_H
#include <cstdint>
#include <functional>
#include <torrent/common.h>
#include "rpc/command.h"
#include "rpc/command_map.h"
#include "rpc/exec_file.h"
#include "rpc/jsonrpc.h"
#include "rpc/xmlrpc.h"
namespace core {
class Download;
}
namespace rpc {
extern ExecFile execFile;
extern CommandMap commands;
class rpc_error : public torrent::base_error {
public:
rpc_error(int type, std::string msg) :
m_type(type), m_msg(msg) {}
virtual ~rpc_error() throw() {}
virtual int type() const throw() { return m_type; }
virtual const char* what() const throw() { return m_msg.c_str(); }
private:
int m_type;
std::string m_msg;
};
class RpcManager {
public:
using slot_download = std::function<core::Download*(const char*)>;
using slot_file = std::function<torrent::File*(core::Download*, uint32_t)>;
using slot_tracker = std::function<torrent::tracker::Tracker(core::Download*, uint32_t)>;
using slot_peer = std::function<torrent::Peer*(core::Download*, const torrent::HashString&)>;
using slot_response_callback = std::function<bool(const char*, uint32_t)>;
enum RPCType { XML,
JSON };
RpcManager() = default;
~RpcManager() = default;
void initialize();
void cleanup();
bool is_initialized() const;
int64_t size_limit() { return m_xmlrpc.size_limit(); };
void set_size_limit(uint64_t size) { m_xmlrpc.set_size_limit(size); };
int dialect() { return m_xmlrpc.dialect(); }
void set_dialect(int dialect) { m_xmlrpc.set_dialect(dialect); }
bool is_type_enabled(RPCType type) const;
void set_type_enabled(RPCType type, bool enabled);
bool process(RPCType type, const char* in_buffer, uint32_t length, slot_response_callback callback);
void insert_command(const char* name, const char* parm, const char* doc);
slot_download& slot_find_download() { return m_slot_find_download; }
slot_file& slot_find_file() { return m_slot_find_file; }
slot_tracker& slot_find_tracker() { return m_slot_find_tracker; }
slot_peer& slot_find_peer() { return m_slot_find_peer; }
static void object_to_target(const torrent::Object& obj, int callFlags, rpc::target_type* target, std::function<void()>* deleter);
private:
XmlRpc m_xmlrpc;
JsonRpc m_jsonrpc;
bool m_initialized = false;
bool m_is_jsonrpc_enabled = true;
bool m_is_xmlrpc_enabled = true;
slot_download m_slot_find_download;
slot_file m_slot_find_file;
slot_tracker m_slot_find_tracker;
slot_peer m_slot_find_peer;
};
extern RpcManager rpc;
} // namespace rpc
#endif

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